NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @namespace mediawiki // @name Rust wiki editor shortcuts // @description Configurable keyboard shortcuts for the Rust wiki editor // @version 1.2.2 // @copyright 2020, Aloso (https://openuserjs.org/users/Aloso) // @license MIT // @include https://runrust.miraheze.org/w/index.php?* // @grant none // @updateURL https://openuserjs.org/meta/Aloso/Rust_wiki_editor_shortcuts.meta.js // @downloadURL https://openuserjs.org/install/Aloso/Rust_wiki_editor_shortcuts.user.js // ==/UserScript== // ==OpenUserJS== // @author Aloso // ==/OpenUserJS== // Shortcuts. Each shortcut is a key combination with // meta, ctrl, alt, shift and another key, e.g. // // meta+ctrl+alt+shift+H // // The keys must be written exactly in this order! // Note that these shortcuts override the default browser behavior. // // Don't modify the shortcuts in this file if possible. // Instead, open the browser console (F12) and follow the instructions! // // If I release a new version of this script and you update it, // modifications of this file will be lost. If you use the exported // functions in the browser console, they're persisted in the local storage. let shortcuts = { 'alt+c': ['wrap', { before: '<code>', after: '</code>' }], 'alt+r': ['wrap', { before: '{{rs|', after: '}}' }], 'alt+h': ['wrap', { before: '<syntaxhighlight lang="rust">\n', after: '\n</syntaxhighlight>' }], 'ctrl+i': ['wrap', { before: "''", after: "''" }], 'ctrl+b': ['wrap', { before: "'''", after: "'''" }], 'alt+t': ['wrap', { before: "{{trait|", after: "}}" }], 'alt+s': ['wrap', { before: "{{struct|", after: "}}" }], 'alt+e': ['wrap', { before: "{{enum|", after: "}}" }], 'alt+m': ['wrap', { before: "{{macro|", after: "}}" }], 'alt+y': ['wrap', { before: "{{yes}}", after: "" }], 'alt+n': ['wrap', { before: "{{no}}", after: "" }], 'alt+u': ['wrap', { before: "{{unknown}}", after: "" }], // the above shortcuts can be reversed with the shift key: 'alt+shift+C': ['unwrap', { before: '<code>', after: '</code>' }], 'alt+shift+R': ['unwrap', { before: '{{rs|', after: '}}' }], 'alt+shift+S': ['unwrap', { before: '<syntaxhighlight lang="rust">\n', after: '\n</syntaxhighlight>' }], 'ctrl+shift+I': ['unwrap', { before: "''", after: "''" }], 'ctrl+shift+B': ['unwrap', { before: "'''", after: "'''" }], 'alt+shift+T': ['unwrap', { before: "{{trait|", after: "}}" }], 'alt+shift+S': ['unwrap', { before: "{{struct|", after: "}}" }], 'alt+shift+E': ['unwrap', { before: "{{enum|", after: "}}" }], 'alt+shift+M': ['unwrap', { before: "{{macro|", after: "}}" }], 'alt+shift+Y': ['unwrap', { before: "{{yes}}", after: "" }], 'alt+shift+N': ['unwrap', { before: "{{no}}", after: "" }], 'alt+shift+U': ['unwrap', { before: "{{unknown}}", after: "" }], // add remove an external link: 'alt+l': ['add_external_link', { default_url: '' }], 'alt+shift+L': ['remove_external_link', {}], } // DO NOT modify this: window.addEventListener('load', function() { 'use strict' const ta = document.getElementById('wpTextbox1') if (ta == null) return const actions = { wrap: function(options) { const val = ta.value const start = ta.selectionStart const end = ta.selectionEnd const newVal = val.slice(0, start) + options.before + val.slice(start, end) + options.after + val.slice(end) const newStart = start + options.before.length const newEnd = end + options.before.length ta.value = newVal selectRange(newStart, newEnd) }, unwrap: function(options) { const val = ta.value const start = ta.selectionStart const end = ta.selectionEnd let p0 = val.slice(0, start) const p1 = val.slice(start, end) let p2 = val.slice(end) if (p0.endsWith(options.before)) p0 = p0.slice(0, start - options.before.length) if (p2.startsWith(options.after)) p2 = p2.slice(options.after.length) const newVal = p0 + p1 + p2 const newStart = p0.length const newEnd = p0.length + p1.length ta.value = newVal selectRange(newStart, newEnd) }, add_external_link: function(options) { const val = ta.value const start = ta.selectionStart const end = ta.selectionEnd const url = prompt("External URL:", options.default_url) if (url != null) { actions.wrap({ before: '[' + url + ' ', after: ']' }) } }, remove_external_link: function(options) { const val = ta.value const start = ta.selectionStart const end = ta.selectionEnd const before = val.slice(0, start).match(/\[[^\[\]\s]*?\s?$/)[0] const after = val.slice(end)[0] if (before != null && after === ']') { actions.unwrap({ before: before, after: after }) } }, } function selectRange(start, end) { ta.focus() if (ta.setSelectionRange) { ta.setSelectionRange(start, end); } else if (ta.createTextRange) { const r = ta.createTextRange(); r.collapse(true); r.moveEnd('character', end); r.moveStart('character', start); r.select(); } } const unsafeWin = typeof unsafeWindow === "undefined" ? window : unsafeWindow if (typeof exportFunction === "undefined") { window.exportFunction = function(f) { return f } } unsafeWin.KEY_DEBUG = false if (unsafeWin.localStorage.gm_editor_shortcuts != null) { shortcuts = JSON.parse(unsafeWin.localStorage.gm_editor_shortcuts) } else { unsafeWin.localStorage.gm_editor_shortcuts = JSON.stringify(shortcuts) } function setWrapShortcut(shortcut, before, after) { const existed = shortcut in shortcuts let obj let add_shift_shortcut = false if (typeof before === 'string' && typeof after === 'string') { obj = ['wrap', { before: before, after: after }] if (!existed) add_shift_shortcut = true } else { obj = before } shortcuts[shortcut] = obj console.log('added %c' + shortcut + '%c (' + obj[0] + ')', 'color: #11aaff;', 'color: inherit;') if (add_shift_shortcut) { const keys = shortcut.split('+') if (!keys.includes('shift')) { const last = keys.pop() keys.push('shift', last) shortcuts[keys.join('+')] = ['unwrap', obj[1]] console.log('added %c' + keys.join('+') + '%c (unwrap)', 'color: #11aaff;', 'color: inherit;') } } unsafeWin.localStorage.gm_editor_shortcuts = JSON.stringify(shortcuts) } function removeWrapShortcut() { for (const shortcut of arguments) { delete shortcuts[shortcut] console.log('deleted %c' + shortcut + '%c', 'color: #11aaff;', 'color: inherit;') } unsafeWin.localStorage.gm_editor_shortcuts = JSON.stringify(shortcuts) } function printAllShortcuts() { console.group('%cAvailable keyboard shortcuts:', 'font-family: Hack, Consolas, monospace; font-weight: bold; font-size: 115%;') for (const s of Object.keys(shortcuts)) { const spaces = ' '.slice(s.length) + ' ' if (shortcuts[s][0] === 'wrap' || shortcuts[s][0] === 'unwrap') { let before = shortcuts[s][1].before let after = shortcuts[s][1].after const indent = ' '.repeat(s.length + spaces.length) before = before.replaceAll("\n", "\n" + indent) after = after.replaceAll("\n", "\n" + indent) const color = shortcuts[s][0] === 'wrap' ? '#00ff00' : 'red' console.log(s + spaces + '%c' + before + '%cā%c' + after, 'color: ' + color, 'color: inherit', 'color: ' + color) } else { console.log(s + spaces + shortcuts[s][0]) } } console.groupEnd() console.info('Note: Green means added text, red means removed text.') console.info('More information: https://openuserjs.org/scripts/Aloso/Rust_wiki_editor_shortcuts') } function printHelpInfo() { console.group('%cRust wiki editor shortcuts āā Help', 'font-family: Hack, Consolas, monospace; font-weight: bold; font-size: 115%;') console.log('Enter this to display pressed key shortcuts:\n' + ' %cKEY_DEBUG = true', 'color: #11aaff; font-size: 120%') console.log("To print this help info:\n" + " %chelp()%c", 'color: #11aaff; font-size: 120%', '') console.log('Enter this to list all available shortcuts:\n' + ' %cshowShort()', 'color: #11aaff; font-size: 120%') console.log("To add keyboard shortcuts:\n" + " %csetShort('alt+m', ['unwrap', { before: '{{', after: '}}' }])%c\n" + " > added %calt+m%c (unwrap)\n" + " %csetShort('ctrl+alt+x', 'prefix', 'postfix')%c\n" + " > added %cctrl+alt+x%c (wrap)\n" + " > added %cctrl+alt+shift+x%c (unwrap)", 'color: #11aaff; font-size: 120%', '', 'color: #11aaff;', '', 'color: #11aaff; font-size: 120%', '', 'color: #11aaff;', '', 'color: #11aaff;', '') console.log("To delete keyboard shortcuts:\n" + " %cdelShort('ctrl+alt+x', 'alt+m')%c\n" + " > removed %cctrl+alt+x%c (wrap)\n" + " > removed %calt+m%c (unwrap)", 'color: #11aaff; font-size: 120%', '', 'color: #11aaff;', '', 'color: #11aaff;', '') console.info('More information: https://openuserjs.org/scripts/Aloso/Rust_wiki_editor_shortcuts') console.groupEnd() } unsafeWin.setShort = exportFunction(setWrapShortcut, unsafeWin) unsafeWin.delShort = exportFunction(removeWrapShortcut, unsafeWin) unsafeWin.showShort = exportFunction(printAllShortcuts, unsafeWin) unsafeWin.help = exportFunction(printHelpInfo, unsafeWin) ta.addEventListener('keydown', function(e) { if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { if (e.key === 'Meta' || e.key === 'Control' || e.key === 'Alt' || e.key === 'Shift') return const evt = [] if (e.metaKey) evt.push('meta') if (e.ctrlKey) evt.push('ctrl') if (e.altKey) evt.push('alt') if (e.shiftKey) evt.push('shift') evt.push(e.key) const shortcut = shortcuts[evt.join('+')] if (unsafeWin.KEY_DEBUG) { console.log('pressed %c' + evt.join('+'), 'color: #11aaff;') } if (shortcut != null) { const fn = actions[shortcut[0]] fn(shortcut[1]) e.preventDefault() e.stopPropagation() return false } } }, false) setTimeout(function() { console.clear() printHelpInfo() }, 1600) })