Browse Source

Editor tweaks (#652)

* feat: toggle comments in editor via Ctrl-/

* fix: don't show missing CM commands in hotkeys tab

* feat: add /*commentSelection*/ via Ctrl-Shift-/

* fix: Tab key should use current indent settings

* feat: display current CodeMirror options in editor settings
tophf 6 years ago
parent
commit
0317de19fd

+ 5 - 2
src/_locales/en/messages.yml

@@ -17,6 +17,9 @@ buttonClose:
 buttonConfirmInstallation:
   description: Button to confirm installation of a script.
   message: Confirm installation
+buttonShowEditorState:
+  description: Button to show the list of currently used CodeMirror options.
+  message: Show editor state
 buttonDisable:
   description: Button to disable a script.
   message: Disable
@@ -118,8 +121,8 @@ descCustomCSS:
 descEditorOptions:
   description: Description of editor options JSON section.
   message: >-
-    Custom CodeMirror options in JSON object like {"indentUnit":2, "smartIndent":true}
-    however note that Violentmonkey doesn't support all of them.
+    Custom options for CodeMirror and addons in JSON object like {"indentUnit":2, "smartIndent":true}
+    however note that some of them may not work in Violentmonkey.
     Full list: https://codemirror.net/doc/manual.html#config
 editLabelMeta:
   description: Metadata section in settings tab of script editor.

+ 9 - 1
src/common/ui/code.vue

@@ -51,6 +51,7 @@ import 'codemirror/lib/codemirror.css';
 import 'codemirror/theme/eclipse.css';
 import 'codemirror/mode/javascript/javascript';
 import 'codemirror/addon/comment/continuecomment';
+import 'codemirror/addon/comment/comment';
 import 'codemirror/addon/edit/matchbrackets';
 import 'codemirror/addon/edit/closebrackets';
 import 'codemirror/addon/fold/foldcode';
@@ -88,8 +89,15 @@ function getHandler(key) {
 ].forEach((key) => {
   CodeMirror.commands[key] = getHandler(key);
 });
+Object.assign(CodeMirror.keyMap.sublime, {
+  Tab: 'indentMore',
+  'Shift-Ctrl-/': 'commentSelection',
+});
+CodeMirror.commands.commentSelection = cm => {
+  cm.blockComment(cm.getCursor('from'), cm.getCursor('to'), { fullLines: false });
+};
 
-const cmOptions = {
+export const cmOptions = {
   continueComments: true,
   styleActiveLine: true,
   foldGutter: true,

+ 1 - 1
src/options/views/edit/keyboard.vue

@@ -34,7 +34,7 @@ function expandKeyMap(res, ...maps) {
   maps.forEach((map) => {
     if (typeof map === 'string') map = CodeMirror.keyMap[map];
     Object.entries(map).forEach(([key, value]) => {
-      if (!res[key] && /^[a-z]+$/i.test(value)) {
+      if (!res[key] && /^[a-z]+$/i.test(value) && CodeMirror.commands[value]) {
         res[key] = value;
       }
     });

+ 44 - 0
src/options/views/tab-settings/vm-editor.vue

@@ -5,6 +5,8 @@
     <setting-text name="editor" ref="editor" :json="true" />
     <button v-text="i18n('buttonSave')" @click="onSave"></button>
     <button v-text="i18n('buttonReset')" @click="onReset"></button>
+    <button v-text="i18n('buttonShowEditorState')" @click="toggleStateHint" />
+    <pre v-text="hint" class="monospace-font dim-hint" />
   </section>
 </template>
 
@@ -16,6 +18,9 @@ import SettingText from '#/common/ui/setting-text';
 import defaults from '#/common/options-defaults';
 
 export default {
+  data() {
+    return { hint: null };
+  },
   components: {
     SettingText,
   },
@@ -37,6 +42,45 @@ export default {
       const toggled = selection === 'false' && 'true' || selection === 'true' && 'false';
       if (toggled) document.execCommand('insertText', false, toggled);
     },
+    async toggleStateHint() {
+      if (this.hint) {
+        this.hint = null;
+        return;
+      }
+      const HIDE_OPTS = [
+        // we activate only one mode: js
+        'mode',
+        // duh
+        'value',
+        // these accept only a function
+        'configureMouse',
+        'lineNumberFormatter',
+        'specialCharPlaceholder',
+      ];
+      const opts = {};
+      Object.entries({
+        ...(await import('codemirror')).defaults,
+        ...(await import('#/common/ui/code')).cmOptions,
+        ...options.get('editor'),
+      })
+      // sort by keys alphabetically to make it more readable
+      .sort(([a], [b]) => (a < b ? -1 : a > b))
+      .filter(([key, val]) => !HIDE_OPTS.includes(key) && typeof val !== 'function')
+      .forEach(([key, val]) => { opts[key] = val; });
+      this.hint = JSON.stringify(opts, null, '  ');
+      setTimeout(() => {
+        if (this.$el.getBoundingClientRect().bottom > window.innerHeight) {
+          this.$el.scrollIntoView({ behavior: 'smooth' });
+        }
+      });
+    },
   },
 };
 </script>
+
+<style>
+  .dim-hint {
+    font-size: .85rem;
+    color: gray;
+  }
+</style>