From ba2205c231e2114128391fa5dee5df8b50d082c2 Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Mon, 2 Jun 2025 15:02:39 +0900 Subject: [PATCH 01/13] feat(v6): update --- .eslintignore | 2 - .eslintrc.yml | 14 - eslint.config.mjs | 22 + keymaps/vim.json | 166 - lib/keymap.js | 6303 -------------------- lib/keymap.js.map | 1 - lib/vim.js | 1312 ----- lib/vim.js.map | 1 - package-lock.json | 3409 ++--------- package.json | 22 +- prettier.config.js => prettier.config.mjs | 4 +- src/clipboard.js | 49 + src/keymap.js | 6446 --------------------- src/vim.js | 1169 +--- styles/vim.css | 8 + styles/vim.less | 2 - 16 files changed, 550 insertions(+), 18380 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.yml create mode 100644 eslint.config.mjs delete mode 100644 lib/keymap.js delete mode 100644 lib/keymap.js.map delete mode 100644 lib/vim.js delete mode 100644 lib/vim.js.map rename prettier.config.js => prettier.config.mjs (76%) create mode 100644 src/clipboard.js delete mode 100644 src/keymap.js create mode 100644 styles/vim.css delete mode 100644 styles/vim.less diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index d45b9ea..0000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -lib -src/keymap.js diff --git a/.eslintrc.yml b/.eslintrc.yml deleted file mode 100644 index d3c928e..0000000 --- a/.eslintrc.yml +++ /dev/null @@ -1,14 +0,0 @@ -root: true -extends: - - prettier -parser: "@babel/eslint-parser" -env: {} -globals: {} -rules: - no-useless-escape: 0 - prefer-const: 2 - no-unused-vars: - - 2 - - - argsIgnorePattern: ^_ - varsIgnorePattern: ^_ diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..158753d --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,22 @@ +import prettier from 'eslint-config-prettier' + +export default [ + { + ignores: [] + }, + + prettier, + + { + languageOptions: { + globals: { + inkdrop: 'readonly' + } + }, + rules: { + 'no-useless-escape': 0, + 'prefer-const': 2, + 'no-unused-vars': 0 + } + } +] diff --git a/keymaps/vim.json b/keymaps/vim.json index 40fb4b6..7d0e761 100644 --- a/keymaps/vim.json +++ b/keymaps/vim.json @@ -1,171 +1,5 @@ { ".CodeMirror.vim-mode": {}, - ".CodeMirror.vim-mode.normal-mode textarea": { - "escape": "vim:reset-normal-mode" - }, - ".CodeMirror.vim-mode:not(.insert-mode):not(.key-buffering) textarea": { - "h": "vim:move-left", - "left": "vim:move-left", - "backspace": "vim:move-left", - "l": "vim:move-right", - "right": "vim:move-right", - "space": "vim:move-right", - "k": "vim:move-up", - "up": "vim:move-up", - "j": "vim:move-down", - "down": "vim:move-down", - "g k": "vim:move-up-by-display-lines", - "g j": "vim:move-down-by-display-lines", - "g v": "vim:reselect-last-selection", - - "w": "vim:move-to-next-word", - "W": "vim:move-to-next-whole-word", - "e": "vim:move-to-end-of-word", - "g e": "vim:move-to-previous-end-of-word", - "E": "vim:move-to-end-of-whole-word", - "g E": "vim:move-to-previous-end-of-whole-word", - "b": "vim:move-to-previous-word", - "B": "vim:move-to-previous-whole-word", - "}": "vim:move-to-next-paragraph", - "{": "vim:move-to-previous-paragraph", - "|": "vim:move-to-beginning-of-line", - "0": "vim:move-to-beginning-of-line-with-zero", - "^": "vim:move-to-first-character-of-line", - "_": "vim:move-to-first-character-of-line-and-down", - "$": "vim:move-to-last-character-of-line", - "g _": "vim:move-to-last-nonblank-character-of-line-and-down", - "-": "vim:move-to-first-character-of-line-up", - "+": "vim:move-to-first-character-of-line-down", - "enter": "vim:move-to-first-character-of-line-down", - "g g": "vim:move-to-start-of-file", - "ctrl-u": "vim:scroll-half-screen-up", - "ctrl-b": "vim:scroll-full-screen-up", - "ctrl-d": "vim:scroll-half-screen-down", - "ctrl-f": "vim:scroll-full-screen-down", - "ctrl-e": "vim:scroll-down", - "ctrl-y": "vim:scroll-up", - "z enter": "vim:scroll-cursor-to-top", - "z t": "vim:scroll-cursor-to-top-leave", - "z .": "vim:scroll-cursor-to-middle", - "z z": "vim:scroll-cursor-to-middle-leave", - "z -": "vim:scroll-cursor-to-bottom", - "z b": "vim:scroll-cursor-to-bottom-leave", - "z s": "vim:scroll-cursor-to-left", - "z e": "vim:scroll-cursor-to-right", - "z M": "editor:fold-all", - "z R": "editor:unfold-all", - "z c": "editor:fold-current-row", - "z o": "editor:unfold-current-row", - "shift-G": "vim:move-to-line", - "H": "vim:move-to-top-of-screen", - "L": "vim:move-to-bottom-of-screen", - "M": "vim:move-to-middle-of-screen", - - "d": "vim:delete", - "D": "vim:delete-to-last-character-of-line", - "c": "vim:change", - "C": "vim:change-to-last-character-of-line", - "r": "vim:replace", - ">": "vim:indent", - "<": "vim:outdent", - "=": "vim:auto-indent", - "J": "vim:join", - - "y": "vim:yank", - "Y": "vim:yank-line", - "P": "vim:put-before", - "p": "vim:put-after", - - "g ~": "vim:toggle-case", - "g U": "vim:upper-case", - "g u": "vim:lower-case", - "~": "vim:toggle-case-now", - - "m": "vim:mark", - "`": "vim:move-to-mark-literal", - "'": "vim:move-to-mark", - - "f": "vim:find", - "F": "vim:find-backwards", - "t": "vim:till", - "T": "vim:till-backwards", - ";": "vim:repeat-find", - ",": "vim:repeat-find-reverse", - - "/": "vim:search", - "?": "vim:reverse-search", - "*": "vim:search-current-word", - "#": "vim:reverse-search-current-word", - "n": "vim:repeat-search", - "N": "vim:repeat-search-backwards", - - "%": "vim:bracket-matching-motion", - - ":": "vim:ex-command" - }, - ".CodeMirror.vim-mode:not(.insert-mode):not(.key-buffering-command) textarea": { - "i": "vim:text-object-manipulation-inner", - "a": "vim:text-object-manipulation" - }, - ".CodeMirror.vim-mode.normal-mode.key-buffering-operator textarea": { - "enter": "vim:move-down", - "space": "vim:move-right", - "up": "vim:move-up", - "down": "vim:move-down", - "right": "vim:move-right", - "left": "vim:move-left" - }, - ".CodeMirror.vim-mode.normal-mode:not(.key-buffering):not(.visual-mode) textarea": { - "i": "vim:activate-insert-mode", - "I": "vim:insert-at-beginning-of-line", - "insert": "vim:activate-insert-mode", - "R": "vim:activate-replace-mode", - "v": "vim:activate-characterwise-visual-mode", - "V": "vim:activate-linewise-visual-mode", - "ctrl-v": "vim:activate-blockwise-visual-mode", - "ctrl-q": "vim:activate-blockwise-visual-mode", - - "u": "vim:undo", - "ctrl-r": "core:redo", - - "O": "vim:insert-above-with-newline", - "o": "vim:insert-below-with-newline", - "a": "vim:insert-after", - "A": "vim:insert-after-end-of-line", - "x": "vim:delete-right", - "X": "vim:delete-left", - "s": "vim:substitute", - "S": "vim:substitute-line", - ".": "vim:repeat", - - "ctrl-a": "vim:increase", - "ctrl-x": "vim:decrease", - - "\"": "vim:register-prefix" - }, - ".CodeMirror.vim-mode.insert-mode textarea": { - "escape": "vim:exit-insert-mode", - "ctrl-w": "vim:delete-to-beginning-of-word" - }, - ".CodeMirror.vim-mode.replace-mode textarea": { - "escape": "vim:exit-insert-mode" - }, - ".CodeMirror.vim-mode.visual-mode textarea": { - "escape": "vim:exit-visual-mode" - }, - ".CodeMirror.vim-mode.visual-mode:not(.key-buffering) textarea": { - "\"": "vim:register-prefix", - "I": "vim:insert-at-start-of-target", - "A": "vim:insert-at-end-of-target", - "v": "vim:activate-characterwise-visual-mode", - "V": "vim:activate-linewise-visual-mode", - "o": "vim:reverse-selections", - "O": "vim:reverse-selections-at-same-line", - "x": "vim:delete-right", - "X": "vim:delete-left", - "s": "vim:substitute-visual", - "S": "vim:substitute-line-visual" - }, ".note-list-bar": { "k": "core:open-prev-note", "j": "core:open-next-note" diff --git a/lib/keymap.js b/lib/keymap.js deleted file mode 100644 index 5940841..0000000 --- a/lib/keymap.js +++ /dev/null @@ -1,6303 +0,0 @@ -"use strict"; - -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Supported keybindings: - * Too many to list. Refer to defaultKeyMap below. - * - * Supported Ex commands: - * Refer to defaultExCommandMap below. - * - * Registers: unnamed, -, a-z, A-Z, 0-9 - * (Does not respect the special case for number registers when delete - * operator is made with these commands: %, (, ), , /, ?, n, N, {, } ) - * TODO: Implement the remaining registers. - * - * Marks: a-z, A-Z, and 0-9 - * TODO: Implement the remaining special marks. They have more complex - * behavior. - * - * Events: - * 'vim-mode-change' - raised on the editor anytime the current mode changes, - * Event object: {mode: "visual", subMode: "linewise"} - * - * Code structure: - * 1. Default keymap - * 2. Variable declarations and short basic helpers - * 3. Instance (External API) implementation - * 4. Internal state tracking objects (input state, counter) implementation - * and instantiation - * 5. Key handler (the main command dispatcher) implementation - * 6. Motion, operator, and action implementations - * 7. Helper functions for the key handler, motions, operators, and actions - * 8. Set up Vim to work as a keymap for CodeMirror. - * 9. Ex command implementations. - */ -const { - logger -} = require('inkdrop'); -const { - clipboard -} = require('electron'); -module.exports = function (CodeMirror) { - var defaultKeymap = []; - var _defaultKeymap = [ - // Key to key mapping. This goes first to make it possible to override - // existing mappings. - { - keys: '', - type: 'keyToKey', - toKeys: 'h' - }, { - keys: '', - type: 'keyToKey', - toKeys: 'l' - }, { - keys: '', - type: 'keyToKey', - toKeys: 'k' - }, { - keys: '', - type: 'keyToKey', - toKeys: 'j' - }, { - keys: '', - type: 'keyToKey', - toKeys: 'l' - }, { - keys: '', - type: 'keyToKey', - toKeys: 'h', - context: 'normal' - }, - // - { - keys: '', - type: 'keyToKey', - toKeys: 'W' - }, { - keys: '', - type: 'keyToKey', - toKeys: 'B', - context: 'normal' - }, { - keys: '', - type: 'keyToKey', - toKeys: 'w' - }, { - keys: '', - type: 'keyToKey', - toKeys: 'b', - context: 'normal' - }, { - keys: '', - type: 'keyToKey', - toKeys: 'j' - }, { - keys: '', - type: 'keyToKey', - toKeys: 'k' - }, { - keys: '', - type: 'keyToKey', - toKeys: '' - }, { - keys: '', - type: 'keyToKey', - toKeys: '' - }, { - keys: '', - type: 'keyToKey', - toKeys: '', - context: 'insert' - }, { - keys: '', - type: 'keyToKey', - toKeys: '', - context: 'insert' - }, { - keys: 's', - type: 'keyToKey', - toKeys: 'cl', - context: 'normal' - }, { - keys: 's', - type: 'keyToKey', - toKeys: 'c', - context: 'visual' - }, { - keys: 'S', - type: 'keyToKey', - toKeys: 'cc', - context: 'normal' - }, { - keys: 'S', - type: 'keyToKey', - toKeys: 'VdO', - context: 'visual' - }, { - keys: '', - type: 'keyToKey', - toKeys: '0' - }, { - keys: '', - type: 'keyToKey', - toKeys: '$' - }, { - keys: '', - type: 'keyToKey', - toKeys: '' - }, { - keys: '', - type: 'keyToKey', - toKeys: '' - }, { - keys: '', - type: 'keyToKey', - toKeys: 'j^', - context: 'normal' - }, { - keys: '', - type: 'action', - action: 'toggleOverwrite', - context: 'insert' - }, - // Motions - { - keys: 'H', - type: 'motion', - motion: 'moveToTopLine', - motionArgs: { - linewise: true, - toJumplist: true - } - }, { - keys: 'M', - type: 'motion', - motion: 'moveToMiddleLine', - motionArgs: { - linewise: true, - toJumplist: true - } - }, { - keys: 'L', - type: 'motion', - motion: 'moveToBottomLine', - motionArgs: { - linewise: true, - toJumplist: true - } - }, { - keys: 'h', - type: 'motion', - motion: 'moveByCharacters', - motionArgs: { - forward: false - } - }, { - keys: 'l', - type: 'motion', - motion: 'moveByCharacters', - motionArgs: { - forward: true - } - }, { - keys: 'j', - type: 'motion', - motion: 'moveByLines', - motionArgs: { - forward: true, - linewise: true - } - }, { - keys: 'k', - type: 'motion', - motion: 'moveByLines', - motionArgs: { - forward: false, - linewise: true - } - }, { - keys: 'gj', - type: 'motion', - motion: 'moveByDisplayLines', - motionArgs: { - forward: true - } - }, { - keys: 'gk', - type: 'motion', - motion: 'moveByDisplayLines', - motionArgs: { - forward: false - } - }, { - keys: 'w', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: true, - wordEnd: false - } - }, { - keys: 'W', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: true, - wordEnd: false, - bigWord: true - } - }, { - keys: 'e', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: true, - wordEnd: true, - inclusive: true - } - }, { - keys: 'E', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: true, - wordEnd: true, - bigWord: true, - inclusive: true - } - }, { - keys: 'b', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: false, - wordEnd: false - } - }, { - keys: 'B', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: false, - wordEnd: false, - bigWord: true - } - }, { - keys: 'ge', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: false, - wordEnd: true, - inclusive: true - } - }, { - keys: 'gE', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: false, - wordEnd: true, - bigWord: true, - inclusive: true - } - }, { - keys: '{', - type: 'motion', - motion: 'moveByParagraph', - motionArgs: { - forward: false, - toJumplist: true - } - }, { - keys: '}', - type: 'motion', - motion: 'moveByParagraph', - motionArgs: { - forward: true, - toJumplist: true - } - }, { - keys: '', - type: 'motion', - motion: 'moveByPage', - motionArgs: { - forward: true - } - }, { - keys: '', - type: 'motion', - motion: 'moveByPage', - motionArgs: { - forward: false - } - }, { - keys: '', - type: 'motion', - motion: 'moveByScroll', - motionArgs: { - forward: true, - explicitRepeat: true - } - }, { - keys: '', - type: 'motion', - motion: 'moveByScroll', - motionArgs: { - forward: false, - explicitRepeat: true - } - }, { - keys: 'gg', - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { - forward: false, - explicitRepeat: true, - linewise: true, - toJumplist: true - } - }, { - keys: 'G', - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { - forward: true, - explicitRepeat: true, - linewise: true, - toJumplist: true - } - }, { - keys: '0', - type: 'motion', - motion: 'moveToStartOfLine' - }, { - keys: '^', - type: 'motion', - motion: 'moveToFirstNonWhiteSpaceCharacter' - }, { - keys: '+', - type: 'motion', - motion: 'moveByLines', - motionArgs: { - forward: true, - toFirstChar: true - } - }, { - keys: '-', - type: 'motion', - motion: 'moveByLines', - motionArgs: { - forward: false, - toFirstChar: true - } - }, { - keys: '_', - type: 'motion', - motion: 'moveByLines', - motionArgs: { - forward: true, - toFirstChar: true, - repeatOffset: -1 - } - }, { - keys: '$', - type: 'motion', - motion: 'moveToEol', - motionArgs: { - inclusive: true - } - }, { - keys: '%', - type: 'motion', - motion: 'moveToMatchedSymbol', - motionArgs: { - inclusive: true, - toJumplist: true - } - }, { - keys: 'f', - type: 'motion', - motion: 'moveToCharacter', - motionArgs: { - forward: true, - inclusive: true - } - }, { - keys: 'F', - type: 'motion', - motion: 'moveToCharacter', - motionArgs: { - forward: false - } - }, { - keys: 't', - type: 'motion', - motion: 'moveTillCharacter', - motionArgs: { - forward: true, - inclusive: true - } - }, { - keys: 'T', - type: 'motion', - motion: 'moveTillCharacter', - motionArgs: { - forward: false - } - }, { - keys: ';', - type: 'motion', - motion: 'repeatLastCharacterSearch', - motionArgs: { - forward: true - } - }, { - keys: ',', - type: 'motion', - motion: 'repeatLastCharacterSearch', - motionArgs: { - forward: false - } - }, { - keys: "'", - type: 'motion', - motion: 'goToMark', - motionArgs: { - toJumplist: true, - linewise: true - } - }, { - keys: '`', - type: 'motion', - motion: 'goToMark', - motionArgs: { - toJumplist: true - } - }, { - keys: ']`', - type: 'motion', - motion: 'jumpToMark', - motionArgs: { - forward: true - } - }, { - keys: '[`', - type: 'motion', - motion: 'jumpToMark', - motionArgs: { - forward: false - } - }, { - keys: "]'", - type: 'motion', - motion: 'jumpToMark', - motionArgs: { - forward: true, - linewise: true - } - }, { - keys: "['", - type: 'motion', - motion: 'jumpToMark', - motionArgs: { - forward: false, - linewise: true - } - }, - // the next two aren't motions but must come before more general motion declarations - { - keys: ']p', - type: 'action', - action: 'paste', - isEdit: true, - actionArgs: { - after: true, - isEdit: true, - matchIndent: true - } - }, { - keys: '[p', - type: 'action', - action: 'paste', - isEdit: true, - actionArgs: { - after: false, - isEdit: true, - matchIndent: true - } - }, { - keys: ']', - type: 'motion', - motion: 'moveToSymbol', - motionArgs: { - forward: true, - toJumplist: true - } - }, { - keys: '[', - type: 'motion', - motion: 'moveToSymbol', - motionArgs: { - forward: false, - toJumplist: true - } - }, { - keys: '|', - type: 'motion', - motion: 'moveToColumn' - }, { - keys: 'o', - type: 'motion', - motion: 'moveToOtherHighlightedEnd', - context: 'visual' - }, { - keys: 'O', - type: 'motion', - motion: 'moveToOtherHighlightedEnd', - motionArgs: { - sameLine: true - }, - context: 'visual' - }, - // Operators - { - keys: 'd', - type: 'operator', - operator: 'delete' - }, { - keys: 'y', - type: 'operator', - operator: 'yank' - }, { - keys: 'c', - type: 'operator', - operator: 'change' - }, { - keys: '>', - type: 'operator', - operator: 'indent', - operatorArgs: { - indentRight: true - } - }, { - keys: '<', - type: 'operator', - operator: 'indent', - operatorArgs: { - indentRight: false - } - }, { - keys: 'g~', - type: 'operator', - operator: 'changeCase' - }, { - keys: 'gu', - type: 'operator', - operator: 'changeCase', - operatorArgs: { - toLower: true - }, - isEdit: true - }, { - keys: 'gU', - type: 'operator', - operator: 'changeCase', - operatorArgs: { - toLower: false - }, - isEdit: true - }, { - keys: 'n', - type: 'motion', - motion: 'findNext', - motionArgs: { - forward: true, - toJumplist: true - } - }, { - keys: 'N', - type: 'motion', - motion: 'findNext', - motionArgs: { - forward: false, - toJumplist: true - } - }, - // Operator-Motion dual commands - { - keys: 'x', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveByCharacters', - motionArgs: { - forward: true - }, - operatorMotionArgs: { - visualLine: false - } - }, { - keys: 'X', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveByCharacters', - motionArgs: { - forward: false - }, - operatorMotionArgs: { - visualLine: true - } - }, { - keys: 'D', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveToEol', - motionArgs: { - inclusive: true - }, - context: 'normal' - }, { - keys: 'D', - type: 'operator', - operator: 'delete', - operatorArgs: { - linewise: true - }, - context: 'visual' - }, { - keys: 'Y', - type: 'operatorMotion', - operator: 'yank', - motion: 'expandToLine', - motionArgs: { - linewise: true - }, - context: 'normal' - }, { - keys: 'Y', - type: 'operator', - operator: 'yank', - operatorArgs: { - linewise: true - }, - context: 'visual' - }, { - keys: 'C', - type: 'operatorMotion', - operator: 'change', - motion: 'moveToEol', - motionArgs: { - inclusive: true - }, - context: 'normal' - }, { - keys: 'C', - type: 'operator', - operator: 'change', - operatorArgs: { - linewise: true - }, - context: 'visual' - }, { - keys: '~', - type: 'operatorMotion', - operator: 'changeCase', - motion: 'moveByCharacters', - motionArgs: { - forward: true - }, - operatorArgs: { - shouldMoveCursor: true - }, - context: 'normal' - }, { - keys: '~', - type: 'operator', - operator: 'changeCase', - context: 'visual' - }, { - keys: '', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveByWords', - motionArgs: { - forward: false, - wordEnd: false - }, - context: 'insert' - }, - // Actions - { - keys: '', - type: 'action', - action: 'jumpListWalk', - actionArgs: { - forward: true - } - }, { - keys: '', - type: 'action', - action: 'jumpListWalk', - actionArgs: { - forward: false - } - }, { - keys: '', - type: 'action', - action: 'scroll', - actionArgs: { - forward: true, - linewise: true - } - }, { - keys: '', - type: 'action', - action: 'scroll', - actionArgs: { - forward: false, - linewise: true - } - }, { - keys: 'a', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - insertAt: 'charAfter' - }, - context: 'normal' - }, { - keys: 'A', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - insertAt: 'eol' - }, - context: 'normal' - }, { - keys: 'A', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - insertAt: 'endOfSelectedArea' - }, - context: 'visual' - }, { - keys: 'i', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - insertAt: 'inplace' - }, - context: 'normal' - }, { - keys: 'I', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - insertAt: 'firstNonBlank' - }, - context: 'normal' - }, { - keys: 'I', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - insertAt: 'startOfSelectedArea' - }, - context: 'visual' - }, { - keys: 'o', - type: 'action', - action: 'newLineAndEnterInsertMode', - isEdit: true, - interlaceInsertRepeat: true, - actionArgs: { - after: true - }, - context: 'normal' - }, { - keys: 'O', - type: 'action', - action: 'newLineAndEnterInsertMode', - isEdit: true, - interlaceInsertRepeat: true, - actionArgs: { - after: false - }, - context: 'normal' - }, { - keys: 'v', - type: 'action', - action: 'toggleVisualMode' - }, { - keys: 'V', - type: 'action', - action: 'toggleVisualMode', - actionArgs: { - linewise: true - } - }, { - keys: '', - type: 'action', - action: 'toggleVisualMode', - actionArgs: { - blockwise: true - } - }, { - keys: '', - type: 'action', - action: 'toggleVisualMode', - actionArgs: { - blockwise: true - } - }, { - keys: 'gv', - type: 'action', - action: 'reselectLastSelection' - }, { - keys: 'J', - type: 'action', - action: 'joinLines', - isEdit: true - }, { - keys: 'p', - type: 'action', - action: 'paste', - isEdit: true, - actionArgs: { - after: true, - isEdit: true - } - }, { - keys: 'P', - type: 'action', - action: 'paste', - isEdit: true, - actionArgs: { - after: false, - isEdit: true - } - }, { - keys: 'r', - type: 'action', - action: 'replace', - isEdit: true - }, { - keys: '@', - type: 'action', - action: 'replayMacro' - }, { - keys: 'q', - type: 'action', - action: 'enterMacroRecordMode' - }, - // Handle Replace-mode as a special case of insert mode. - { - keys: 'R', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - replace: true - } - }, { - keys: 'u', - type: 'action', - action: 'undo', - context: 'normal' - }, { - keys: 'u', - type: 'operator', - operator: 'changeCase', - operatorArgs: { - toLower: true - }, - context: 'visual', - isEdit: true - }, { - keys: 'U', - type: 'operator', - operator: 'changeCase', - operatorArgs: { - toLower: false - }, - context: 'visual', - isEdit: true - }, { - keys: '', - type: 'action', - action: 'redo' - }, { - keys: 'm', - type: 'action', - action: 'setMark' - }, { - keys: '"', - type: 'action', - action: 'setRegister' - }, { - keys: 'zz', - type: 'action', - action: 'scrollToCursor', - actionArgs: { - position: 'center' - } - }, { - keys: 'z.', - type: 'action', - action: 'scrollToCursor', - actionArgs: { - position: 'center' - }, - motion: 'moveToFirstNonWhiteSpaceCharacter' - }, { - keys: 'zt', - type: 'action', - action: 'scrollToCursor', - actionArgs: { - position: 'top' - } - }, { - keys: 'z', - type: 'action', - action: 'scrollToCursor', - actionArgs: { - position: 'top' - }, - motion: 'moveToFirstNonWhiteSpaceCharacter' - }, { - keys: 'z-', - type: 'action', - action: 'scrollToCursor', - actionArgs: { - position: 'bottom' - } - }, { - keys: 'zb', - type: 'action', - action: 'scrollToCursor', - actionArgs: { - position: 'bottom' - }, - motion: 'moveToFirstNonWhiteSpaceCharacter' - }, { - keys: '.', - type: 'action', - action: 'repeatLastEdit' - }, { - keys: '', - type: 'action', - action: 'incrementNumberToken', - isEdit: true, - actionArgs: { - increase: true, - backtrack: false - } - }, { - keys: '', - type: 'action', - action: 'incrementNumberToken', - isEdit: true, - actionArgs: { - increase: false, - backtrack: false - } - }, { - keys: '', - type: 'action', - action: 'indent', - actionArgs: { - indentRight: true - }, - context: 'insert' - }, { - keys: '', - type: 'action', - action: 'indent', - actionArgs: { - indentRight: false - }, - context: 'insert' - }, - // Text object motions - { - keys: 'a', - type: 'motion', - motion: 'textObjectManipulation' - }, { - keys: 'i', - type: 'motion', - motion: 'textObjectManipulation', - motionArgs: { - textObjectInner: true - } - }, - // Search - { - keys: '/', - type: 'search', - searchArgs: { - forward: true, - querySrc: 'prompt', - toJumplist: true - } - }, { - keys: '?', - type: 'search', - searchArgs: { - forward: false, - querySrc: 'prompt', - toJumplist: true - } - }, { - keys: '*', - type: 'search', - searchArgs: { - forward: true, - querySrc: 'wordUnderCursor', - wholeWordOnly: true, - toJumplist: true - } - }, { - keys: '#', - type: 'search', - searchArgs: { - forward: false, - querySrc: 'wordUnderCursor', - wholeWordOnly: true, - toJumplist: true - } - }, { - keys: 'g*', - type: 'search', - searchArgs: { - forward: true, - querySrc: 'wordUnderCursor', - toJumplist: true - } - }, { - keys: 'g#', - type: 'search', - searchArgs: { - forward: false, - querySrc: 'wordUnderCursor', - toJumplist: true - } - }, - // Ex command - { - keys: ':', - type: 'ex' - }]; - - /** - * Ex commands - * Care must be taken when adding to the default Ex command map. For any - * pair of commands that have a shared prefix, at least one of their - * shortNames must not match the prefix of the other command. - */ - var defaultExCommandMap = [{ - name: 'colorscheme', - shortName: 'colo' - }, { - name: 'map' - }, { - name: 'imap', - shortName: 'im' - }, { - name: 'nmap', - shortName: 'nm' - }, { - name: 'vmap', - shortName: 'vm' - }, { - name: 'unmap' - }, { - name: 'write', - shortName: 'w' - }, { - name: 'undo', - shortName: 'u' - }, { - name: 'redo', - shortName: 'red' - }, { - name: 'set', - shortName: 'se' - }, { - name: 'set', - shortName: 'se' - }, { - name: 'setlocal', - shortName: 'setl' - }, { - name: 'setglobal', - shortName: 'setg' - }, { - name: 'sort', - shortName: 'sor' - }, { - name: 'substitute', - shortName: 's', - possiblyAsync: true - }, { - name: 'nohlsearch', - shortName: 'noh' - }, { - name: 'yank', - shortName: 'y' - }, { - name: 'delmarks', - shortName: 'delm' - }, { - name: 'registers', - shortName: 'reg', - excludeFromCommandHistory: true - }, { - name: 'global', - shortName: 'g' - }]; - var Pos = CodeMirror.Pos; - var Vim = function () { - function enterVimMode(cm) { - cm.setOption('disableInput', true); - cm.setOption('showCursorWhenSelecting', false); - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'normal' - }); - cm.on('cursorActivity', onCursorActivity); - maybeInitVimState(cm); - CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); - } - function leaveVimMode(cm) { - cm.setOption('disableInput', false); - cm.off('cursorActivity', onCursorActivity); - CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); - cm.state.vim = null; - } - function detachVimMap(cm, next) { - if (this == CodeMirror.keyMap.vim) { - CodeMirror.rmClass(cm.getWrapperElement(), 'cm-fat-cursor'); - } - if (!next || next.attach != attachVimMap) { - leaveVimMode(cm); - } - } - function attachVimMap(cm, prev) { - if (this == CodeMirror.keyMap.vim) { - CodeMirror.addClass(cm.getWrapperElement(), 'cm-fat-cursor'); - } - if (!prev || prev.attach != attachVimMap) { - enterVimMode(cm); - } - } - - // Deprecated, simply setting the keymap works again. - CodeMirror.defineOption('vimMode', false, function (cm, val, prev) { - if (val && cm.getOption('keyMap') != 'vim') { - cm.setOption('keyMap', 'vim'); - } else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption('keyMap'))) { - cm.setOption('keyMap', 'default'); - } - }); - function cmKey(key, cm) { - if (!cm) { - return undefined; - } - if (this[key]) { - return this[key]; - } - var vimKey = cmKeyToVimKey(key); - if (!vimKey) { - return false; - } - var cmd = CodeMirror.Vim.findKey(cm, vimKey); - if (typeof cmd === 'function') { - CodeMirror.signal(cm, 'vim-keypress', vimKey); - } - return cmd; - } - var modifiers = { - Shift: 'S', - Ctrl: 'C', - Alt: 'A', - Cmd: 'D', - Mod: 'A' - }; - var specialKeys = { - Enter: 'CR', - Backspace: 'BS', - Delete: 'Del', - Insert: 'Ins' - }; - function cmKeyToVimKey(key) { - if (key.charAt(0) == "'") { - // Keypress character binding of format "'a'" - return key.charAt(1); - } - var pieces = key.split(/-(?!$)/); - var lastPiece = pieces[pieces.length - 1]; - if (pieces.length == 1 && pieces[0].length == 1) { - // No-modifier bindings use literal character bindings above. Skip. - return false; - } else if (pieces.length == 2 && pieces[0] == 'Shift' && lastPiece.length == 1) { - // Ignore Shift+char bindings as they should be handled by literal character. - return false; - } - var hasCharacter = false; - for (var i = 0; i < pieces.length; i++) { - var piece = pieces[i]; - if (piece in modifiers) { - pieces[i] = modifiers[piece]; - } else { - hasCharacter = true; - } - if (piece in specialKeys) { - pieces[i] = specialKeys[piece]; - } - } - if (!hasCharacter) { - // Vim does not support modifier only keys. - return false; - } - // TODO: Current bindings expect the character to be lower case, but - // it looks like vim key notation uses upper case. - if (isUpperCase(lastPiece)) { - pieces[pieces.length - 1] = lastPiece.toLowerCase(); - } - return '<' + pieces.join('-') + '>'; - } - function getOnPasteFn(cm) { - var vim = cm.state.vim; - if (!vim.onPasteFn) { - vim.onPasteFn = function () { - if (!vim.insertMode) { - cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); - actions.enterInsertMode(cm, {}, vim); - } - }; - } - return vim.onPasteFn; - } - var numberRegex = /[\d]/; - var wordCharTest = [CodeMirror.isWordChar, function (ch) { - return ch && !CodeMirror.isWordChar(ch) && !/\s/.test(ch); - }], - bigWordCharTest = [function (ch) { - return /\S/.test(ch); - }]; - function makeKeyRange(start, size) { - var keys = []; - for (var i = start; i < start + size; i++) { - keys.push(String.fromCharCode(i)); - } - return keys; - } - var upperCaseAlphabet = makeKeyRange(65, 26); - var lowerCaseAlphabet = makeKeyRange(97, 26); - var numbers = makeKeyRange(48, 10); - var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']); - var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']); - function isLine(cm, line) { - return line >= cm.firstLine() && line <= cm.lastLine(); - } - function isLowerCase(k) { - return /^[a-z]$/.test(k); - } - function isMatchableSymbol(k) { - return '()[]{}'.indexOf(k) != -1; - } - function isNumber(k) { - return numberRegex.test(k); - } - function isUpperCase(k) { - return /^[A-Z]$/.test(k); - } - function isWhiteSpaceString(k) { - return /^\s*$/.test(k); - } - function inArray(val, arr) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] == val) { - return true; - } - } - return false; - } - var options = {}; - function defineOption(name, defaultValue, type, aliases, callback) { - if (defaultValue === undefined && !callback) { - throw Error('defaultValue is required unless callback is provided'); - } - if (!type) { - type = 'string'; - } - options[name] = { - type: type, - defaultValue: defaultValue, - callback: callback - }; - if (aliases) { - for (var i = 0; i < aliases.length; i++) { - options[aliases[i]] = options[name]; - } - } - if (defaultValue) { - setOption(name, defaultValue); - } - } - function setOption(name, value, cm, cfg) { - var option = options[name]; - cfg = cfg || {}; - var scope = cfg.scope; - if (!option) { - return new Error('Unknown option: ' + name); - } - if (option.type == 'boolean') { - if (value && value !== true) { - return new Error('Invalid argument: ' + name + '=' + value); - } else if (value !== false) { - // Boolean options are set to true if value is not defined. - value = true; - } - } - if (option.callback) { - if (scope !== 'local') { - option.callback(value, undefined); - } - if (scope !== 'global' && cm) { - option.callback(value, cm); - } - } else { - if (scope !== 'local') { - option.value = option.type == 'boolean' ? !!value : value; - } - if (scope !== 'global' && cm) { - cm.state.vim.options[name] = { - value: value - }; - } - } - } - function getOption(name, cm, cfg) { - var option = options[name]; - cfg = cfg || {}; - var scope = cfg.scope; - if (!option) { - return new Error('Unknown option: ' + name); - } - if (option.callback) { - var local = cm && option.callback(undefined, cm); - if (scope !== 'global' && local !== undefined) { - return local; - } - if (scope !== 'local') { - return option.callback(); - } - } else { - var local = scope !== 'global' && cm && cm.state.vim.options[name]; - return (local || scope !== 'local' && option || {}).value; - } - } - defineOption('filetype', undefined, 'string', ['ft'], function (name, cm) { - // Option is local. Do nothing for global. - if (cm === undefined) { - return; - } - // The 'filetype' option proxies to the CodeMirror 'mode' option. - if (name === undefined) { - var mode = cm.getOption('mode'); - return mode == 'null' ? '' : mode; - } else { - var mode = name == '' ? 'null' : name; - cm.setOption('mode', mode); - } - }); - var createCircularJumpList = function () { - var size = 100; - var pointer = -1; - var head = 0; - var tail = 0; - var buffer = new Array(size); - function add(cm, oldCur, newCur) { - var current = pointer % size; - var curMark = buffer[current]; - function useNextSlot(cursor) { - var next = ++pointer % size; - var trashMark = buffer[next]; - if (trashMark) { - trashMark.clear(); - } - buffer[next] = cm.setBookmark(cursor); - } - if (curMark) { - var markPos = curMark.find(); - // avoid recording redundant cursor position - if (markPos && !cursorEqual(markPos, oldCur)) { - useNextSlot(oldCur); - } - } else { - useNextSlot(oldCur); - } - useNextSlot(newCur); - head = pointer; - tail = pointer - size + 1; - if (tail < 0) { - tail = 0; - } - } - function move(cm, offset) { - pointer += offset; - if (pointer > head) { - pointer = head; - } else if (pointer < tail) { - pointer = tail; - } - var mark = buffer[(size + pointer) % size]; - // skip marks that are temporarily removed from text buffer - if (mark && !mark.find()) { - var inc = offset > 0 ? 1 : -1; - var newCur; - var oldCur = cm.getCursor(); - do { - pointer += inc; - mark = buffer[(size + pointer) % size]; - // skip marks that are the same as current position - if (mark && (newCur = mark.find()) && !cursorEqual(oldCur, newCur)) { - break; - } - } while (pointer < head && pointer > tail); - } - return mark; - } - return { - cachedCursor: undefined, - // used for # and * jumps - add: add, - move: move - }; - }; - - // Returns an object to track the changes associated insert mode. It - // clones the object that is passed in, or creates an empty object one if - // none is provided. - var createInsertModeChanges = function (c) { - if (c) { - // Copy construction - return { - changes: c.changes, - expectCursorActivityForChange: c.expectCursorActivityForChange - }; - } - return { - // Change list - changes: [], - // Set to true on change, false on cursorActivity. - expectCursorActivityForChange: false - }; - }; - function MacroModeState() { - this.latestRegister = undefined; - this.isPlaying = false; - this.isRecording = false; - this.replaySearchQueries = []; - this.onRecordingDone = undefined; - this.lastInsertModeChanges = createInsertModeChanges(); - } - MacroModeState.prototype = { - exitMacroRecordMode: function () { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.onRecordingDone) { - macroModeState.onRecordingDone(); // close dialog - } - - macroModeState.onRecordingDone = undefined; - macroModeState.isRecording = false; - }, - enterMacroRecordMode: function (cm, registerName) { - var register = vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.clear(); - this.latestRegister = registerName; - if (cm.openDialog) { - this.onRecordingDone = cm.openDialog('(recording)[' + registerName + ']', null, { - bottom: true - }); - } - this.isRecording = true; - } - } - }; - function maybeInitVimState(cm) { - if (!cm.state.vim) { - // Store instance state in the CodeMirror object. - cm.state.vim = { - inputState: new InputState(), - // Vim's input state that triggered the last edit, used to repeat - // motions and operators with '.'. - lastEditInputState: undefined, - // Vim's action command before the last edit, used to repeat actions - // with '.' and insert mode repeat. - lastEditActionCommand: undefined, - // When using jk for navigation, if you move from a longer line to a - // shorter line, the cursor may clip to the end of the shorter line. - // If j is pressed again and cursor goes to the next line, the - // cursor should go back to its horizontal position on the longer - // line if it can. This is to keep track of the horizontal position. - lastHPos: -1, - // Doing the same with screen-position for gj/gk - lastHSPos: -1, - // The last motion command run. Cleared if a non-motion command gets - // executed in between. - lastMotion: null, - marks: {}, - // Mark for rendering fake cursor for visual mode. - fakeCursor: null, - insertMode: false, - // Repeat count for changes made in insert mode, triggered by key - // sequences like 3,i. Only exists when insertMode is true. - insertModeRepeat: undefined, - visualMode: false, - // If we are in visual line mode. No effect if visualMode is false. - visualLine: false, - visualBlock: false, - lastSelection: null, - lastPastedText: null, - sel: {}, - // Buffer-local/window-local values of vim options. - options: {} - }; - } - return cm.state.vim; - } - var vimGlobalState; - function resetVimGlobalState() { - vimGlobalState = { - // The current search query. - searchQuery: null, - // Whether we are searching backwards. - searchIsReversed: false, - // Replace part of the last substituted pattern - lastSubstituteReplacePart: undefined, - jumpList: createCircularJumpList(), - macroModeState: new MacroModeState(), - // Recording latest f, t, F or T motion command. - lastCharacterSearch: { - increment: 0, - forward: true, - selectedCharacter: '' - }, - registerController: new RegisterController({}), - // search history buffer - searchHistoryController: new HistoryController(), - // ex Command history buffer - exCommandHistoryController: new HistoryController() - }; - for (var optionName in options) { - var option = options[optionName]; - option.value = option.defaultValue; - } - } - var lastInsertModeKeyTimer; - var vimApi = { - buildKeyMap: function () { - // TODO: Convert keymap into dictionary format for fast lookup. - }, - // Testing hook, though it might be useful to expose the register - // controller anyways. - getRegisterController: function () { - return vimGlobalState.registerController; - }, - resetVimGlobalState: resetVimGlobalState, - getVimGlobalState: function () { - return vimGlobalState; - }, - maybeInitVimState: maybeInitVimState, - suppressErrorLogging: false, - InsertModeKey: InsertModeKey, - map: function (lhs, rhs, ctx) { - // Add user defined key bindings. - exCommandDispatcher.map(lhs, rhs, ctx); - }, - unmap: function (lhs, ctx) { - exCommandDispatcher.unmap(lhs, ctx); - }, - // TODO: Expose setOption and getOption as instance methods. Need to decide how to namespace - // them, or somehow make them work with the existing CodeMirror setOption/getOption API. - setOption: setOption, - getOption: getOption, - defineOption: defineOption, - defineEx: function (name, prefix, func) { - if (!prefix) { - prefix = name; - } else if (name.indexOf(prefix) !== 0) { - throw new Error('(Vim.defineEx) "' + prefix + '" is not a prefix of "' + name + '", command not registered'); - } - exCommands[name] = func; - exCommandDispatcher.commandMap_[prefix] = { - name: name, - shortName: prefix, - type: 'api' - }; - }, - handleKey: function (cm, key, origin) { - var command = this.findKey(cm, key, origin); - if (typeof command === 'function') { - return command(); - } - }, - /** - * This is the outermost function called by CodeMirror, after keys have - * been mapped to their Vim equivalents. - * - * Finds a command based on the key (and cached keys if there is a - * multi-key sequence). Returns `undefined` if no key is matched, a noop - * function if a partial match is found (multi-key), and a function to - * execute the bound command if a a key is matched. The function always - * returns true. - */ - findKey: function (cm, key, origin) { - var vim = maybeInitVimState(cm); - function handleMacroRecording() { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isRecording) { - if (key == 'q') { - macroModeState.exitMacroRecordMode(); - clearInputState(cm); - return true; - } - if (origin != 'mapping') { - logKey(macroModeState, key); - } - } - } - function handleEsc() { - if (key == '') { - // Clear input state and get back to normal mode. - clearInputState(cm); - if (vim.visualMode) { - exitVisualMode(cm); - } else if (vim.insertMode) { - exitInsertMode(cm); - } - return true; - } - } - function doKeyToKey(keys) { - // TODO: prevent infinite recursion. - var match; - while (keys) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - match = /<\w+-.+?>|<\w+>|./.exec(keys); - key = match[0]; - keys = keys.substring(match.index + key.length); - CodeMirror.Vim.handleKey(cm, key, 'mapping'); - } - } - function handleKeyInsertMode() { - if (handleEsc()) { - return true; - } - var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; - logger.debug('keyBuffer:', keys); - var keysAreChars = key.length == 1; - var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); - // Need to check all key substrings in insert mode. - while (keys.length > 1 && match.type !== 'full') { - var keys = vim.inputState.keyBuffer = keys.slice(1); - var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); - if (thisMatch.type !== 'none') { - match = thisMatch; - } - } - if (match.type === 'none') { - clearInputState(cm); - return false; - } else if (match.type === 'partial') { - if (lastInsertModeKeyTimer) { - window.clearTimeout(lastInsertModeKeyTimer); - } - lastInsertModeKeyTimer = window.setTimeout(() => { - if (vim.insertMode && vim.inputState.keyBuffer) { - clearInputState(cm); - } - }, getOption('insertModeEscKeysTimeout')); - return !keysAreChars; - } - if (lastInsertModeKeyTimer) { - window.clearTimeout(lastInsertModeKeyTimer); - } - if (keysAreChars) { - var selections = cm.listSelections(); - for (var i = 0; i < selections.length; i++) { - var here = selections[i].head; - cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input'); - } - vimGlobalState.macroModeState.lastInsertModeChanges.changes.pop(); - } - clearInputState(cm); - return match.command; - } - function handleKeyNonInsertMode() { - if (handleMacroRecording() || handleEsc()) { - return true; - } - var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; - if (/^[1-9]\d*$/.test(keys)) { - return true; - } - var keysMatcher = /^(\d*)(.*)$/.exec(keys); - if (!keysMatcher) { - clearInputState(cm); - return false; - } - var context = vim.visualMode ? 'visual' : 'normal'; - var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context); - if (match.type === 'none') { - clearInputState(cm); - return false; - } else if (match.type === 'partial') { - return true; - } - vim.inputState.keyBuffer = ''; - keysMatcher = /^(\d*)(.*)$/.exec(keys); - if (keysMatcher[1] && keysMatcher[1] !== '0') { - vim.inputState.pushRepeatDigit(keysMatcher[1]); - } - return match.command; - } - var command; - if (vim.insertMode) { - command = handleKeyInsertMode(); - } else { - command = handleKeyNonInsertMode(); - } - logger.debug('keyBuffer::::', command, vim.inputState.keyBuffer, vim.inputState.operator, vim.inputState.operatorArgs); - if (command === false) { - return undefined; - } else if (command === true) { - // TODO: Look into using CodeMirror's multi-key handling. - // Return no-op since we are caching the key. Counts as handled, but - // don't want act on it just yet. - return function () { - return true; - }; - } else { - return function () { - return cm.operation(function () { - cm.curOp.isVimOp = true; - try { - if (command.type === 'keyToKey') { - doKeyToKey(command.toKeys); - } else { - commandDispatcher.processCommand(cm, vim, command); - } - } catch (e) { - // clear VIM state in case it's in a bad state. - cm.state.vim = undefined; - maybeInitVimState(cm); - if (!CodeMirror.Vim.suppressErrorLogging) { - console['log'](e); - } - throw e; - } - return true; - }); - }; - } - }, - handleEx: function (cm, input) { - exCommandDispatcher.processCommand(cm, input); - }, - defineMotion: defineMotion, - defineAction: defineAction, - defineOperator: defineOperator, - mapCommand: mapCommand, - _mapCommand: _mapCommand, - defineRegister: defineRegister, - exitVisualMode: exitVisualMode, - exitInsertMode: exitInsertMode, - clearInputState: clearInputState, - cmKeyToVimKey: cmKeyToVimKey - }; - - // Represents the current input state. - function InputState() { - this.prefixRepeat = []; - this.motionRepeat = []; - this.operator = null; - this.operatorArgs = null; - this.motion = null; - this.motionArgs = null; - this.keyBuffer = []; // For matching multi-key commands. - this.registerName = null; // Defaults to the unnamed register. - } - - InputState.prototype.pushRepeatDigit = function (n) { - if (!this.operator) { - this.prefixRepeat = this.prefixRepeat.concat(n); - } else { - this.motionRepeat = this.motionRepeat.concat(n); - } - }; - InputState.prototype.getRepeat = function () { - var repeat = 0; - if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) { - repeat = 1; - if (this.prefixRepeat.length > 0) { - repeat *= parseInt(this.prefixRepeat.join(''), 10); - } - if (this.motionRepeat.length > 0) { - repeat *= parseInt(this.motionRepeat.join(''), 10); - } - } - return repeat; - }; - function clearInputState(cm, reason) { - cm.state.vim.inputState = new InputState(); - CodeMirror.signal(cm, 'vim-command-done', reason); - } - - /* - * Register stores information about copy and paste registers. Besides - * text, a register must store whether it is linewise (i.e., when it is - * pasted, should it insert itself into a new line, or should the text be - * inserted at the cursor position.) - */ - function Register(text, linewise, blockwise) { - this.clear(); - this.keyBuffer = [text || '']; - this.insertModeChanges = []; - this.searchQueries = []; - this.linewise = !!linewise; - this.blockwise = !!blockwise; - } - Register.prototype = { - setText: function (text, linewise, blockwise) { - this.keyBuffer = [text || '']; - this.linewise = !!linewise; - this.blockwise = !!blockwise; - }, - pushText: function (text, linewise) { - // if this register has ever been set to linewise, use linewise. - if (linewise) { - if (!this.linewise) { - this.keyBuffer.push('\n'); - } - this.linewise = true; - } - this.keyBuffer.push(text); - }, - pushInsertModeChanges: function (changes) { - this.insertModeChanges.push(createInsertModeChanges(changes)); - }, - pushSearchQuery: function (query) { - this.searchQueries.push(query); - }, - clear: function () { - this.keyBuffer = []; - this.insertModeChanges = []; - this.searchQueries = []; - this.linewise = false; - }, - toString: function () { - return this.keyBuffer.join(''); - } - }; - - /** - * Defines an external register. - * - * The name should be a single character that will be used to reference the register. - * The register should support setText, pushText, clear, and toString(). See Register - * for a reference implementation. - */ - function defineRegister(name, register) { - var registers = vimGlobalState.registerController.registers; - if (!name || name.length != 1) { - throw Error('Register name must be 1 character'); - } - if (registers[name]) { - throw Error('Register already defined ' + name); - } - registers[name] = register; - validRegisters.push(name); - } - - /* - * vim registers allow you to keep many independent copy and paste buffers. - * See http://usevim.com/2012/04/13/registers/ for an introduction. - * - * RegisterController keeps the state of all the registers. An initial - * state may be passed in. The unnamed register '"' will always be - * overridden. - */ - function RegisterController(registers) { - this.registers = registers; - this.unnamedRegister = registers['"'] = new Register(); - registers['.'] = new Register(); - registers[':'] = new Register(); - registers['/'] = new Register(); - } - RegisterController.prototype = { - pushText: function (registerName, operator, text, linewise, blockwise) { - if (linewise && text.charAt(text.length - 1) !== '\n') { - text += '\n'; - } - // Lowercase and uppercase registers refer to the same register. - // Uppercase just means append. - var register = this.isValidRegister(registerName) ? this.getRegister(registerName) : null; - // if no register/an invalid register was specified, things go to the - // default registers - if (!register) { - switch (operator) { - case 'yank': - // The 0 register contains the text from the most recent yank. - const reg = new Register(text, linewise, blockwise); - logger.debug('yanked:', reg); - this.registers['0'] = reg; - clipboard.writeText(reg.keyBuffer[0]); - break; - case 'delete': - case 'change': - clipboard.writeText(text); - if (text.indexOf('\n') == -1) { - // Delete less than 1 line. Update the small delete register. - this.registers['-'] = new Register(text, linewise); - } else { - // Shift down the contents of the numbered registers and put the - // deleted text into register 1. - this.shiftNumericRegisters_(); - this.registers['1'] = new Register(text, linewise); - } - break; - } - // Make sure the unnamed register is set to what just happened - this.unnamedRegister.setText(text, linewise, blockwise); - return; - } - - // If we've gotten to this point, we've actually specified a register - var append = isUpperCase(registerName); - if (append) { - register.pushText(text, linewise); - } else { - register.setText(text, linewise, blockwise); - } - // The unnamed register always has the same value as the last used - // register. - this.unnamedRegister.setText(register.toString(), linewise); - }, - // Gets the register named @name. If one of @name doesn't already exist, - // create it. If @name is invalid, return the unnamedRegister. - getRegister: function (name) { - if (!this.isValidRegister(name)) { - return this.unnamedRegister; - } - name = name.toLowerCase(); - if (!this.registers[name]) { - this.registers[name] = new Register(); - } - return this.registers[name]; - }, - isValidRegister: function (name) { - return name && inArray(name, validRegisters); - }, - shiftNumericRegisters_: function () { - for (var i = 9; i >= 2; i--) { - this.registers[i] = this.getRegister('' + (i - 1)); - } - } - }; - function HistoryController() { - this.historyBuffer = []; - this.iterator = 0; - this.initialPrefix = null; - } - HistoryController.prototype = { - // the input argument here acts a user entered prefix for a small time - // until we start autocompletion in which case it is the autocompleted. - nextMatch: function (input, up) { - var historyBuffer = this.historyBuffer; - var dir = up ? -1 : 1; - if (this.initialPrefix === null) this.initialPrefix = input; - for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i += dir) { - var element = historyBuffer[i]; - for (var j = 0; j <= element.length; j++) { - if (this.initialPrefix == element.substring(0, j)) { - this.iterator = i; - return element; - } - } - } - // should return the user input in case we reach the end of buffer. - if (i >= historyBuffer.length) { - this.iterator = historyBuffer.length; - return this.initialPrefix; - } - // return the last autocompleted query or exCommand as it is. - if (i < 0) return input; - }, - pushInput: function (input) { - var index = this.historyBuffer.indexOf(input); - if (index > -1) this.historyBuffer.splice(index, 1); - if (input.length) this.historyBuffer.push(input); - }, - reset: function () { - this.initialPrefix = null; - this.iterator = this.historyBuffer.length; - } - }; - var commandDispatcher = { - matchCommand: function (keys, keyMap, inputState, context) { - var matches = commandMatches(keys, keyMap, context, inputState); - if (!matches.full && !matches.partial) { - return { - type: 'none' - }; - } else if (!matches.full && matches.partial) { - return { - type: 'partial' - }; - } - var bestMatch; - for (var i = 0; i < matches.full.length; i++) { - var match = matches.full[i]; - if (!bestMatch) { - bestMatch = match; - } - } - if (bestMatch.keys.slice(-11) == '') { - var character = lastChar(keys); - if (!character) return { - type: 'none' - }; - inputState.selectedCharacter = character; - } - return { - type: 'full', - command: bestMatch - }; - }, - processCommand: function (cm, vim, command) { - vim.inputState.repeatOverride = command.repeatOverride; - switch (command.type) { - case 'motion': - this.processMotion(cm, vim, command); - break; - case 'operator': - this.processOperator(cm, vim, command); - break; - case 'operatorMotion': - this.processOperatorMotion(cm, vim, command); - break; - case 'action': - this.processAction(cm, vim, command); - break; - case 'search': - this.processSearch(cm, vim, command); - break; - case 'ex': - case 'keyToEx': - this.processEx(cm, vim, command); - break; - default: - break; - } - }, - processMotion: function (cm, vim, command) { - vim.inputState.motion = command.motion; - vim.inputState.motionArgs = copyArgs(command.motionArgs); - this.evalInput(cm, vim); - }, - processOperator: function (cm, vim, command) { - var inputState = vim.inputState; - if (inputState.operator) { - if (inputState.operator === command.operator) { - // Typing an operator twice like 'dd' makes the operator operate - // linewise - inputState.motion = 'expandToLine'; - inputState.motionArgs = { - linewise: true - }; - this.evalInput(cm, vim); - return; - } else { - // 2 different operators in a row doesn't make sense. - clearInputState(cm); - } - } - inputState.operator = command.operator; - inputState.operatorArgs = copyArgs(command.operatorArgs); - if (vim.visualMode) { - // Operating on a selection in visual mode. We don't need a motion. - this.evalInput(cm, vim); - } - }, - processOperatorMotion: function (cm, vim, command) { - var visualMode = vim.visualMode; - var operatorMotionArgs = copyArgs(command.operatorMotionArgs); - if (operatorMotionArgs) { - // Operator motions may have special behavior in visual mode. - if (visualMode && operatorMotionArgs.visualLine) { - vim.visualLine = true; - } - } - this.processOperator(cm, vim, command); - if (!visualMode) { - this.processMotion(cm, vim, command); - } - }, - processAction: function (cm, vim, command) { - var inputState = vim.inputState; - var repeat = inputState.getRepeat(); - var repeatIsExplicit = !!repeat; - var actionArgs = copyArgs(command.actionArgs) || {}; - if (inputState.selectedCharacter) { - actionArgs.selectedCharacter = inputState.selectedCharacter; - } - // Actions may or may not have motions and operators. Do these first. - if (command.operator) { - this.processOperator(cm, vim, command); - } - if (command.motion) { - this.processMotion(cm, vim, command); - } - if (command.motion || command.operator) { - this.evalInput(cm, vim); - } - actionArgs.repeat = repeat || 1; - actionArgs.repeatIsExplicit = repeatIsExplicit; - actionArgs.registerName = inputState.registerName; - clearInputState(cm); - vim.lastMotion = null; - if (command.isEdit) { - this.recordLastEdit(vim, inputState, command); - } - actions[command.action](cm, actionArgs, vim); - }, - processSearch: function (cm, vim, command) { - if (!cm.getSearchCursor) { - // Search depends on SearchCursor. - return; - } - var forward = command.searchArgs.forward; - var wholeWordOnly = command.searchArgs.wholeWordOnly; - getSearchState(cm).setReversed(!forward); - var promptPrefix = forward ? '/' : '?'; - var originalQuery = getSearchState(cm).getQuery(); - var originalScrollPos = cm.getScrollInfo(); - function handleQuery(query, ignoreCase, smartCase) { - vimGlobalState.searchHistoryController.pushInput(query); - vimGlobalState.searchHistoryController.reset(); - try { - updateSearchQuery(cm, query, ignoreCase, smartCase); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + query); - clearInputState(cm); - return; - } - commandDispatcher.processMotion(cm, vim, { - type: 'motion', - motion: 'findNext', - motionArgs: { - forward: true, - toJumplist: command.searchArgs.toJumplist - } - }); - } - function onPromptClose(query) { - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - handleQuery(query, true /** ignoreCase */, true /** smartCase */); - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isRecording) { - logSearchQuery(macroModeState, query); - } - } - function onPromptKeyUp(e, query, close) { - var keyName = CodeMirror.keyName(e), - up, - offset; - if (keyName == 'Up' || keyName == 'Down') { - up = keyName == 'Up'; - offset = e.target ? e.target.selectionEnd : 0; - query = vimGlobalState.searchHistoryController.nextMatch(query, up) || ''; - close(query); - if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length); - } else { - if (keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') { - vimGlobalState.searchHistoryController.reset(); - } - } - var parsedQuery; - try { - parsedQuery = updateSearchQuery(cm, query, true /** ignoreCase */, true /** smartCase */); - } catch (e) { - // Swallow bad regexes for incremental search. - } - if (parsedQuery) { - cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30); - } else { - clearSearchHighlight(cm); - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - } - } - function onPromptKeyDown(e, query, close) { - var keyName = CodeMirror.keyName(e); - if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' || keyName == 'Backspace' && query == '') { - vimGlobalState.searchHistoryController.pushInput(query); - vimGlobalState.searchHistoryController.reset(); - updateSearchQuery(cm, originalQuery); - clearSearchHighlight(cm); - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - CodeMirror.e_stop(e); - clearInputState(cm); - close(); - cm.focus(); - } else if (keyName == 'Up' || keyName == 'Down') { - CodeMirror.e_stop(e); - } else if (keyName == 'Ctrl-U') { - // Ctrl-U clears input. - CodeMirror.e_stop(e); - close(''); - } - } - switch (command.searchArgs.querySrc) { - case 'prompt': - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { - var query = macroModeState.replaySearchQueries.shift(); - handleQuery(query, true /** ignoreCase */, false /** smartCase */); - } else { - showPrompt(cm, { - onClose: onPromptClose, - prefix: promptPrefix, - desc: searchPromptDesc, - onKeyUp: onPromptKeyUp, - onKeyDown: onPromptKeyDown - }); - } - break; - case 'wordUnderCursor': - var word = expandWordUnderCursor(cm, false /** inclusive */, true /** forward */, false /** bigWord */, true /** noSymbol */); - - var isKeyword = true; - if (!word) { - word = expandWordUnderCursor(cm, false /** inclusive */, true /** forward */, false /** bigWord */, false /** noSymbol */); - - isKeyword = false; - } - if (!word) { - return; - } - var query = cm.getLine(word.start.line).substring(word.start.ch, word.end.ch); - if (isKeyword && wholeWordOnly) { - query = '\\b' + query + '\\b'; - } else { - query = escapeRegex(query); - } - - // cachedCursor is used to save the old position of the cursor - // when * or # causes vim to seek for the nearest word and shift - // the cursor before entering the motion. - vimGlobalState.jumpList.cachedCursor = cm.getCursor(); - cm.setCursor(word.start); - handleQuery(query, true /** ignoreCase */, false /** smartCase */); - break; - } - }, - processEx: function (cm, vim, command) { - function onPromptClose(input) { - // Give the prompt some time to close so that if processCommand shows - // an error, the elements don't overlap. - vimGlobalState.exCommandHistoryController.pushInput(input); - vimGlobalState.exCommandHistoryController.reset(); - exCommandDispatcher.processCommand(cm, input); - } - function onPromptKeyDown(e, input, close) { - var keyName = CodeMirror.keyName(e), - up, - offset; - if (keyName === 'Esc' || keyName === 'Ctrl-C' || keyName === 'Ctrl-[' || keyName === 'Backspace' && input === '') { - vimGlobalState.exCommandHistoryController.pushInput(input); - vimGlobalState.exCommandHistoryController.reset(); - CodeMirror.e_stop(e); - clearInputState(cm); - close(); - cm.focus(); - } - if (keyName === 'Up' || keyName === 'Down') { - CodeMirror.e_stop(e); - up = keyName === 'Up'; - offset = e.target ? e.target.selectionEnd : 0; - input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || ''; - close(input); - if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length); - } else if (keyName === 'Ctrl-U') { - // Ctrl-U clears input. - CodeMirror.e_stop(e); - close(''); - } else { - if (keyName !== 'Left' && keyName !== 'Right' && keyName !== 'Ctrl' && keyName !== 'Alt' && keyName !== 'Shift') { - vimGlobalState.exCommandHistoryController.reset(); - } - } - } - if (command.type === 'keyToEx') { - // Handle user defined Ex to Ex mappings - exCommandDispatcher.processCommand(cm, command.exArgs.input); - } else { - if (vim.visualMode) { - showPrompt(cm, { - onClose: onPromptClose, - prefix: ':', - value: "'<,'>", - onKeyDown: onPromptKeyDown - }); - } else { - showPrompt(cm, { - onClose: onPromptClose, - prefix: ':', - onKeyDown: onPromptKeyDown - }); - } - } - }, - evalInput: function (cm, vim) { - // If the motion command is set, execute both the operator and motion. - // Otherwise return. - var inputState = vim.inputState; - var motion = inputState.motion; - var motionArgs = inputState.motionArgs || {}; - var operator = inputState.operator; - var operatorArgs = inputState.operatorArgs || {}; - var registerName = inputState.registerName; - var sel = vim.sel; - // TODO: Make sure cm and vim selections are identical outside visual mode. - var origHead = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.head) : cm.getCursor('head')); - var origAnchor = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.anchor) : cm.getCursor('anchor')); - var oldHead = copyCursor(origHead); - var oldAnchor = copyCursor(origAnchor); - var newHead, newAnchor; - var repeat; - if (operator) { - this.recordLastEdit(vim, inputState); - } - if (inputState.repeatOverride !== undefined) { - // If repeatOverride is specified, that takes precedence over the - // input state's repeat. Used by Ex mode and can be user defined. - repeat = inputState.repeatOverride; - } else { - repeat = inputState.getRepeat(); - } - if (repeat > 0 && motionArgs.explicitRepeat) { - motionArgs.repeatIsExplicit = true; - } else if (motionArgs.noRepeat || !motionArgs.explicitRepeat && repeat === 0) { - repeat = 1; - motionArgs.repeatIsExplicit = false; - } - if (inputState.selectedCharacter) { - // If there is a character input, stick it in all of the arg arrays. - motionArgs.selectedCharacter = operatorArgs.selectedCharacter = inputState.selectedCharacter; - } - motionArgs.repeat = repeat; - clearInputState(cm); - if (motion) { - var motionResult = motions[motion](cm, origHead, motionArgs, vim); - vim.lastMotion = motions[motion]; - if (!motionResult) { - return; - } - if (motionArgs.toJumplist) { - var jumpList = vimGlobalState.jumpList; - // if the current motion is # or *, use cachedCursor - var cachedCursor = jumpList.cachedCursor; - if (cachedCursor) { - recordJumpPosition(cm, cachedCursor, motionResult); - delete jumpList.cachedCursor; - } else { - recordJumpPosition(cm, origHead, motionResult); - } - } - if (motionResult instanceof Array) { - newAnchor = motionResult[0]; - newHead = motionResult[1]; - } else { - newHead = motionResult; - } - // TODO: Handle null returns from motion commands better. - if (!newHead) { - newHead = copyCursor(origHead); - } - if (vim.visualMode) { - if (!(vim.visualBlock && newHead.ch === Infinity)) { - newHead = clipCursorToContent(cm, newHead, vim.visualBlock); - } - if (newAnchor) { - newAnchor = clipCursorToContent(cm, newAnchor, true); - } - newAnchor = newAnchor || oldAnchor; - sel.anchor = newAnchor; - sel.head = newHead; - updateCmSelection(cm); - updateMark(cm, vim, '<', cursorIsBefore(newAnchor, newHead) ? newAnchor : newHead); - updateMark(cm, vim, '>', cursorIsBefore(newAnchor, newHead) ? newHead : newAnchor); - } else if (!operator) { - newHead = clipCursorToContent(cm, newHead); - cm.setCursor(newHead.line, newHead.ch); - } - } - if (operator) { - if (operatorArgs.lastSel) { - // Replaying a visual mode operation - newAnchor = oldAnchor; - var lastSel = operatorArgs.lastSel; - var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line); - var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch); - if (lastSel.visualLine) { - // Linewise Visual mode: The same number of lines. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); - } else if (lastSel.visualBlock) { - // Blockwise Visual mode: The same number of lines and columns. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset); - } else if (lastSel.head.line == lastSel.anchor.line) { - // Normal Visual mode within one line: The same number of characters. - newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset); - } else { - // Normal Visual mode with several lines: The same number of lines, in the - // last line the same number of characters as in the last line the last time. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); - } - vim.visualMode = true; - vim.visualLine = lastSel.visualLine; - vim.visualBlock = lastSel.visualBlock; - sel = vim.sel = { - anchor: newAnchor, - head: newHead - }; - updateCmSelection(cm); - } else if (vim.visualMode) { - operatorArgs.lastSel = { - anchor: copyCursor(sel.anchor), - head: copyCursor(sel.head), - visualBlock: vim.visualBlock, - visualLine: vim.visualLine - }; - } - var curStart, curEnd, linewise, mode; - var cmSel; - if (vim.visualMode) { - // Init visual op - curStart = cursorMin(sel.head, sel.anchor); - curEnd = cursorMax(sel.head, sel.anchor); - linewise = vim.visualLine || operatorArgs.linewise; - mode = vim.visualBlock ? 'block' : linewise ? 'line' : 'char'; - cmSel = makeCmSelection(cm, { - anchor: curStart, - head: curEnd - }, mode); - if (linewise) { - var ranges = cmSel.ranges; - if (mode == 'block') { - // Linewise operators in visual block mode extend to end of line - for (var i = 0; i < ranges.length; i++) { - ranges[i].head.ch = lineLength(cm, ranges[i].head.line); - } - } else if (mode == 'line') { - ranges[0].head = Pos(ranges[0].head.line + 1, 0); - } - } - } else { - // Init motion op - curStart = copyCursor(newAnchor || oldAnchor); - curEnd = copyCursor(newHead || oldHead); - if (cursorIsBefore(curEnd, curStart)) { - var tmp = curStart; - curStart = curEnd; - curEnd = tmp; - } - linewise = motionArgs.linewise || operatorArgs.linewise; - if (linewise) { - // Expand selection to entire line. - expandSelectionToLine(cm, curStart, curEnd); - } else if (motionArgs.forward) { - // Clip to trailing newlines only if the motion goes forward. - clipToLine(cm, curStart, curEnd); - } - mode = 'char'; - var exclusive = !motionArgs.inclusive || linewise; - cmSel = makeCmSelection(cm, { - anchor: curStart, - head: curEnd - }, mode, exclusive); - } - cm.setSelections(cmSel.ranges, cmSel.primary); - vim.lastMotion = null; - operatorArgs.repeat = repeat; // For indent in visual mode. - operatorArgs.registerName = registerName; - // Keep track of linewise as it affects how paste and change behave. - operatorArgs.linewise = linewise; - var operatorMoveTo = operators[operator](cm, operatorArgs, cmSel.ranges, oldAnchor, newHead); - if (vim.visualMode) { - exitVisualMode(cm, operatorMoveTo != null); - } - if (operatorMoveTo) { - cm.setCursor(operatorMoveTo); - } - } - }, - recordLastEdit: function (vim, inputState, actionCommand) { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { - return; - } - vim.lastEditInputState = inputState; - vim.lastEditActionCommand = actionCommand; - macroModeState.lastInsertModeChanges.changes = []; - macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false; - } - }; - - /** - * typedef {Object{line:number,ch:number}} Cursor An object containing the - * position of the cursor. - */ - // All of the functions below return Cursor objects. - var motions = { - moveToTopLine: function (cm, _head, motionArgs) { - var line = getUserVisibleLines(cm).top + motionArgs.repeat - 1; - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - moveToMiddleLine: function (cm) { - var range = getUserVisibleLines(cm); - var line = Math.floor((range.top + range.bottom) * 0.5); - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - moveToBottomLine: function (cm, _head, motionArgs) { - var line = getUserVisibleLines(cm).bottom - motionArgs.repeat + 1; - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - expandToLine: function (_cm, head, motionArgs) { - // Expands forward to end of line, and then to next line if repeat is - // >1. Does not handle backward motion! - var cur = head; - return Pos(cur.line + motionArgs.repeat - 1, Infinity); - }, - findNext: function (cm, _head, motionArgs) { - var state = getSearchState(cm); - var query = state.getQuery(); - if (!query) { - return; - } - var prev = !motionArgs.forward; - // If search is initiated with ? instead of /, negate direction. - prev = state.isReversed() ? !prev : prev; - highlightSearchMatches(cm, query); - return findNext(cm, prev /** prev */, query, motionArgs.repeat); - }, - goToMark: function (cm, _head, motionArgs, vim) { - var pos = getMarkPos(cm, vim, motionArgs.selectedCharacter); - if (pos) { - return motionArgs.linewise ? { - line: pos.line, - ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) - } : pos; - } - return null; - }, - moveToOtherHighlightedEnd: function (cm, _head, motionArgs, vim) { - if (vim.visualBlock && motionArgs.sameLine) { - var sel = vim.sel; - return [clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)), clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch))]; - } else { - return [vim.sel.head, vim.sel.anchor]; - } - }, - jumpToMark: function (cm, head, motionArgs, vim) { - var best = head; - for (var i = 0; i < motionArgs.repeat; i++) { - var cursor = best; - for (var key in vim.marks) { - if (!isLowerCase(key)) { - continue; - } - var mark = vim.marks[key].find(); - var isWrongDirection = motionArgs.forward ? cursorIsBefore(mark, cursor) : cursorIsBefore(cursor, mark); - if (isWrongDirection) { - continue; - } - if (motionArgs.linewise && mark.line == cursor.line) { - continue; - } - var equal = cursorEqual(cursor, best); - var between = motionArgs.forward ? cursorIsBetween(cursor, mark, best) : cursorIsBetween(best, mark, cursor); - if (equal || between) { - best = mark; - } - } - } - if (motionArgs.linewise) { - // Vim places the cursor on the first non-whitespace character of - // the line if there is one, else it places the cursor at the end - // of the line, regardless of whether a mark was found. - best = Pos(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line))); - } - return best; - }, - moveByCharacters: function (_cm, head, motionArgs) { - var cur = head; - var repeat = motionArgs.repeat; - var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat; - return Pos(cur.line, ch); - }, - moveByLines: function (cm, head, motionArgs, vim) { - var cur = head; - var endCh = cur.ch; - // Depending what our last motion was, we may want to do different - // things. If our last motion was moving vertically, we want to - // preserve the HPos from our last horizontal move. If our last motion - // was going to the end of a line, moving vertically we should go to - // the end of the line, etc. - switch (vim.lastMotion) { - case this.moveByLines: - case this.moveByDisplayLines: - case this.moveByScroll: - case this.moveToColumn: - case this.moveToEol: - endCh = vim.lastHPos; - break; - default: - vim.lastHPos = endCh; - } - var repeat = motionArgs.repeat + (motionArgs.repeatOffset || 0); - var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat; - var first = cm.firstLine(); - var last = cm.lastLine(); - // Vim go to line begin or line end when cursor at first/last line and - // move to previous/next line is triggered. - if (line < first && cur.line == first) { - return this.moveToStartOfLine(cm, head, motionArgs, vim); - } else if (line > last && cur.line == last) { - return this.moveToEol(cm, head, motionArgs, vim); - } - if (motionArgs.toFirstChar) { - endCh = findFirstNonWhiteSpaceCharacter(cm.getLine(line)); - vim.lastHPos = endCh; - } - vim.lastHSPos = cm.charCoords(Pos(line, endCh), 'div').left; - return Pos(line, endCh); - }, - moveByDisplayLines: function (cm, head, motionArgs, vim) { - var cur = head; - switch (vim.lastMotion) { - case this.moveByDisplayLines: - case this.moveByScroll: - case this.moveByLines: - case this.moveToColumn: - case this.moveToEol: - break; - default: - vim.lastHSPos = cm.charCoords(cur, 'div').left; - } - var repeat = motionArgs.repeat; - var res = cm.findPosV(cur, motionArgs.forward ? repeat : -repeat, 'line', vim.lastHSPos); - if (res.hitSide) { - if (motionArgs.forward) { - var lastCharCoords = cm.charCoords(res, 'div'); - var goalCoords = { - top: lastCharCoords.top + 8, - left: vim.lastHSPos - }; - var res = cm.coordsChar(goalCoords, 'div'); - } else { - var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div'); - resCoords.left = vim.lastHSPos; - res = cm.coordsChar(resCoords, 'div'); - } - } - vim.lastHPos = res.ch; - return res; - }, - moveByPage: function (cm, head, motionArgs) { - // CodeMirror only exposes functions that move the cursor page down, so - // doing this bad hack to move the cursor and move it back. evalInput - // will move the cursor to where it should be in the end. - var curStart = head; - var repeat = motionArgs.repeat; - return cm.findPosV(curStart, motionArgs.forward ? repeat : -repeat, 'page'); - }, - moveByParagraph: function (cm, head, motionArgs) { - var dir = motionArgs.forward ? 1 : -1; - return findParagraph(cm, head, motionArgs.repeat, dir); - }, - moveByScroll: function (cm, head, motionArgs, vim) { - var scrollbox = cm.getScrollInfo(); - var curEnd = null; - var repeat = motionArgs.repeat; - if (!repeat) { - repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight()); - } - var orig = cm.charCoords(head, 'local'); - motionArgs.repeat = repeat; - var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim); - if (!curEnd) { - return null; - } - var dest = cm.charCoords(curEnd, 'local'); - cm.scrollTo(null, scrollbox.top + dest.top - orig.top); - return curEnd; - }, - moveByWords: function (cm, head, motionArgs) { - return moveToWord(cm, head, motionArgs.repeat, !!motionArgs.forward, !!motionArgs.wordEnd, !!motionArgs.bigWord); - }, - moveTillCharacter: function (cm, _head, motionArgs) { - var repeat = motionArgs.repeat; - var curEnd = moveToCharacter(cm, repeat, motionArgs.forward, motionArgs.selectedCharacter); - var increment = motionArgs.forward ? -1 : 1; - recordLastCharacterSearch(increment, motionArgs); - if (!curEnd) return null; - curEnd.ch += increment; - return curEnd; - }, - moveToCharacter: function (cm, head, motionArgs) { - var repeat = motionArgs.repeat; - recordLastCharacterSearch(0, motionArgs); - logger.debug('moveToCharacter:', motionArgs); - return moveToCharacter(cm, repeat, motionArgs.forward, motionArgs.selectedCharacter) || head; - }, - moveToSymbol: function (cm, head, motionArgs) { - var repeat = motionArgs.repeat; - return findSymbol(cm, repeat, motionArgs.forward, motionArgs.selectedCharacter) || head; - }, - moveToColumn: function (cm, head, motionArgs, vim) { - var repeat = motionArgs.repeat; - // repeat is equivalent to which column we want to move to! - vim.lastHPos = repeat - 1; - vim.lastHSPos = cm.charCoords(head, 'div').left; - return moveToColumn(cm, repeat); - }, - moveToEol: function (cm, head, motionArgs, vim) { - var cur = head; - vim.lastHPos = Infinity; - var retval = Pos(cur.line + motionArgs.repeat - 1, Infinity); - var end = cm.clipPos(retval); - end.ch--; - vim.lastHSPos = cm.charCoords(end, 'div').left; - return retval; - }, - moveToFirstNonWhiteSpaceCharacter: function (cm, head) { - // Go to the start of the line where the text begins, or the end for - // whitespace-only lines - var cursor = head; - return Pos(cursor.line, findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))); - }, - moveToMatchedSymbol: function (cm, head) { - var cursor = head; - var line = cursor.line; - var ch = cursor.ch; - var lineText = cm.getLine(line); - var symbol; - for (; ch < lineText.length; ch++) { - symbol = lineText.charAt(ch); - if (symbol && isMatchableSymbol(symbol)) { - var style = cm.getTokenTypeAt(Pos(line, ch + 1)); - if (style !== 'string' && style !== 'comment') { - break; - } - } - } - if (ch < lineText.length) { - var matched = cm.findMatchingBracket(Pos(line, ch)); - return matched.to; - } else { - return cursor; - } - }, - moveToStartOfLine: function (_cm, head) { - return Pos(head.line, 0); - }, - moveToLineOrEdgeOfDocument: function (cm, _head, motionArgs) { - var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine(); - if (motionArgs.repeatIsExplicit) { - lineNum = motionArgs.repeat - cm.getOption('firstLineNumber'); - } - return Pos(lineNum, findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))); - }, - textObjectManipulation: function (cm, head, motionArgs, vim) { - // TODO: lots of possible exceptions that can be thrown here. Try da( - // outside of a () block. - - // TODO: adding <> >< to this map doesn't work, presumably because - // they're operators - var mirroredPairs = { - '(': ')', - ')': '(', - '{': '}', - '}': '{', - '[': ']', - ']': '[' - }; - var selfPaired = { - "'": true, - '"': true - }; - var character = motionArgs.selectedCharacter; - // 'b' refers to '()' block. - // 'B' refers to '{}' block. - if (character == 'b') { - character = '('; - } else if (character == 'B') { - character = '{'; - } - - // Inclusive is the difference between a and i - // TODO: Instead of using the additional text object map to perform text - // object operations, merge the map into the defaultKeyMap and use - // motionArgs to define behavior. Define separate entries for 'aw', - // 'iw', 'a[', 'i[', etc. - var inclusive = !motionArgs.textObjectInner; - var tmp; - if (mirroredPairs[character]) { - tmp = selectCompanionObject(cm, head, character, inclusive); - } else if (selfPaired[character]) { - tmp = findBeginningAndEnd(cm, head, character, inclusive); - } else if (character === 'W') { - tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, true /** bigWord */); - } else if (character === 'w') { - tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, false /** bigWord */); - } else if (character === 'p') { - tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive); - motionArgs.linewise = true; - if (vim.visualMode) { - if (!vim.visualLine) { - vim.visualLine = true; - } - } else { - var operatorArgs = vim.inputState.operatorArgs; - if (operatorArgs) { - operatorArgs.linewise = true; - } - tmp.end.line--; - } - } else { - // No text object defined for this, don't move. - return null; - } - if (!cm.state.vim.visualMode) { - return [tmp.start, tmp.end]; - } else { - return expandSelection(cm, tmp.start, tmp.end); - } - }, - repeatLastCharacterSearch: function (cm, head, motionArgs) { - var lastSearch = vimGlobalState.lastCharacterSearch; - var repeat = motionArgs.repeat; - var forward = motionArgs.forward === lastSearch.forward; - var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1); - cm.moveH(-increment, 'char'); - motionArgs.inclusive = !!forward; - var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter); - if (!curEnd) { - cm.moveH(increment, 'char'); - return head; - } - curEnd.ch += increment; - return curEnd; - } - }; - function defineMotion(name, fn) { - motions[name] = fn; - } - function fillArray(val, times) { - var arr = []; - for (var i = 0; i < times; i++) { - arr.push(val); - } - return arr; - } - /** - * An operator acts on a text selection. It receives the list of selections - * as input. The corresponding CodeMirror selection is guaranteed to - * match the input selection. - */ - var operators = { - change: function (cm, args, ranges) { - var finalHead, text; - var vim = cm.state.vim; - vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock; - if (!vim.visualMode) { - var anchor = ranges[0].anchor, - head = ranges[0].head; - text = cm.getRange(anchor, head); - var lastState = vim.lastEditInputState || {}; - if (lastState.motion == 'moveByWords' && !isWhiteSpaceString(text)) { - // Exclude trailing whitespace if the range is not all whitespace. - var match = /\s+$/.exec(text); - if (match && lastState.motionArgs && lastState.motionArgs.forward) { - head = offsetCursor(head, 0, -match[0].length); - text = text.slice(0, -match[0].length); - } - } - var prevLineEnd = new Pos(anchor.line - 1, Number.MAX_VALUE); - var wasLastLine = cm.firstLine() == cm.lastLine(); - if (head.line > cm.lastLine() && args.linewise && !wasLastLine) { - cm.replaceRange('', prevLineEnd, head); - } else { - cm.replaceRange('', anchor, head); - } - if (args.linewise) { - // Push the next line back down, if there is a next line. - if (!wasLastLine) { - cm.setCursor(prevLineEnd); - CodeMirror.commands.newlineAndIndent(cm); - } - // make sure cursor ends up at the end of the line. - anchor.ch = Number.MAX_VALUE; - } - finalHead = anchor; - } else { - text = cm.getSelection(); - var replacement = fillArray('', ranges.length); - cm.replaceSelections(replacement); - finalHead = cursorMin(ranges[0].head, ranges[0].anchor); - } - vimGlobalState.registerController.pushText(args.registerName, 'change', text, args.linewise, ranges.length > 1); - actions.enterInsertMode(cm, { - head: finalHead - }, cm.state.vim); - }, - // delete is a javascript keyword. - delete: function (cm, args, ranges) { - var finalHead, text; - var vim = cm.state.vim; - if (!vim.visualBlock) { - var anchor = ranges[0].anchor, - head = ranges[0].head; - if (args.linewise && head.line != cm.firstLine() && anchor.line == cm.lastLine() && anchor.line == head.line - 1) { - // Special case for dd on last line (and first line). - if (anchor.line == cm.firstLine()) { - anchor.ch = 0; - } else { - anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1)); - } - } - text = cm.getRange(anchor, head); - cm.replaceRange('', anchor, head); - finalHead = anchor; - if (args.linewise) { - finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor); - } - } else { - text = cm.getSelection(); - var replacement = fillArray('', ranges.length); - cm.replaceSelections(replacement); - finalHead = ranges[0].anchor; - } - vimGlobalState.registerController.pushText(args.registerName, 'delete', text, args.linewise, vim.visualBlock); - var includeLineBreak = vim.insertMode; - return clipCursorToContent(cm, finalHead, includeLineBreak); - }, - indent: function (cm, args, ranges) { - var vim = cm.state.vim; - var startLine = ranges[0].anchor.line; - var endLine = vim.visualBlock ? ranges[ranges.length - 1].anchor.line : ranges[0].head.line; - // In visual mode, n> shifts the selection right n times, instead of - // shifting n lines right once. - var repeat = vim.visualMode ? args.repeat : 1; - if (args.linewise) { - // The only way to delete a newline is to delete until the start of - // the next line, so in linewise mode evalInput will include the next - // line. We don't want this in indent, so we go back a line. - endLine--; - } - for (var i = startLine; i <= endLine; i++) { - for (var j = 0; j < repeat; j++) { - cm.indentLine(i, args.indentRight); - } - } - return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor); - }, - changeCase: function (cm, args, ranges, oldAnchor, newHead) { - var selections = cm.getSelections(); - var swapped = []; - var toLower = args.toLower; - for (var j = 0; j < selections.length; j++) { - var toSwap = selections[j]; - var text = ''; - if (toLower === true) { - text = toSwap.toLowerCase(); - } else if (toLower === false) { - text = toSwap.toUpperCase(); - } else { - for (var i = 0; i < toSwap.length; i++) { - var character = toSwap.charAt(i); - text += isUpperCase(character) ? character.toLowerCase() : character.toUpperCase(); - } - } - swapped.push(text); - } - cm.replaceSelections(swapped); - if (args.shouldMoveCursor) { - return newHead; - } else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) { - return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor); - } else if (args.linewise) { - return oldAnchor; - } else { - return cursorMin(ranges[0].anchor, ranges[0].head); - } - }, - yank: function (cm, args, ranges, oldAnchor) { - var vim = cm.state.vim; - var text = cm.getSelection(); - var endPos = vim.visualMode ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor) : oldAnchor; - vimGlobalState.registerController.pushText(args.registerName, 'yank', text, args.linewise, vim.visualBlock); - return endPos; - } - }; - function defineOperator(name, fn) { - operators[name] = fn; - } - var actions = { - jumpListWalk: function (cm, actionArgs, vim) { - if (vim.visualMode) { - return; - } - var repeat = actionArgs.repeat; - var forward = actionArgs.forward; - var jumpList = vimGlobalState.jumpList; - var mark = jumpList.move(cm, forward ? repeat : -repeat); - var markPos = mark ? mark.find() : undefined; - markPos = markPos || cm.getCursor(); - cm.setCursor(markPos); - }, - scroll: function (cm, actionArgs, vim) { - if (vim.visualMode) { - return; - } - var repeat = actionArgs.repeat || 1; - var lineHeight = cm.defaultTextHeight(); - var top = cm.getScrollInfo().top; - var delta = lineHeight * repeat; - var newPos = actionArgs.forward ? top + delta : top - delta; - var cursor = copyCursor(cm.getCursor()); - var cursorCoords = cm.charCoords(cursor, 'local'); - if (actionArgs.forward) { - if (newPos > cursorCoords.top) { - cursor.line += (newPos - cursorCoords.top) / lineHeight; - cursor.line = Math.ceil(cursor.line); - cm.setCursor(cursor); - cursorCoords = cm.charCoords(cursor, 'local'); - cm.scrollTo(null, cursorCoords.top); - } else { - // Cursor stays within bounds. Just reposition the scroll window. - cm.scrollTo(null, newPos); - } - } else { - var newBottom = newPos + cm.getScrollInfo().clientHeight; - if (newBottom < cursorCoords.bottom) { - cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight; - cursor.line = Math.floor(cursor.line); - cm.setCursor(cursor); - cursorCoords = cm.charCoords(cursor, 'local'); - cm.scrollTo(null, cursorCoords.bottom - cm.getScrollInfo().clientHeight); - } else { - // Cursor stays within bounds. Just reposition the scroll window. - cm.scrollTo(null, newPos); - } - } - }, - scrollToCursor: function (cm, actionArgs) { - var lineNum = cm.getCursor().line; - var charCoords = cm.charCoords(Pos(lineNum, 0), 'local'); - var height = cm.getScrollInfo().clientHeight; - var y = charCoords.top; - var lineHeight = charCoords.bottom - y; - switch (actionArgs.position) { - case 'center': - y = y - height / 2 + lineHeight; - break; - case 'bottom': - y = y - height + lineHeight; - break; - } - cm.scrollTo(null, y); - }, - replayMacro: function (cm, actionArgs, vim) { - var registerName = actionArgs.selectedCharacter; - var repeat = actionArgs.repeat; - var macroModeState = vimGlobalState.macroModeState; - if (registerName == '@') { - registerName = macroModeState.latestRegister; - } - while (repeat--) { - executeMacroRegister(cm, vim, macroModeState, registerName); - } - }, - enterMacroRecordMode: function (cm, actionArgs) { - var macroModeState = vimGlobalState.macroModeState; - var registerName = actionArgs.selectedCharacter; - if (vimGlobalState.registerController.isValidRegister(registerName)) { - macroModeState.enterMacroRecordMode(cm, registerName); - } - }, - toggleOverwrite: function (cm) { - if (!cm.state.overwrite) { - cm.toggleOverwrite(true); - cm.setOption('keyMap', 'vim-replace'); - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'replace' - }); - } else { - cm.toggleOverwrite(false); - cm.setOption('keyMap', 'vim-insert'); - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'insert' - }); - } - }, - enterInsertMode: function (cm, actionArgs, vim) { - if (cm.getOption('readOnly')) { - return; - } - cm.getWrapperElement().classList.add('insert-mode'); - cm.getWrapperElement().classList.remove('visual-mode'); - cm.getWrapperElement().classList.remove('normal-mode'); - vim.insertMode = true; - vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1; - var insertAt = actionArgs ? actionArgs.insertAt : null; - var sel = vim.sel; - var head = actionArgs.head || cm.getCursor('head'); - var height = cm.listSelections().length; - if (insertAt == 'eol') { - head = Pos(head.line, lineLength(cm, head.line)); - } else if (insertAt == 'charAfter') { - head = offsetCursor(head, 0, 1); - } else if (insertAt == 'firstNonBlank') { - head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head); - } else if (insertAt == 'startOfSelectedArea') { - logger.debug('startOfSelectedArea:', vim.visualBlock); - logger.debug('sel:', JSON.stringify(sel, null, 2)); - if (!vim.visualBlock) { - if (sel.head.line < sel.anchor.line) { - head = sel.head; - } else { - head = Pos(sel.anchor.line, 0); - } - } else { - head = Pos(Math.min(sel.head.line, sel.anchor.line), Math.min(sel.head.ch, sel.anchor.ch)); - height = Math.abs(sel.head.line - sel.anchor.line) + 1; - } - } else if (insertAt == 'endOfSelectedArea') { - if (!vim.visualBlock) { - if (sel.head.line >= sel.anchor.line) { - head = offsetCursor(sel.head, 0, 1); - } else { - head = Pos(sel.anchor.line, 0); - } - } else { - head = Pos(Math.min(sel.head.line, sel.anchor.line), Math.max(sel.head.ch + 1, sel.anchor.ch)); - height = Math.abs(sel.head.line - sel.anchor.line) + 1; - } - } else if (insertAt == 'inplace') { - if (vim.visualMode) { - return; - } - } - cm.setOption('disableInput', false); - if (vim.visualMode) { - exitVisualMode(cm); - } - if (actionArgs && actionArgs.replace) { - // Handle Replace-mode as a special case of insert mode. - cm.toggleOverwrite(true); - cm.setOption('keyMap', 'vim-replace'); - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'replace' - }); - } else { - cm.toggleOverwrite(false); - cm.setOption('keyMap', 'vim-insert'); - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'insert' - }); - } - if (!vimGlobalState.macroModeState.isPlaying) { - // Only record if not replaying. - cm.on('change', onChange); - CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); - } - selectForInsert(cm, head, height); - }, - toggleVisualMode: function (cm, actionArgs, vim) { - logger.debug('toggleVisualMode', actionArgs); - var repeat = actionArgs.repeat; - var anchor = cm.getCursor(); - var head; - // TODO: The repeat should actually select number of characters/lines - // equal to the repeat times the size of the previous visual - // operation. - if (!vim.visualMode) { - // Entering visual mode - vim.visualMode = true; - vim.visualLine = !!actionArgs.linewise; - vim.visualBlock = !!actionArgs.blockwise; - head = clipCursorToContent(cm, Pos(anchor.line, anchor.ch + repeat - 1), true /** includeLineBreak */); - - vim.sel = { - anchor: anchor, - head: head - }; - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'visual', - subMode: vim.visualLine ? 'linewise' : vim.visualBlock ? 'blockwise' : '' - }); - updateCmSelection(cm); - updateMark(cm, vim, '<', cursorMin(anchor, head)); - updateMark(cm, vim, '>', cursorMax(anchor, head)); - } else if (vim.visualLine ^ actionArgs.linewise || vim.visualBlock ^ actionArgs.blockwise) { - // Toggling between modes - vim.visualLine = !!actionArgs.linewise; - vim.visualBlock = !!actionArgs.blockwise; - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'visual', - subMode: vim.visualLine ? 'linewise' : vim.visualBlock ? 'blockwise' : '' - }); - updateCmSelection(cm); - } else { - exitVisualMode(cm); - } - }, - reselectLastSelection: function (cm, _actionArgs, vim) { - var lastSelection = vim.lastSelection; - if (vim.visualMode) { - updateLastSelection(cm, vim); - } - if (lastSelection) { - var anchor = lastSelection.anchorMark.find(); - var head = lastSelection.headMark.find(); - if (!anchor || !head) { - // If the marks have been destroyed due to edits, do nothing. - return; - } - vim.sel = { - anchor: anchor, - head: head - }; - vim.visualMode = true; - vim.visualLine = lastSelection.visualLine; - vim.visualBlock = lastSelection.visualBlock; - updateCmSelection(cm); - updateMark(cm, vim, '<', cursorMin(anchor, head)); - updateMark(cm, vim, '>', cursorMax(anchor, head)); - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'visual', - subMode: vim.visualLine ? 'linewise' : vim.visualBlock ? 'blockwise' : '' - }); - } - }, - joinLines: function (cm, actionArgs, vim) { - var curStart, curEnd; - if (vim.visualMode) { - curStart = cm.getCursor('anchor'); - curEnd = cm.getCursor('head'); - if (cursorIsBefore(curEnd, curStart)) { - var tmp = curEnd; - curEnd = curStart; - curStart = tmp; - } - curEnd.ch = lineLength(cm, curEnd.line) - 1; - } else { - // Repeat is the number of lines to join. Minimum 2 lines. - var repeat = Math.max(actionArgs.repeat, 2); - curStart = cm.getCursor(); - curEnd = clipCursorToContent(cm, Pos(curStart.line + repeat - 1, Infinity)); - } - var finalCh = 0; - for (var i = curStart.line; i < curEnd.line; i++) { - finalCh = lineLength(cm, curStart.line); - var tmp = Pos(curStart.line + 1, lineLength(cm, curStart.line + 1)); - var text = cm.getRange(curStart, tmp); - text = text.replace(/\n\s*/g, ' '); - cm.replaceRange(text, curStart, tmp); - } - var curFinalPos = Pos(curStart.line, finalCh); - if (vim.visualMode) { - exitVisualMode(cm, false); - } - cm.setCursor(curFinalPos); - }, - newLineAndEnterInsertMode: function (cm, actionArgs, vim) { - vim.insertMode = true; - var insertAt = copyCursor(cm.getCursor()); - if (insertAt.line === cm.firstLine() && !actionArgs.after) { - // Special case for inserting newline before start of document. - cm.replaceRange('\n', Pos(cm.firstLine(), 0)); - cm.setCursor(cm.firstLine(), 0); - } else { - insertAt.line = actionArgs.after ? insertAt.line : insertAt.line - 1; - insertAt.ch = lineLength(cm, insertAt.line); - cm.setCursor(insertAt); - var newlineFn = CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent; - newlineFn(cm); - } - this.enterInsertMode(cm, { - repeat: actionArgs.repeat - }, vim); - }, - paste: function (cm, actionArgs, vim) { - var cur = copyCursor(cm.getCursor()); - var register = vimGlobalState.registerController.getRegister(actionArgs.registerName); - var text = register.toString(); - if (!text) { - return; - } - if (actionArgs.matchIndent) { - var tabSize = cm.getOption('tabSize'); - // length that considers tabs and tabSize - var whitespaceLength = function (str) { - var tabs = str.split('\t').length - 1; - var spaces = str.split(' ').length - 1; - return tabs * tabSize + spaces * 1; - }; - var currentLine = cm.getLine(cm.getCursor().line); - var indent = whitespaceLength(currentLine.match(/^\s*/)[0]); - // chomp last newline b/c don't want it to match /^\s*/gm - var chompedText = text.replace(/\n$/, ''); - var wasChomped = text !== chompedText; - var firstIndent = whitespaceLength(text.match(/^\s*/)[0]); - var text = chompedText.replace(/^\s*/gm, function (wspace) { - var newIndent = indent + (whitespaceLength(wspace) - firstIndent); - if (newIndent < 0) { - return ''; - } else if (cm.getOption('indentWithTabs')) { - var quotient = Math.floor(newIndent / tabSize); - return Array(quotient + 1).join('\t'); - } else { - return Array(newIndent + 1).join(' '); - } - }); - text += wasChomped ? '\n' : ''; - } - if (actionArgs.repeat > 1) { - var text = Array(actionArgs.repeat + 1).join(text); - } - var linewise = register.linewise; - var blockwise = register.blockwise; - if (linewise) { - if (vim.visualMode) { - text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n'; - } else if (actionArgs.after) { - // Move the newline at the end to the start instead, and paste just - // before the newline character of the line we are on right now. - text = '\n' + text.slice(0, text.length - 1); - cur.ch = lineLength(cm, cur.line); - } else { - cur.ch = 0; - } - } else { - if (blockwise) { - text = text.split('\n'); - for (var i = 0; i < text.length; i++) { - text[i] = text[i] == '' ? ' ' : text[i]; - } - } - cur.ch += actionArgs.after ? 1 : 0; - } - var curPosFinal; - var idx; - if (vim.visualMode) { - // save the pasted text for reselection if the need arises - vim.lastPastedText = text; - var lastSelectionCurEnd; - var selectedArea = getSelectedAreaRange(cm, vim); - var selectionStart = selectedArea[0]; - var selectionEnd = selectedArea[1]; - var selectedText = cm.getSelection(); - var selections = cm.listSelections(); - var emptyStrings = new Array(selections.length).join('1').split('1'); - // save the curEnd marker before it get cleared due to cm.replaceRange. - if (vim.lastSelection) { - lastSelectionCurEnd = vim.lastSelection.headMark.find(); - } - // push the previously selected text to unnamed register - vimGlobalState.registerController.unnamedRegister.setText(selectedText); - if (blockwise) { - // first delete the selected text - cm.replaceSelections(emptyStrings); - // Set new selections as per the block length of the yanked text - selectionEnd = Pos(selectionStart.line + text.length - 1, selectionStart.ch); - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); - cm.replaceSelections(text); - curPosFinal = selectionStart; - } else if (vim.visualBlock) { - cm.replaceSelections(emptyStrings); - cm.setCursor(selectionStart); - cm.replaceRange(text, selectionStart, selectionStart); - curPosFinal = selectionStart; - } else { - cm.replaceRange(text, selectionStart, selectionEnd); - curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1); - } - // restore the the curEnd marker - if (lastSelectionCurEnd) { - vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd); - } - if (linewise) { - curPosFinal.ch = 0; - } - } else { - if (blockwise) { - cm.setCursor(cur); - for (var i = 0; i < text.length; i++) { - var line = cur.line + i; - if (line > cm.lastLine()) { - cm.replaceRange('\n', Pos(line, 0)); - } - var lastCh = lineLength(cm, line); - if (lastCh < cur.ch) { - extendLineToColumn(cm, line, cur.ch); - } - } - cm.setCursor(cur); - selectBlock(cm, Pos(cur.line + text.length - 1, cur.ch)); - cm.replaceSelections(text); - curPosFinal = cur; - } else { - cm.replaceRange(text, cur); - // Now fine tune the cursor to where we want it. - if (linewise && actionArgs.after) { - curPosFinal = Pos(cur.line + 1, findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1))); - } else if (linewise && !actionArgs.after) { - curPosFinal = Pos(cur.line, findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line))); - } else if (!linewise && actionArgs.after) { - idx = cm.indexFromPos(cur); - curPosFinal = cm.posFromIndex(idx + text.length - 1); - } else { - idx = cm.indexFromPos(cur); - curPosFinal = cm.posFromIndex(idx + text.length); - } - } - } - if (vim.visualMode) { - exitVisualMode(cm, false); - } - cm.setCursor(curPosFinal); - }, - undo: function (cm, actionArgs) { - cm.operation(function () { - repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)(); - cm.setCursor(cm.getCursor('anchor')); - }); - }, - redo: function (cm, actionArgs) { - repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)(); - }, - setRegister: function (_cm, actionArgs, vim) { - vim.inputState.registerName = actionArgs.selectedCharacter; - }, - setMark: function (cm, actionArgs, vim) { - var markName = actionArgs.selectedCharacter; - updateMark(cm, vim, markName, cm.getCursor()); - }, - replace: function (cm, actionArgs, vim) { - var replaceWith = actionArgs.selectedCharacter; - var curStart = cm.getCursor(); - var replaceTo; - var curEnd; - var selections = cm.listSelections(); - if (vim.visualMode) { - curStart = cm.getCursor('start'); - curEnd = cm.getCursor('end'); - } else { - var line = cm.getLine(curStart.line); - replaceTo = curStart.ch + actionArgs.repeat; - if (replaceTo > line.length) { - replaceTo = line.length; - } - curEnd = Pos(curStart.line, replaceTo); - } - if (replaceWith == '\n') { - if (!vim.visualMode) cm.replaceRange('', curStart, curEnd) - // special case, where vim help says to replace by just one line-break - ; - (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm); - } else { - var replaceWithStr = cm.getRange(curStart, curEnd); - // replace all characters in range by selected, but keep linebreaks - replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith); - if (vim.visualBlock) { - // Tabs are split in visua block before replacing - var spaces = new Array(cm.getOption('tabSize') + 1).join(' '); - replaceWithStr = cm.getSelection(); - replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n'); - cm.replaceSelections(replaceWithStr); - } else { - cm.replaceRange(replaceWithStr, curStart, curEnd); - } - if (vim.visualMode) { - curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ? selections[0].anchor : selections[0].head; - cm.setCursor(curStart); - exitVisualMode(cm, false); - } else { - cm.setCursor(offsetCursor(curEnd, 0, -1)); - } - } - }, - incrementNumberToken: function (cm, actionArgs) { - var cur = cm.getCursor(); - var lineStr = cm.getLine(cur.line); - var re = /-?\d+/g; - var match; - var start; - var end; - var numberStr; - var token; - while ((match = re.exec(lineStr)) !== null) { - token = match[0]; - start = match.index; - end = start + token.length; - if (cur.ch < end) break; - } - if (!actionArgs.backtrack && end <= cur.ch) return; - if (token) { - var increment = actionArgs.increase ? 1 : -1; - var number = parseInt(token) + increment * actionArgs.repeat; - var from = Pos(cur.line, start); - var to = Pos(cur.line, end); - numberStr = number.toString(); - cm.replaceRange(numberStr, from, to); - } else { - return; - } - cm.setCursor(Pos(cur.line, start + numberStr.length - 1)); - }, - repeatLastEdit: function (cm, actionArgs, vim) { - var lastEditInputState = vim.lastEditInputState; - if (!lastEditInputState) { - return; - } - var repeat = actionArgs.repeat; - if (repeat && actionArgs.repeatIsExplicit) { - vim.lastEditInputState.repeatOverride = repeat; - } else { - repeat = vim.lastEditInputState.repeatOverride || repeat; - } - repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */); - }, - - indent: function (cm, actionArgs) { - cm.indentLine(cm.getCursor().line, actionArgs.indentRight); - }, - exitInsertMode: exitInsertMode - }; - function defineAction(name, fn) { - actions[name] = fn; - } - - /* - * Below are miscellaneous utility functions used by vim.js - */ - - /** - * Clips cursor to ensure that line is within the buffer's range - * If includeLineBreak is true, then allow cur.ch == lineLength. - */ - function clipCursorToContent(cm, cur, includeLineBreak) { - var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine()); - var maxCh = lineLength(cm, line) - 1; - maxCh = includeLineBreak ? maxCh + 1 : maxCh; - var ch = Math.min(Math.max(0, cur.ch), maxCh); - return Pos(line, ch); - } - function copyArgs(args) { - var ret = {}; - for (var prop in args) { - if (args.hasOwnProperty(prop)) { - ret[prop] = args[prop]; - } - } - return ret; - } - function offsetCursor(cur, offsetLine, offsetCh) { - if (typeof offsetLine === 'object') { - offsetCh = offsetLine.ch; - offsetLine = offsetLine.line; - } - return Pos(cur.line + offsetLine, cur.ch + offsetCh); - } - function getOffset(anchor, head) { - return { - line: head.line - anchor.line, - ch: head.line - anchor.line - }; - } - function commandMatches(keys, keyMap, context, inputState) { - // Partial matches are not applied. They inform the key handler - // that the current key sequence is a subsequence of a valid key - // sequence, so that the key buffer is not cleared. - var match, - partial = [], - full = []; - for (var i = 0; i < keyMap.length; i++) { - var command = keyMap[i]; - if (context == 'insert' && command.context != 'insert' || command.context && command.context != context || inputState.operator && command.type == 'action' || !(match = commandMatch(keys, command.keys))) { - continue; - } - if (match == 'partial') { - partial.push(command); - } - if (match == 'full') { - full.push(command); - } - } - return { - partial: partial.length && partial, - full: full.length && full - }; - } - function commandMatch(pressed, mapped) { - if (mapped.slice(-11) == '') { - // Last character matches anything. - var prefixLen = mapped.length - 11; - var pressedPrefix = pressed.slice(0, prefixLen); - var mappedPrefix = mapped.slice(0, prefixLen); - return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' : mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false; - } else { - return pressed == mapped ? 'full' : mapped.indexOf(pressed) == 0 ? 'partial' : false; - } - } - function lastChar(keys) { - var match = /^.*(<[^>]+>)$/.exec(keys); - var selectedCharacter = match ? match[1] : keys.slice(-1); - if (selectedCharacter.length > 1) { - switch (selectedCharacter) { - case '': - selectedCharacter = '\n'; - break; - case '': - selectedCharacter = ' '; - break; - default: - selectedCharacter = ''; - break; - } - } - return selectedCharacter; - } - function repeatFn(cm, fn, repeat) { - return function () { - for (var i = 0; i < repeat; i++) { - fn(cm); - } - }; - } - function copyCursor(cur) { - return Pos(cur.line, cur.ch); - } - function cursorEqual(cur1, cur2) { - return cur1.ch == cur2.ch && cur1.line == cur2.line; - } - function cursorIsBefore(cur1, cur2) { - if (cur1.line < cur2.line) { - return true; - } - if (cur1.line == cur2.line && cur1.ch < cur2.ch) { - return true; - } - return false; - } - function cursorMin(cur1, cur2) { - if (arguments.length > 2) { - cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1)); - } - return cursorIsBefore(cur1, cur2) ? cur1 : cur2; - } - function cursorMax(cur1, cur2) { - if (arguments.length > 2) { - cur2 = cursorMax.apply(undefined, Array.prototype.slice.call(arguments, 1)); - } - return cursorIsBefore(cur1, cur2) ? cur2 : cur1; - } - function cursorIsBetween(cur1, cur2, cur3) { - // returns true if cur2 is between cur1 and cur3. - var cur1before2 = cursorIsBefore(cur1, cur2); - var cur2before3 = cursorIsBefore(cur2, cur3); - return cur1before2 && cur2before3; - } - function lineLength(cm, lineNum) { - return cm.getLine(lineNum).length; - } - function trim(s) { - if (s.trim) { - return s.trim(); - } - return s.replace(/^\s+|\s+$/g, ''); - } - function escapeRegex(s) { - return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1'); - } - function extendLineToColumn(cm, lineNum, column) { - var endCh = lineLength(cm, lineNum); - var spaces = new Array(column - endCh + 1).join(' '); - cm.setCursor(Pos(lineNum, endCh)); - cm.replaceRange(spaces, cm.getCursor()); - } - // This functions selects a rectangular block - // of text with selectionEnd as any of its corner - // Height of block: - // Difference in selectionEnd.line and first/last selection.line - // Width of the block: - // Distance between selectionEnd.ch and any(first considered here) selection.ch - function selectBlock(cm, selectionEnd) { - var selections = [], - ranges = cm.listSelections(); - var head = copyCursor(cm.clipPos(selectionEnd)); - var isClipped = !cursorEqual(selectionEnd, head); - var curHead = cm.getCursor('head'); - var primIndex = getIndex(ranges, curHead); - var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor); - var max = ranges.length - 1; - var index = max - primIndex > primIndex ? max : 0; - var base = ranges[index].anchor; - var firstLine = Math.min(base.line, head.line); - var lastLine = Math.max(base.line, head.line); - var baseCh = base.ch, - headCh = head.ch; - var dir = ranges[index].head.ch - baseCh; - var newDir = headCh - baseCh; - if (dir > 0 && newDir <= 0) { - baseCh++; - if (!isClipped) { - headCh--; - } - } else if (dir < 0 && newDir >= 0) { - baseCh--; - if (!wasClipped) { - headCh++; - } - } else if (dir < 0 && newDir == -1) { - baseCh--; - headCh++; - } - for (var line = firstLine; line <= lastLine; line++) { - var range = { - anchor: new Pos(line, baseCh), - head: new Pos(line, headCh) - }; - selections.push(range); - } - cm.setSelections(selections); - selectionEnd.ch = headCh; - base.ch = baseCh; - return base; - } - function selectForInsert(cm, head, height) { - var sel = []; - for (var i = 0; i < height; i++) { - var lineHead = offsetCursor(head, i, 0); - sel.push({ - anchor: lineHead, - head: lineHead - }); - } - cm.setSelections(sel, 0); - } - // getIndex returns the index of the cursor in the selections. - function getIndex(ranges, cursor, end) { - for (var i = 0; i < ranges.length; i++) { - var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor); - var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor); - if (atAnchor || atHead) { - return i; - } - } - return -1; - } - function getSelectedAreaRange(cm, vim) { - var lastSelection = vim.lastSelection; - var getCurrentSelectedAreaRange = function () { - var selections = cm.listSelections(); - var start = selections[0]; - var end = selections[selections.length - 1]; - var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; - var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; - return [selectionStart, selectionEnd]; - }; - var getLastSelectedAreaRange = function () { - var selectionStart = cm.getCursor(); - var selectionEnd = cm.getCursor(); - var block = lastSelection.visualBlock; - if (block) { - var width = block.width; - var height = block.height; - selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width); - var selections = []; - // selectBlock creates a 'proper' rectangular block. - // We do not want that in all cases, so we manually set selections. - for (var i = selectionStart.line; i < selectionEnd.line; i++) { - var anchor = Pos(i, selectionStart.ch); - var head = Pos(i, selectionEnd.ch); - var range = { - anchor: anchor, - head: head - }; - selections.push(range); - } - cm.setSelections(selections); - } else { - var start = lastSelection.anchorMark.find(); - var end = lastSelection.headMark.find(); - var line = end.line - start.line; - var ch = end.ch - start.ch; - selectionEnd = { - line: selectionEnd.line + line, - ch: line ? selectionEnd.ch : ch + selectionEnd.ch - }; - if (lastSelection.visualLine) { - selectionStart = Pos(selectionStart.line, 0); - selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line)); - } - cm.setSelection(selectionStart, selectionEnd); - } - return [selectionStart, selectionEnd]; - }; - if (!vim.visualMode) { - // In case of replaying the action. - return getLastSelectedAreaRange(); - } else { - return getCurrentSelectedAreaRange(); - } - } - // Updates the previous selection with the current selection's values. This - // should only be called in visual mode. - function updateLastSelection(cm, vim) { - var anchor = vim.sel.anchor; - var head = vim.sel.head; - // To accommodate the effect of lastPastedText in the last selection - if (vim.lastPastedText) { - head = cm.posFromIndex(cm.indexFromPos(anchor) + vim.lastPastedText.length); - vim.lastPastedText = null; - } - vim.lastSelection = { - anchorMark: cm.setBookmark(anchor), - headMark: cm.setBookmark(head), - anchor: copyCursor(anchor), - head: copyCursor(head), - visualMode: vim.visualMode, - visualLine: vim.visualLine, - visualBlock: vim.visualBlock - }; - } - function expandSelection(cm, start, end) { - var sel = cm.state.vim.sel; - var head = sel.head; - var anchor = sel.anchor; - var tmp; - if (cursorIsBefore(end, start)) { - tmp = end; - end = start; - start = tmp; - } - if (cursorIsBefore(head, anchor)) { - head = cursorMin(start, head); - anchor = cursorMax(anchor, end); - } else { - anchor = cursorMin(start, anchor); - head = cursorMax(head, end); - head = offsetCursor(head, 0, -1); - if (head.ch == -1 && head.line != cm.firstLine()) { - head = Pos(head.line - 1, lineLength(cm, head.line - 1)); - } - } - return [anchor, head]; - } - /** - * Updates the CodeMirror selection to match the provided vim selection. - * If no arguments are given, it uses the current vim selection state. - */ - function updateCmSelection(cm, sel, mode) { - var vim = cm.state.vim; - sel = sel || vim.sel; - var mode = mode || vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char'; - var cmSel = makeCmSelection(cm, sel, mode); - cm.setSelections(cmSel.ranges, cmSel.primary); - updateFakeCursor(cm); - } - function makeCmSelection(cm, sel, mode, exclusive) { - var head = copyCursor(sel.head); - var anchor = copyCursor(sel.anchor); - if (mode == 'char') { - var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; - var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; - head = offsetCursor(sel.head, 0, headOffset); - anchor = offsetCursor(sel.anchor, 0, anchorOffset); - return { - ranges: [{ - anchor: anchor, - head: head - }], - primary: 0 - }; - } else if (mode == 'line') { - if (!cursorIsBefore(sel.head, sel.anchor)) { - anchor.ch = 0; - var lastLine = cm.lastLine(); - if (head.line > lastLine) { - head.line = lastLine; - } - head.ch = lineLength(cm, head.line); - } else { - head.ch = 0; - anchor.ch = lineLength(cm, anchor.line); - } - return { - ranges: [{ - anchor: anchor, - head: head - }], - primary: 0 - }; - } else if (mode == 'block') { - var top = Math.min(anchor.line, head.line), - left = Math.min(anchor.ch, head.ch), - bottom = Math.max(anchor.line, head.line), - right = Math.max(anchor.ch, head.ch) + 1; - var height = bottom - top + 1; - var primary = head.line == top ? 0 : height - 1; - var ranges = []; - for (var i = 0; i < height; i++) { - ranges.push({ - anchor: Pos(top + i, left), - head: Pos(top + i, right) - }); - } - return { - ranges: ranges, - primary: primary - }; - } - } - function getHead(cm) { - var cur = cm.getCursor('head'); - if (cm.getSelection().length == 1) { - // Small corner case when only 1 character is selected. The "real" - // head is the left of head and anchor. - cur = cursorMin(cur, cm.getCursor('anchor')); - } - return cur; - } - - /** - * If moveHead is set to false, the CodeMirror selection will not be - * touched. The caller assumes the responsibility of putting the cursor - * in the right place. - */ - function exitVisualMode(cm, moveHead) { - var vim = cm.state.vim; - if (moveHead !== false) { - cm.setCursor(clipCursorToContent(cm, vim.sel.head)); - } - updateLastSelection(cm, vim); - vim.visualMode = false; - vim.visualLine = false; - vim.visualBlock = false; - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'normal' - }); - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } - } - - // Remove any trailing newlines from the selection. For - // example, with the caret at the start of the last word on the line, - // 'dw' should word, but not the newline, while 'w' should advance the - // caret to the first character of the next line. - function clipToLine(cm, curStart, curEnd) { - var selection = cm.getRange(curStart, curEnd); - // Only clip if the selection ends with trailing newline + whitespace - if (/\n\s*$/.test(selection)) { - var lines = selection.split('\n'); - // We know this is all whitespace. - lines.pop(); - - // Cases: - // 1. Last word is an empty line - do not clip the trailing '\n' - // 2. Last word is not an empty line - clip the trailing '\n' - var line; - // Find the line containing the last word, and clip all whitespace up - // to it. - for (var line = lines.pop(); lines.length > 0 && line && isWhiteSpaceString(line); line = lines.pop()) { - curEnd.line--; - curEnd.ch = 0; - } - // If the last word is not an empty line, clip an additional newline - if (line) { - curEnd.line--; - curEnd.ch = lineLength(cm, curEnd.line); - } else { - curEnd.ch = 0; - } - } - } - - // Expand the selection to line ends. - function expandSelectionToLine(_cm, curStart, curEnd) { - curStart.ch = 0; - curEnd.ch = 0; - curEnd.line++; - } - function findFirstNonWhiteSpaceCharacter(text) { - if (!text) { - return 0; - } - var firstNonWS = text.search(/\S/); - return firstNonWS == -1 ? text.length : firstNonWS; - } - function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) { - var cur = getHead(cm); - var line = cm.getLine(cur.line); - var idx = cur.ch; - - // Seek to first word or non-whitespace character, depending on if - // noSymbol is true. - var test = noSymbol ? wordCharTest[0] : bigWordCharTest[0]; - while (!test(line.charAt(idx))) { - idx++; - if (idx >= line.length) { - return null; - } - } - if (bigWord) { - test = bigWordCharTest[0]; - } else { - test = wordCharTest[0]; - if (!test(line.charAt(idx))) { - test = wordCharTest[1]; - } - } - var end = idx, - start = idx; - while (test(line.charAt(end)) && end < line.length) { - end++; - } - while (test(line.charAt(start)) && start >= 0) { - start--; - } - start++; - if (inclusive) { - // If present, include all whitespace after word. - // Otherwise, include all whitespace before word, except indentation. - var wordEnd = end; - while (/\s/.test(line.charAt(end)) && end < line.length) { - end++; - } - if (wordEnd == end) { - var wordStart = start; - while (/\s/.test(line.charAt(start - 1)) && start > 0) { - start--; - } - if (!start) { - start = wordStart; - } - } - } - return { - start: Pos(cur.line, start), - end: Pos(cur.line, end) - }; - } - function recordJumpPosition(cm, oldCur, newCur) { - if (!cursorEqual(oldCur, newCur)) { - vimGlobalState.jumpList.add(cm, oldCur, newCur); - } - } - function recordLastCharacterSearch(increment, args) { - vimGlobalState.lastCharacterSearch.increment = increment; - vimGlobalState.lastCharacterSearch.forward = args.forward; - vimGlobalState.lastCharacterSearch.selectedCharacter = args.selectedCharacter; - } - var symbolToMode = { - '(': 'bracket', - ')': 'bracket', - '{': 'bracket', - '}': 'bracket', - '[': 'section', - ']': 'section', - '*': 'comment', - '/': 'comment', - m: 'method', - M: 'method', - '#': 'preprocess' - }; - var findSymbolModes = { - bracket: { - isComplete: function (state) { - if (state.nextCh === state.symb) { - state.depth++; - if (state.depth >= 1) return true; - } else if (state.nextCh === state.reverseSymb) { - state.depth--; - } - return false; - } - }, - section: { - init: function (state) { - state.curMoveThrough = true; - state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}'; - }, - isComplete: function (state) { - return state.index === 0 && state.nextCh === state.symb; - } - }, - comment: { - isComplete: function (state) { - var found = state.lastCh === '*' && state.nextCh === '/'; - state.lastCh = state.nextCh; - return found; - } - }, - // TODO: The original Vim implementation only operates on level 1 and 2. - // The current implementation doesn't check for code block level and - // therefore it operates on any levels. - method: { - init: function (state) { - state.symb = state.symb === 'm' ? '{' : '}'; - state.reverseSymb = state.symb === '{' ? '}' : '{'; - }, - isComplete: function (state) { - if (state.nextCh === state.symb) return true; - return false; - } - }, - preprocess: { - init: function (state) { - state.index = 0; - }, - isComplete: function (state) { - if (state.nextCh === '#') { - var token = state.lineText.match(/#(\w+)/)[1]; - if (token === 'endif') { - if (state.forward && state.depth === 0) { - return true; - } - state.depth++; - } else if (token === 'if') { - if (!state.forward && state.depth === 0) { - return true; - } - state.depth--; - } - if (token === 'else' && state.depth === 0) return true; - } - return false; - } - } - }; - function findSymbol(cm, repeat, forward, symb) { - var cur = copyCursor(cm.getCursor()); - var increment = forward ? 1 : -1; - var endLine = forward ? cm.lineCount() : -1; - var curCh = cur.ch; - var line = cur.line; - var lineText = cm.getLine(line); - var state = { - lineText: lineText, - nextCh: lineText.charAt(curCh), - lastCh: null, - index: curCh, - symb: symb, - reverseSymb: (forward ? { - ')': '(', - '}': '{' - } : { - '(': ')', - '{': '}' - })[symb], - forward: forward, - depth: 0, - curMoveThrough: false - }; - var mode = symbolToMode[symb]; - if (!mode) return cur; - var init = findSymbolModes[mode].init; - var isComplete = findSymbolModes[mode].isComplete; - if (init) { - init(state); - } - while (line !== endLine && repeat) { - state.index += increment; - state.nextCh = state.lineText.charAt(state.index); - if (!state.nextCh) { - line += increment; - state.lineText = cm.getLine(line) || ''; - if (increment > 0) { - state.index = 0; - } else { - var lineLen = state.lineText.length; - state.index = lineLen > 0 ? lineLen - 1 : 0; - } - state.nextCh = state.lineText.charAt(state.index); - } - if (isComplete(state)) { - cur.line = line; - cur.ch = state.index; - repeat--; - } - } - if (state.nextCh || state.curMoveThrough) { - return Pos(line, state.index); - } - return cur; - } - - /** - * Returns the boundaries of the next word. If the cursor in the middle of - * the word, then returns the boundaries of the current word, starting at - * the cursor. If the cursor is at the start/end of a word, and we are going - * forward/backward, respectively, find the boundaries of the next word. - * - * @param {CodeMirror} cm CodeMirror object. - * @param {Cursor} cur The cursor position. - * @param {boolean} forward True to search forward. False to search - * backward. - * @param {boolean} bigWord True if punctuation count as part of the word. - * False if only [a-zA-Z0-9] characters count as part of the word. - * @param {boolean} emptyLineIsWord True if empty lines should be treated - * as words. - * @return {Object{from:number, to:number, line: number}} The boundaries of - * the word, or null if there are no more words. - */ - function findWord(cm, cur, forward, bigWord, emptyLineIsWord) { - var lineNum = cur.line; - var pos = cur.ch; - var line = cm.getLine(lineNum); - var dir = forward ? 1 : -1; - var charTests = bigWord ? bigWordCharTest : wordCharTest; - if (emptyLineIsWord && line == '') { - lineNum += dir; - line = cm.getLine(lineNum); - if (!isLine(cm, lineNum)) { - return null; - } - pos = forward ? 0 : line.length; - } - while (true) { - if (emptyLineIsWord && line == '') { - return { - from: 0, - to: 0, - line: lineNum - }; - } - var stop = dir > 0 ? line.length : -1; - var wordStart = stop, - wordEnd = stop; - // Find bounds of next word. - while (pos != stop) { - var foundWord = false; - for (var i = 0; i < charTests.length && !foundWord; ++i) { - if (charTests[i](line.charAt(pos))) { - wordStart = pos; - // Advance to end of word. - while (pos != stop && charTests[i](line.charAt(pos))) { - pos += dir; - } - wordEnd = pos; - foundWord = wordStart != wordEnd; - if (wordStart == cur.ch && lineNum == cur.line && wordEnd == wordStart + dir) { - // We started at the end of a word. Find the next one. - continue; - } else { - return { - from: Math.min(wordStart, wordEnd + 1), - to: Math.max(wordStart, wordEnd), - line: lineNum - }; - } - } - } - if (!foundWord) { - pos += dir; - } - } - // Advance to next/prev line. - lineNum += dir; - if (!isLine(cm, lineNum)) { - return null; - } - line = cm.getLine(lineNum); - pos = dir > 0 ? 0 : line.length; - } - } - - /** - * @param {CodeMirror} cm CodeMirror object. - * @param {Pos} cur The position to start from. - * @param {int} repeat Number of words to move past. - * @param {boolean} forward True to search forward. False to search - * backward. - * @param {boolean} wordEnd True to move to end of word. False to move to - * beginning of word. - * @param {boolean} bigWord True if punctuation count as part of the word. - * False if only alphabet characters count as part of the word. - * @return {Cursor} The position the cursor should move to. - */ - function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) { - var curStart = copyCursor(cur); - var words = []; - if (forward && !wordEnd || !forward && wordEnd) { - repeat++; - } - // For 'e', empty lines are not considered words, go figure. - var emptyLineIsWord = !(forward && wordEnd); - for (var i = 0; i < repeat; i++) { - var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord); - if (!word) { - var eodCh = lineLength(cm, cm.lastLine()); - words.push(forward ? { - line: cm.lastLine(), - from: eodCh, - to: eodCh - } : { - line: 0, - from: 0, - to: 0 - }); - break; - } - words.push(word); - cur = Pos(word.line, forward ? word.to - 1 : word.from); - } - var shortCircuit = words.length != repeat; - var firstWord = words[0]; - var lastWord = words.pop(); - if (forward && !wordEnd) { - // w - if (!shortCircuit && (firstWord.from != curStart.ch || firstWord.line != curStart.line)) { - // We did not start in the middle of a word. Discard the extra word at the end. - lastWord = words.pop(); - } - return Pos(lastWord.line, lastWord.from); - } else if (forward && wordEnd) { - return Pos(lastWord.line, lastWord.to - 1); - } else if (!forward && wordEnd) { - // ge - if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) { - // We did not start in the middle of a word. Discard the extra word at the end. - lastWord = words.pop(); - } - return Pos(lastWord.line, lastWord.to); - } else { - // b - return Pos(lastWord.line, lastWord.from); - } - } - function moveToCharacter(cm, repeat, forward, character) { - var cur = cm.getCursor(); - var start = cur.ch; - var idx; - for (var i = 0; i < repeat; i++) { - var line = cm.getLine(cur.line); - idx = charIdxInLine(start, line, character, forward, true); - if (idx == -1) { - return null; - } - start = idx; - } - return Pos(cm.getCursor().line, idx); - } - function moveToColumn(cm, repeat) { - // repeat is always >= 1, so repeat - 1 always corresponds - // to the column we want to go to. - var line = cm.getCursor().line; - return clipCursorToContent(cm, Pos(line, repeat - 1)); - } - function updateMark(cm, vim, markName, pos) { - if (!inArray(markName, validMarks)) { - return; - } - if (vim.marks[markName]) { - vim.marks[markName].clear(); - } - vim.marks[markName] = cm.setBookmark(pos); - } - function charIdxInLine(start, line, character, forward, includeChar) { - // Search for char in line. - // motion_options: {forward, includeChar} - // If includeChar = true, include it too. - // If forward = true, search forward, else search backwards. - // If char is not found on this line, do nothing - var idx; - if (forward) { - idx = line.indexOf(character, start + 1); - if (idx != -1 && !includeChar) { - idx -= 1; - } - } else { - idx = line.lastIndexOf(character, start - 1); - if (idx != -1 && !includeChar) { - idx += 1; - } - } - return idx; - } - function findParagraph(cm, head, repeat, dir, inclusive) { - var line = head.line; - var min = cm.firstLine(); - var max = cm.lastLine(); - var start, - end, - i = line; - function isEmpty(i) { - return !cm.getLine(i); - } - function isBoundary(i, dir, any) { - if (any) { - return isEmpty(i) != isEmpty(i + dir); - } - return !isEmpty(i) && isEmpty(i + dir); - } - if (dir) { - while (min <= i && i <= max && repeat > 0) { - if (isBoundary(i, dir)) { - repeat--; - } - i += dir; - } - return new Pos(i, 0); - } - var vim = cm.state.vim; - if (vim.visualLine && isBoundary(line, 1, true)) { - var anchor = vim.sel.anchor; - if (isBoundary(anchor.line, -1, true)) { - if (!inclusive || anchor.line != line) { - line += 1; - } - } - } - var startState = isEmpty(line); - for (i = line; i <= max && repeat; i++) { - if (isBoundary(i, 1, true)) { - if (!inclusive || isEmpty(i) != startState) { - repeat--; - } - } - } - end = new Pos(i, 0); - // select boundary before paragraph for the last one - if (i > max && !startState) { - startState = true; - } else { - inclusive = false; - } - for (i = line; i > min; i--) { - if (!inclusive || isEmpty(i) == startState || i == line) { - if (isBoundary(i, -1, true)) { - break; - } - } - } - start = new Pos(i, 0); - return { - start: start, - end: end - }; - } - - // TODO: perhaps this finagling of start and end positions belonds - // in codemirror/replaceRange? - function selectCompanionObject(cm, head, symb, inclusive) { - var cur = head, - start, - end; - var bracketRegexp = { - '(': /[()]/, - ')': /[()]/, - '[': /[[\]]/, - ']': /[[\]]/, - '{': /[{}]/, - '}': /[{}]/ - }[symb]; - var openSym = { - '(': '(', - ')': '(', - '[': '[', - ']': '[', - '{': '{', - '}': '{' - }[symb]; - var curChar = cm.getLine(cur.line).charAt(cur.ch); - // Due to the behavior of scanForBracket, we need to add an offset if the - // cursor is on a matching open bracket. - var offset = curChar === openSym ? 1 : 0; - start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, undefined, { - bracketRegex: bracketRegexp - }); - end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, undefined, { - bracketRegex: bracketRegexp - }); - if (!start || !end) { - return { - start: cur, - end: cur - }; - } - start = start.pos; - end = end.pos; - if (start.line == end.line && start.ch > end.ch || start.line > end.line) { - var tmp = start; - start = end; - end = tmp; - } - if (inclusive) { - end.ch += 1; - } else { - start.ch += 1; - } - return { - start: start, - end: end - }; - } - - // Takes in a symbol and a cursor and tries to simulate text objects that - // have identical opening and closing symbols - // TODO support across multiple lines - function findBeginningAndEnd(cm, head, symb, inclusive) { - var cur = copyCursor(head); - var line = cm.getLine(cur.line); - var chars = line.split(''); - var start, end, i, len; - var firstIndex = chars.indexOf(symb); - - // the decision tree is to always look backwards for the beginning first, - // but if the cursor is in front of the first instance of the symb, - // then move the cursor forward - if (cur.ch < firstIndex) { - cur.ch = firstIndex; - // Why is this line even here??? - // cm.setCursor(cur.line, firstIndex+1); - } - // otherwise if the cursor is currently on the closing symbol - else if (firstIndex < cur.ch && chars[cur.ch] == symb) { - end = cur.ch; // assign end to the current cursor - --cur.ch; // make sure to look backwards - } - - // if we're currently on the symbol, we've got a start - if (chars[cur.ch] == symb && !end) { - start = cur.ch + 1; // assign start to ahead of the cursor - } else { - // go backwards to find the start - for (i = cur.ch; i > -1 && !start; i--) { - if (chars[i] == symb) { - start = i + 1; - } - } - } - - // look forwards for the end symbol - if (start && !end) { - for (i = start, len = chars.length; i < len && !end; i++) { - if (chars[i] == symb) { - end = i; - } - } - } - - // nothing found - if (!start || !end) { - return { - start: cur, - end: cur - }; - } - - // include the symbols - if (inclusive) { - --start; - ++end; - } - return { - start: Pos(cur.line, start), - end: Pos(cur.line, end) - }; - } - - // Search functions - defineOption('pcre', true, 'boolean'); - function SearchState() {} - SearchState.prototype = { - getQuery: function () { - return vimGlobalState.query; - }, - setQuery: function (query) { - vimGlobalState.query = query; - }, - getOverlay: function () { - return this.searchOverlay; - }, - setOverlay: function (overlay) { - this.searchOverlay = overlay; - }, - isReversed: function () { - return vimGlobalState.isReversed; - }, - setReversed: function (reversed) { - vimGlobalState.isReversed = reversed; - }, - getScrollbarAnnotate: function () { - return this.annotate; - }, - setScrollbarAnnotate: function (annotate) { - this.annotate = annotate; - } - }; - function getSearchState(cm) { - var vim = cm.state.vim; - return vim.searchState_ || (vim.searchState_ = new SearchState()); - } - function dialog(cm, template, shortText, onClose, options) { - if (cm.openDialog) { - cm.openDialog(template, onClose, { - bottom: true, - value: options.value, - onKeyDown: options.onKeyDown, - onKeyUp: options.onKeyUp, - selectValueOnOpen: false - }); - } else { - onClose(prompt(shortText, '')); - } - } - function splitBySlash(argString) { - var slashes = findUnescapedSlashes(argString) || []; - if (!slashes.length) return []; - var tokens = []; - // in case of strings like foo/bar - if (slashes[0] !== 0) return; - for (var i = 0; i < slashes.length; i++) { - if (typeof slashes[i] === 'number') { - tokens.push(argString.substring(slashes[i] + 1, slashes[i + 1])); - } - } - return tokens; - } - function findUnescapedSlashes(str) { - var escapeNextChar = false; - var slashes = []; - for (var i = 0; i < str.length; i++) { - var c = str.charAt(i); - if (!escapeNextChar && c == '/') { - slashes.push(i); - } - escapeNextChar = !escapeNextChar && c == '\\'; - } - return slashes; - } - - // Translates a search string from ex (vim) syntax into javascript form. - function translateRegex(str) { - // When these match, add a '\' if unescaped or remove one if escaped. - var specials = '|(){'; - // Remove, but never add, a '\' for these. - var unescape = '}'; - var escapeNextChar = false; - var out = []; - for (var i = -1; i < str.length; i++) { - var c = str.charAt(i) || ''; - var n = str.charAt(i + 1) || ''; - var specialComesNext = n && specials.indexOf(n) != -1; - if (escapeNextChar) { - if (c !== '\\' || !specialComesNext) { - out.push(c); - } - escapeNextChar = false; - } else { - if (c === '\\') { - escapeNextChar = true; - // Treat the unescape list as special for removing, but not adding '\'. - if (n && unescape.indexOf(n) != -1) { - specialComesNext = true; - } - // Not passing this test means removing a '\'. - if (!specialComesNext || n === '\\') { - out.push(c); - } - } else { - out.push(c); - if (specialComesNext && n !== '\\') { - out.push('\\'); - } - } - } - } - return out.join(''); - } - - // Translates the replace part of a search and replace from ex (vim) syntax into - // javascript form. Similar to translateRegex, but additionally fixes back references - // (translates '\[0..9]' to '$[0..9]') and follows different rules for escaping '$'. - var charUnescapes = { - '\\n': '\n', - '\\r': '\r', - '\\t': '\t' - }; - function translateRegexReplace(str) { - var escapeNextChar = false; - var out = []; - for (var i = -1; i < str.length; i++) { - var c = str.charAt(i) || ''; - var n = str.charAt(i + 1) || ''; - if (charUnescapes[c + n]) { - out.push(charUnescapes[c + n]); - i++; - } else if (escapeNextChar) { - // At any point in the loop, escapeNextChar is true if the previous - // character was a '\' and was not escaped. - out.push(c); - escapeNextChar = false; - } else { - if (c === '\\') { - escapeNextChar = true; - if (isNumber(n) || n === '$') { - out.push('$'); - } else if (n !== '/' && n !== '\\') { - out.push('\\'); - } - } else { - if (c === '$') { - out.push('$'); - } - out.push(c); - if (n === '/') { - out.push('\\'); - } - } - } - } - return out.join(''); - } - - // Unescape \ and / in the replace part, for PCRE mode. - var unescapes = { - '\\/': '/', - '\\\\': '\\', - '\\n': '\n', - '\\r': '\r', - '\\t': '\t' - }; - function unescapeRegexReplace(str) { - var stream = new CodeMirror.StringStream(str); - var output = []; - while (!stream.eol()) { - // Search for \. - while (stream.peek() && stream.peek() != '\\') { - output.push(stream.next()); - } - var matched = false; - for (var matcher in unescapes) { - if (stream.match(matcher, true)) { - matched = true; - output.push(unescapes[matcher]); - break; - } - } - if (!matched) { - // Don't change anything - output.push(stream.next()); - } - } - return output.join(''); - } - - /** - * Extract the regular expression from the query and return a Regexp object. - * Returns null if the query is blank. - * If ignoreCase is passed in, the Regexp object will have the 'i' flag set. - * If smartCase is passed in, and the query contains upper case letters, - * then ignoreCase is overridden, and the 'i' flag will not be set. - * If the query contains the /i in the flag part of the regular expression, - * then both ignoreCase and smartCase are ignored, and 'i' will be passed - * through to the Regex object. - */ - function parseQuery(query, ignoreCase, smartCase) { - // First update the last search register - var lastSearchRegister = vimGlobalState.registerController.getRegister('/'); - lastSearchRegister.setText(query); - // Check if the query is already a regex. - if (query instanceof RegExp) { - return query; - } - // First try to extract regex + flags from the input. If no flags found, - // extract just the regex. IE does not accept flags directly defined in - // the regex string in the form /regex/flags - var slashes = findUnescapedSlashes(query); - var regexPart; - var forceIgnoreCase; - if (!slashes.length) { - // Query looks like 'regexp' - regexPart = query; - } else { - // Query looks like 'regexp/...' - regexPart = query.substring(0, slashes[0]); - var flagsPart = query.substring(slashes[0]); - forceIgnoreCase = flagsPart.indexOf('i') != -1; - } - if (!regexPart) { - return null; - } - if (!getOption('pcre')) { - regexPart = translateRegex(regexPart); - } - if (smartCase) { - ignoreCase = /^[^A-Z]*$/.test(regexPart); - } - var regexp = new RegExp(regexPart, ignoreCase || forceIgnoreCase ? 'i' : undefined); - return regexp; - } - function showConfirm(cm, text) { - if (cm.openNotification) { - cm.openNotification('' + text + '', { - bottom: true, - duration: 5000 - }); - } else { - alert(text); - } - } - function makePrompt(prefix, desc) { - var raw = '' + (prefix || '') + ''; - if (desc) { - raw += ' ' + desc + ''; - } - return raw; - } - var searchPromptDesc = '(Javascript regexp)'; - function showPrompt(cm, options) { - var shortText = (options.prefix || '') + ' ' + (options.desc || ''); - var prompt = makePrompt(options.prefix, options.desc); - dialog(cm, prompt, shortText, options.onClose, options); - } - function regexEqual(r1, r2) { - if (r1 instanceof RegExp && r2 instanceof RegExp) { - var props = ['global', 'multiline', 'ignoreCase', 'source']; - for (var i = 0; i < props.length; i++) { - var prop = props[i]; - if (r1[prop] !== r2[prop]) { - return false; - } - } - return true; - } - return false; - } - // Returns true if the query is valid. - function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) { - if (!rawQuery) { - return; - } - var state = getSearchState(cm); - var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase); - if (!query) { - return; - } - highlightSearchMatches(cm, query); - if (regexEqual(query, state.getQuery())) { - return query; - } - state.setQuery(query); - return query; - } - function searchOverlay(query) { - if (query.source.charAt(0) == '^') { - var matchSol = true; - } - return { - token: function (stream) { - if (matchSol && !stream.sol()) { - stream.skipToEnd(); - return; - } - var match = stream.match(query, false); - if (match) { - if (match[0].length == 0) { - // Matched empty string, skip to next. - stream.next(); - return 'searching'; - } - if (!stream.sol()) { - // Backtrack 1 to match \b - stream.backUp(1); - if (!query.exec(stream.next() + match[0])) { - stream.next(); - return null; - } - } - stream.match(query); - return 'searching'; - } - while (!stream.eol()) { - stream.next(); - if (stream.match(query, false)) break; - } - }, - query: query - }; - } - function highlightSearchMatches(cm, query) { - var searchState = getSearchState(cm); - var overlay = searchState.getOverlay(); - if (!overlay || query != overlay.query) { - if (overlay) { - cm.removeOverlay(overlay); - } - overlay = searchOverlay(query); - cm.addOverlay(overlay); - if (cm.showMatchesOnScrollbar) { - if (searchState.getScrollbarAnnotate()) { - searchState.getScrollbarAnnotate().clear(); - } - searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query)); - } - searchState.setOverlay(overlay); - } - } - function findNext(cm, prev, query, repeat) { - if (repeat === undefined) { - repeat = 1; - } - return cm.operation(function () { - var pos = cm.getCursor(); - var cursor = cm.getSearchCursor(query, pos); - for (var i = 0; i < repeat; i++) { - var found = cursor.find(prev); - if (i == 0 && found && cursorEqual(cursor.from(), pos)) { - found = cursor.find(prev); - } - if (!found) { - // SearchCursor may have returned null because it hit EOF, wrap - // around and try again. - cursor = cm.getSearchCursor(query, prev ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0)); - if (!cursor.find(prev)) { - return; - } - } - } - return cursor.from(); - }); - } - function clearSearchHighlight(cm) { - var state = getSearchState(cm); - cm.removeOverlay(getSearchState(cm).getOverlay()); - state.setOverlay(null); - if (state.getScrollbarAnnotate()) { - state.getScrollbarAnnotate().clear(); - state.setScrollbarAnnotate(null); - } - } - /** - * Check if pos is in the specified range, INCLUSIVE. - * Range can be specified with 1 or 2 arguments. - * If the first range argument is an array, treat it as an array of line - * numbers. Match pos against any of the lines. - * If the first range argument is a number, - * if there is only 1 range argument, check if pos has the same line - * number - * if there are 2 range arguments, then check if pos is in between the two - * range arguments. - */ - function isInRange(pos, start, end) { - if (typeof pos !== 'number') { - // Assume it is a cursor position. Get the line number. - pos = pos.line; - } - if (start instanceof Array) { - return inArray(pos, start); - } else { - if (end) { - return pos >= start && pos <= end; - } else { - return pos == start; - } - } - } - function getUserVisibleLines(cm) { - var scrollInfo = cm.getScrollInfo(); - var occludeToleranceTop = 6; - var occludeToleranceBottom = 10; - var from = cm.coordsChar({ - left: 0, - top: occludeToleranceTop + scrollInfo.top - }, 'local'); - var bottomY = scrollInfo.clientHeight - occludeToleranceBottom + scrollInfo.top; - var to = cm.coordsChar({ - left: 0, - top: bottomY - }, 'local'); - return { - top: from.line, - bottom: to.line - }; - } - function getMarkPos(cm, vim, markName) { - if (markName == "'") { - var history = cm.doc.history.done; - var event = history[history.length - 2]; - return event && event.ranges && event.ranges[0].head; - } - var mark = vim.marks[markName]; - return mark && mark.find(); - } - var ExCommandDispatcher = function () { - this.buildCommandMap_(); - }; - ExCommandDispatcher.prototype = { - processCommand: function (cm, input, opt_params) { - var that = this; - cm.operation(function () { - cm.curOp.isVimOp = true; - that._processCommand(cm, input, opt_params); - }); - }, - _processCommand: function (cm, input, opt_params) { - var vim = cm.state.vim; - var commandHistoryRegister = vimGlobalState.registerController.getRegister(':'); - var previousCommand = commandHistoryRegister.toString(); - if (vim.visualMode) { - exitVisualMode(cm); - } - var inputStream = new CodeMirror.StringStream(input); - // update ": with the latest command whether valid or invalid - commandHistoryRegister.setText(input); - var params = opt_params || {}; - params.input = input; - try { - this.parseInput_(cm, inputStream, params); - } catch (e) { - showConfirm(cm, e); - throw e; - } - var command; - var commandName; - if (!params.commandName) { - // If only a line range is defined, move to the line. - if (params.line !== undefined) { - commandName = 'move'; - } - } else { - command = this.matchCommand_(params.commandName); - if (command) { - commandName = command.name; - if (command.excludeFromCommandHistory) { - commandHistoryRegister.setText(previousCommand); - } - this.parseCommandArgs_(inputStream, params, command); - if (command.type == 'exToKey') { - // Handle Ex to Key mapping. - for (var i = 0; i < command.toKeys.length; i++) { - CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping'); - } - return; - } else if (command.type == 'exToEx') { - // Handle Ex to Ex mapping. - this.processCommand(cm, command.toInput); - return; - } - } - } - if (!commandName) { - showConfirm(cm, 'Not an editor command ":' + input + '"'); - return; - } - try { - exCommands[commandName](cm, params); - // Possibly asynchronous commands (e.g. substitute, which might have a - // user confirmation), are responsible for calling the callback when - // done. All others have it taken care of for them here. - if ((!command || !command.possiblyAsync) && params.callback) { - params.callback(); - } - } catch (e) { - showConfirm(cm, e); - throw e; - } - }, - parseInput_: function (cm, inputStream, result) { - inputStream.eatWhile(':'); - // Parse range. - if (inputStream.eat('%')) { - result.line = cm.firstLine(); - result.lineEnd = cm.lastLine(); - } else { - result.line = this.parseLineSpec_(cm, inputStream); - if (result.line !== undefined && inputStream.eat(',')) { - result.lineEnd = this.parseLineSpec_(cm, inputStream); - } - } - - // Parse command name. - var commandMatch = inputStream.match(/^(\w+)/); - if (commandMatch) { - result.commandName = commandMatch[1]; - } else { - result.commandName = inputStream.match(/.*/)[0]; - } - return result; - }, - parseLineSpec_: function (cm, inputStream) { - var numberMatch = inputStream.match(/^(\d+)/); - if (numberMatch) { - // Absolute line number plus offset (N+M or N-M) is probably a typo, - // not something the user actually wanted. (NB: vim does allow this.) - return parseInt(numberMatch[1], 10) - 1; - } - switch (inputStream.next()) { - case '.': - return this.parseLineSpecOffset_(inputStream, cm.getCursor().line); - case '$': - return this.parseLineSpecOffset_(inputStream, cm.lastLine()); - case "'": - var markName = inputStream.next(); - var markPos = getMarkPos(cm, cm.state.vim, markName); - if (!markPos) throw new Error('Mark not set'); - return this.parseLineSpecOffset_(inputStream, markPos.line); - case '-': - case '+': - inputStream.backUp(1); - // Offset is relative to current line if not otherwise specified. - return this.parseLineSpecOffset_(inputStream, cm.getCursor().line); - default: - inputStream.backUp(1); - return undefined; - } - }, - parseLineSpecOffset_: function (inputStream, line) { - var offsetMatch = inputStream.match(/^([+-])?(\d+)/); - if (offsetMatch) { - var offset = parseInt(offsetMatch[2], 10); - if (offsetMatch[1] == '-') { - line -= offset; - } else { - line += offset; - } - } - return line; - }, - parseCommandArgs_: function (inputStream, params, command) { - if (inputStream.eol()) { - return; - } - params.argString = inputStream.match(/.*/)[0]; - // Parse command-line arguments - var delim = command.argDelimiter || /\s+/; - var args = trim(params.argString).split(delim); - if (args.length && args[0]) { - params.args = args; - } - }, - matchCommand_: function (commandName) { - // Return the command in the command map that matches the shortest - // prefix of the passed in command name. The match is guaranteed to be - // unambiguous if the defaultExCommandMap's shortNames are set up - // correctly. (see @code{defaultExCommandMap}). - for (var i = commandName.length; i > 0; i--) { - var prefix = commandName.substring(0, i); - if (this.commandMap_[prefix]) { - var command = this.commandMap_[prefix]; - if (command.name.indexOf(commandName) === 0) { - return command; - } - } - } - return null; - }, - buildCommandMap_: function () { - this.commandMap_ = {}; - for (var i = 0; i < defaultExCommandMap.length; i++) { - var command = defaultExCommandMap[i]; - var key = command.shortName || command.name; - this.commandMap_[key] = command; - } - }, - map: function (lhs, rhs, ctx) { - if (lhs != ':' && lhs.charAt(0) == ':') { - if (ctx) { - throw Error('Mode not supported for ex mappings'); - } - var commandName = lhs.substring(1); - if (rhs != ':' && rhs.charAt(0) == ':') { - // Ex to Ex mapping - this.commandMap_[commandName] = { - name: commandName, - type: 'exToEx', - toInput: rhs.substring(1), - user: true - }; - } else { - // Ex to key mapping - this.commandMap_[commandName] = { - name: commandName, - type: 'exToKey', - toKeys: rhs, - user: true - }; - } - } else { - if (rhs != ':' && rhs.charAt(0) == ':') { - // Key to Ex mapping. - var mapping = { - keys: lhs, - type: 'keyToEx', - exArgs: { - input: rhs.substring(1) - } - }; - if (ctx) { - mapping.context = ctx; - } - defaultKeymap.unshift(mapping); - } else { - // Key to key mapping - var mapping = { - keys: lhs, - type: 'keyToKey', - toKeys: rhs - }; - if (ctx) { - mapping.context = ctx; - } - defaultKeymap.unshift(mapping); - } - } - }, - unmap: function (lhs, ctx) { - if (lhs != ':' && lhs.charAt(0) == ':') { - // Ex to Ex or Ex to key mapping - if (ctx) { - throw Error('Mode not supported for ex mappings'); - } - var commandName = lhs.substring(1); - if (this.commandMap_[commandName] && this.commandMap_[commandName].user) { - delete this.commandMap_[commandName]; - return; - } - } else { - // Key to Ex or key to key mapping - var keys = lhs; - for (var i = 0; i < defaultKeymap.length; i++) { - if (keys == defaultKeymap[i].keys && defaultKeymap[i].context === ctx) { - defaultKeymap.splice(i, 1); - return; - } - } - } - throw Error('No such mapping.'); - } - }; - var exCommands = { - colorscheme: function (cm, params) { - if (!params.args || params.args.length < 1) { - showConfirm(cm, cm.getOption('theme')); - return; - } - cm.setOption('theme', params.args[0]); - }, - map: function (cm, params, ctx) { - var mapArgs = params.args; - if (!mapArgs || mapArgs.length < 2) { - if (cm) { - showConfirm(cm, 'Invalid mapping: ' + params.input); - } - return; - } - exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx); - }, - imap: function (cm, params) { - this.map(cm, params, 'insert'); - }, - nmap: function (cm, params) { - this.map(cm, params, 'normal'); - }, - vmap: function (cm, params) { - this.map(cm, params, 'visual'); - }, - unmap: function (cm, params, ctx) { - var mapArgs = params.args; - if (!mapArgs || mapArgs.length < 1) { - if (cm) { - showConfirm(cm, 'No such mapping: ' + params.input); - } - return; - } - exCommandDispatcher.unmap(mapArgs[0], ctx); - }, - move: function (cm, params) { - commandDispatcher.processCommand(cm, cm.state.vim, { - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { - forward: false, - explicitRepeat: true, - linewise: true - }, - repeatOverride: params.line + 1 - }); - }, - set: function (cm, params) { - var setArgs = params.args; - // Options passed through to the setOption/getOption calls. May be passed in by the - // local/global versions of the set command - var setCfg = params.setCfg || {}; - if (!setArgs || setArgs.length < 1) { - if (cm) { - showConfirm(cm, 'Invalid mapping: ' + params.input); - } - return; - } - var expr = setArgs[0].split('='); - var optionName = expr[0]; - var value = expr[1]; - var forceGet = false; - if (optionName.charAt(optionName.length - 1) == '?') { - // If post-fixed with ?, then the set is actually a get. - if (value) { - throw Error('Trailing characters: ' + params.argString); - } - optionName = optionName.substring(0, optionName.length - 1); - forceGet = true; - } - if (value === undefined && optionName.substring(0, 2) == 'no') { - // To set boolean options to false, the option name is prefixed with - // 'no'. - optionName = optionName.substring(2); - value = false; - } - var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean'; - if (optionIsBoolean && value == undefined) { - // Calling set with a boolean option sets it to true. - value = true; - } - // If no value is provided, then we assume this is a get. - if (!optionIsBoolean && value === undefined || forceGet) { - var oldValue = getOption(optionName, cm, setCfg); - if (oldValue instanceof Error) { - showConfirm(cm, oldValue.message); - } else if (oldValue === true || oldValue === false) { - showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName); - } else { - showConfirm(cm, ' ' + optionName + '=' + oldValue); - } - } else { - var setOptionReturn = setOption(optionName, value, cm, setCfg); - if (setOptionReturn instanceof Error) { - showConfirm(cm, setOptionReturn.message); - } - } - }, - setlocal: function (cm, params) { - // setCfg is passed through to setOption - params.setCfg = { - scope: 'local' - }; - this.set(cm, params); - }, - setglobal: function (cm, params) { - // setCfg is passed through to setOption - params.setCfg = { - scope: 'global' - }; - this.set(cm, params); - }, - registers: function (cm, params) { - var regArgs = params.args; - var registers = vimGlobalState.registerController.registers; - var regInfo = '----------Registers----------

'; - if (!regArgs) { - for (var registerName in registers) { - var text = registers[registerName].toString(); - if (text.length) { - regInfo += '"' + registerName + ' ' + text + '
'; - } - } - } else { - var registerName; - regArgs = regArgs.join(''); - for (var i = 0; i < regArgs.length; i++) { - registerName = regArgs.charAt(i); - if (!vimGlobalState.registerController.isValidRegister(registerName)) { - continue; - } - var register = registers[registerName] || new Register(); - regInfo += '"' + registerName + ' ' + register.toString() + '
'; - } - } - showConfirm(cm, regInfo); - }, - sort: function (cm, params) { - var reverse, ignoreCase, unique, number, pattern; - function parseArgs() { - if (params.argString) { - var args = new CodeMirror.StringStream(params.argString); - if (args.eat('!')) { - reverse = true; - } - if (args.eol()) { - return; - } - if (!args.eatSpace()) { - return 'Invalid arguments'; - } - var opts = args.match(/([dinuox]+)?\s*(\/.+\/)?\s*/); - if (!opts && !args.eol()) { - return 'Invalid arguments'; - } - if (opts[1]) { - ignoreCase = opts[1].indexOf('i') != -1; - unique = opts[1].indexOf('u') != -1; - var decimal = opts[1].indexOf('d') != -1 || opts[1].indexOf('n') != -1 && 1; - var hex = opts[1].indexOf('x') != -1 && 1; - var octal = opts[1].indexOf('o') != -1 && 1; - if (decimal + hex + octal > 1) { - return 'Invalid arguments'; - } - number = decimal && 'decimal' || hex && 'hex' || octal && 'octal'; - } - if (opts[2]) { - pattern = new RegExp(opts[2].substr(1, opts[2].length - 2), ignoreCase ? 'i' : ''); - } - } - } - var err = parseArgs(); - if (err) { - showConfirm(cm, err + ': ' + params.argString); - return; - } - var lineStart = params.line || cm.firstLine(); - var lineEnd = params.lineEnd || params.line || cm.lastLine(); - if (lineStart == lineEnd) { - return; - } - var curStart = Pos(lineStart, 0); - var curEnd = Pos(lineEnd, lineLength(cm, lineEnd)); - var text = cm.getRange(curStart, curEnd).split('\n'); - var numberRegex = pattern || number == 'decimal' ? /(-?)([\d]+)/ : number == 'hex' ? /(-?)(?:0x)?([0-9a-f]+)/i : number == 'octal' ? /([0-7]+)/ : null; - var radix = number == 'decimal' ? 10 : number == 'hex' ? 16 : number == 'octal' ? 8 : null; - var numPart = [], - textPart = []; - if (number || pattern) { - for (var i = 0; i < text.length; i++) { - var matchPart = pattern ? text[i].match(pattern) : null; - if (matchPart && matchPart[0] != '') { - numPart.push(matchPart); - } else if (!pattern && numberRegex.exec(text[i])) { - numPart.push(text[i]); - } else { - textPart.push(text[i]); - } - } - } else { - textPart = text; - } - function compareFn(a, b) { - if (reverse) { - var tmp; - tmp = a; - a = b; - b = tmp; - } - if (ignoreCase) { - a = a.toLowerCase(); - b = b.toLowerCase(); - } - var anum = number && numberRegex.exec(a); - var bnum = number && numberRegex.exec(b); - if (!anum) { - return a < b ? -1 : 1; - } - anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix); - bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix); - return anum - bnum; - } - function comparePatternFn(a, b) { - if (reverse) { - var tmp; - tmp = a; - a = b; - b = tmp; - } - if (ignoreCase) { - a[0] = a[0].toLowerCase(); - b[0] = b[0].toLowerCase(); - } - return a[0] < b[0] ? -1 : 1; - } - numPart.sort(pattern ? comparePatternFn : compareFn); - if (pattern) { - for (var i = 0; i < numPart.length; i++) { - numPart[i] = numPart[i].input; - } - } else if (!number) { - textPart.sort(compareFn); - } - text = !reverse ? textPart.concat(numPart) : numPart.concat(textPart); - if (unique) { - // Remove duplicate lines - var textOld = text; - var lastLine; - text = []; - for (var i = 0; i < textOld.length; i++) { - if (textOld[i] != lastLine) { - text.push(textOld[i]); - } - lastLine = textOld[i]; - } - } - cm.replaceRange(text.join('\n'), curStart, curEnd); - }, - global: function (cm, params) { - // a global command is of the form - // :[range]g/pattern/[cmd] - // argString holds the string /pattern/[cmd] - var argString = params.argString; - if (!argString) { - showConfirm(cm, 'Regular Expression missing from global'); - return; - } - // range is specified here - var lineStart = params.line !== undefined ? params.line : cm.firstLine(); - var lineEnd = params.lineEnd || params.line || cm.lastLine(); - // get the tokens from argString - var tokens = splitBySlash(argString); - var regexPart = argString, - cmd; - if (tokens.length) { - regexPart = tokens[0]; - cmd = tokens.slice(1, tokens.length).join('/'); - } - if (regexPart) { - // If regex part is empty, then use the previous query. Otherwise - // use the regex part as the new query. - try { - updateSearchQuery(cm, regexPart, true /** ignoreCase */, true /** smartCase */); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + regexPart); - return; - } - } - // now that we have the regexPart, search for regex matches in the - // specified range of lines - var query = getSearchState(cm).getQuery(); - var matchedLines = [], - content = ''; - for (var i = lineStart; i <= lineEnd; i++) { - var matched = query.test(cm.getLine(i)); - if (matched) { - matchedLines.push(i + 1); - content += cm.getLine(i) + '
'; - } - } - // if there is no [cmd], just display the list of matched lines - if (!cmd) { - showConfirm(cm, content); - return; - } - var index = 0; - var nextCommand = function () { - if (index < matchedLines.length) { - var command = matchedLines[index] + cmd; - exCommandDispatcher.processCommand(cm, command, { - callback: nextCommand - }); - } - index++; - }; - nextCommand(); - }, - substitute: function (cm, params) { - if (!cm.getSearchCursor) { - throw new Error('Search feature not available. Requires searchcursor.js or ' + 'any other getSearchCursor implementation.'); - } - var argString = params.argString; - var tokens = argString ? splitBySlash(argString) : []; - var regexPart, - replacePart = '', - trailing, - flagsPart, - count; - var confirm = false; // Whether to confirm each replace. - var global = false; // True to replace all instances on a line, false to replace only 1. - if (tokens.length) { - regexPart = tokens[0]; - replacePart = tokens[1]; - if (regexPart && regexPart[regexPart.length - 1] === '$') { - regexPart = regexPart.slice(0, regexPart.length - 1) + '\\n'; - replacePart = replacePart ? replacePart + '\n' : '\n'; - } - if (replacePart !== undefined) { - if (getOption('pcre')) { - replacePart = unescapeRegexReplace(replacePart); - } else { - replacePart = translateRegexReplace(replacePart); - } - vimGlobalState.lastSubstituteReplacePart = replacePart; - } - trailing = tokens[2] ? tokens[2].split(' ') : []; - } else { - // either the argString is empty or its of the form ' hello/world' - // actually splitBySlash returns a list of tokens - // only if the string starts with a '/' - if (argString && argString.length) { - showConfirm(cm, 'Substitutions should be of the form ' + ':s/pattern/replace/'); - return; - } - } - // After the 3rd slash, we can have flags followed by a space followed - // by count. - if (trailing) { - flagsPart = trailing[0]; - count = parseInt(trailing[1]); - if (flagsPart) { - if (flagsPart.indexOf('c') != -1) { - confirm = true; - flagsPart.replace('c', ''); - } - if (flagsPart.indexOf('g') != -1) { - global = true; - flagsPart.replace('g', ''); - } - regexPart = regexPart + '/' + flagsPart; - } - } - if (regexPart) { - // If regex part is empty, then use the previous query. Otherwise use - // the regex part as the new query. - try { - updateSearchQuery(cm, regexPart, true /** ignoreCase */, true /** smartCase */); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + regexPart); - return; - } - } - replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart; - if (replacePart === undefined) { - showConfirm(cm, 'No previous substitute regular expression'); - return; - } - var state = getSearchState(cm); - var query = state.getQuery(); - var lineStart = params.line !== undefined ? params.line : cm.getCursor().line; - var lineEnd = params.lineEnd || lineStart; - if (lineStart == cm.firstLine() && lineEnd == cm.lastLine()) { - lineEnd = Infinity; - } - if (count) { - lineStart = lineEnd; - lineEnd = lineStart + count - 1; - } - var startPos = clipCursorToContent(cm, Pos(lineStart, 0)); - var cursor = cm.getSearchCursor(query, startPos); - doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback); - }, - redo: CodeMirror.commands.redo, - undo: CodeMirror.commands.undo, - write: function (cm) { - if (CodeMirror.commands.save) { - // If a save command is defined, call it. - CodeMirror.commands.save(cm); - } else if (cm.save) { - // Saves to text area if no save command is defined and cm.save() is available. - cm.save(); - } - }, - nohlsearch: function (cm) { - clearSearchHighlight(cm); - }, - yank: function (cm) { - var cur = copyCursor(cm.getCursor()); - var line = cur.line; - var lineText = cm.getLine(line); - vimGlobalState.registerController.pushText('0', 'yank', lineText, true, true); - }, - delmarks: function (cm, params) { - if (!params.argString || !trim(params.argString)) { - showConfirm(cm, 'Argument required'); - return; - } - var state = cm.state.vim; - var stream = new CodeMirror.StringStream(trim(params.argString)); - while (!stream.eol()) { - stream.eatSpace(); - - // Record the streams position at the beginning of the loop for use - // in error messages. - var count = stream.pos; - if (!stream.match(/[a-zA-Z]/, false)) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - var sym = stream.next(); - // Check if this symbol is part of a range - if (stream.match('-', true)) { - // This symbol is part of a range. - - // The range must terminate at an alphabetic character. - if (!stream.match(/[a-zA-Z]/, false)) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - var startMark = sym; - var finishMark = stream.next(); - // The range must terminate at an alphabetic character which - // shares the same case as the start of the range. - if (isLowerCase(startMark) && isLowerCase(finishMark) || isUpperCase(startMark) && isUpperCase(finishMark)) { - var start = startMark.charCodeAt(0); - var finish = finishMark.charCodeAt(0); - if (start >= finish) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - - // Because marks are always ASCII values, and we have - // determined that they are the same case, we can use - // their char codes to iterate through the defined range. - for (var j = 0; j <= finish - start; j++) { - var mark = String.fromCharCode(start + j); - delete state.marks[mark]; - } - } else { - showConfirm(cm, 'Invalid argument: ' + startMark + '-'); - return; - } - } else { - // This symbol is a valid mark, and is not part of a range. - delete state.marks[sym]; - } - } - } - }; - var exCommandDispatcher = new ExCommandDispatcher(); - - /** - * @param {CodeMirror} cm CodeMirror instance we are in. - * @param {boolean} confirm Whether to confirm each replace. - * @param {Cursor} lineStart Line to start replacing from. - * @param {Cursor} lineEnd Line to stop replacing at. - * @param {RegExp} query Query for performing matches with. - * @param {string} replaceWith Text to replace matches with. May contain $1, - * $2, etc for replacing captured groups using Javascript replace. - * @param {function()} callback A callback for when the replace is done. - */ - function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query, replaceWith, callback) { - // Set up all the functions. - cm.state.vim.exMode = true; - var done = false; - var lastPos = searchCursor.from(); - function replaceAll() { - cm.operation(function () { - while (!done) { - replace(); - next(); - } - stop(); - }); - } - function replace() { - var text = cm.getRange(searchCursor.from(), searchCursor.to()); - var newText = text.replace(query, replaceWith); - searchCursor.replace(newText); - } - function next() { - // The below only loops to skip over multiple occurrences on the same - // line when 'global' is not true. - while (searchCursor.findNext() && isInRange(searchCursor.from(), lineStart, lineEnd)) { - if (!global && lastPos && searchCursor.from().line == lastPos.line) { - continue; - } - cm.scrollIntoView(searchCursor.from(), 30); - cm.setSelection(searchCursor.from(), searchCursor.to()); - lastPos = searchCursor.from(); - done = false; - return; - } - done = true; - } - function stop(close) { - if (close) { - close(); - } - cm.focus(); - if (lastPos) { - cm.setCursor(lastPos); - var vim = cm.state.vim; - vim.exMode = false; - vim.lastHPos = vim.lastHSPos = lastPos.ch; - } - if (callback) { - callback(); - } - } - function onPromptKeyDown(e, _value, close) { - // Swallow all keys. - CodeMirror.e_stop(e); - var keyName = CodeMirror.keyName(e); - switch (keyName) { - case 'Y': - replace(); - next(); - break; - case 'N': - next(); - break; - case 'A': - // replaceAll contains a call to close of its own. We don't want it - // to fire too early or multiple times. - var savedCallback = callback; - callback = undefined; - cm.operation(replaceAll); - callback = savedCallback; - break; - case 'L': - replace(); - // fall through and exit. - case 'Q': - case 'Esc': - case 'Ctrl-C': - case 'Ctrl-[': - stop(close); - break; - } - if (done) { - stop(close); - } - return true; - } - - // Actually do replace. - next(); - if (done) { - showConfirm(cm, 'No matches for ' + query.source); - return; - } - if (!confirm) { - replaceAll(); - if (callback) { - callback(); - } - return; - } - showPrompt(cm, { - prefix: 'replace with ' + replaceWith + ' (y/n/a/q/l)', - onKeyDown: onPromptKeyDown - }); - } - CodeMirror.keyMap.vim = { - attach: attachVimMap, - detach: detachVimMap - // call: cmKey - }; - - function exitInsertMode(cm) { - var vim = cm.state.vim; - var macroModeState = vimGlobalState.macroModeState; - var insertModeChangeRegister = vimGlobalState.registerController.getRegister('.'); - var isPlaying = macroModeState.isPlaying; - var lastChange = macroModeState.lastInsertModeChanges; - // In case of visual block, the insertModeChanges are not saved as a - // single word, so we convert them to a single word - // so as to update the ". register as expected in real vim. - var text = []; - if (!isPlaying) { - var selLength = lastChange.inVisualBlock ? vim.lastSelection.visualBlock.height : 1; - var changes = lastChange.changes; - var text = []; - var i = 0; - // In case of multiple selections in blockwise visual, - // the inserted text, for example: 'foo', is stored as - // 'f', 'f', InsertModeKey 'o', 'o', 'o', 'o'. (if you have a block with 2 lines). - // We push the contents of the changes array as per the following: - // 1. In case of InsertModeKey, just increment by 1. - // 2. In case of a character, jump by selLength (2 in the example). - while (i < changes.length) { - // This loop will convert 'ffoooo' to 'foo'. - text.push(changes[i]); - if (changes[i] instanceof InsertModeKey) { - i++; - } else { - i += selLength; - } - } - lastChange.changes = text; - cm.off('change', onChange); - CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); - } - if (!isPlaying && vim.insertModeRepeat > 1) { - // Perform insert mode repeat for commands like 3,a and 3,o. - repeatLastEdit(cm, vim, vim.insertModeRepeat - 1, true /** repeatForInsert */); - - vim.lastEditInputState.repeatOverride = vim.insertModeRepeat; - } - delete vim.insertModeRepeat; - vim.insertMode = false; - cm.setCursor(cm.getCursor().line, cm.getCursor().ch - 1); - cm.setOption('keyMap', 'vim'); - cm.setOption('disableInput', true); - cm.toggleOverwrite(false); // exit replace mode if we were in it. - // update the ". register before exiting insert mode - insertModeChangeRegister.setText(lastChange.changes.join('')); - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'normal' - }); - if (macroModeState.isRecording) { - logInsertModeChange(macroModeState); - } - } - function _mapCommand(command) { - defaultKeymap.unshift(command); - } - function mapCommand(keys, type, name, args, extra) { - var command = { - keys: keys, - type: type - }; - command[type] = name; - command[type + 'Args'] = args; - for (var key in extra) { - command[key] = extra[key]; - } - _mapCommand(command); - } - - // The timeout in milliseconds for the two-character ESC keymap should be - // adjusted according to your typing speed to prevent false positives. - defineOption('insertModeEscKeysTimeout', 200, 'number'); - CodeMirror.keyMap['vim-insert'] = { - // TODO: override navigation keys so that Esc will cancel automatic - // indentation from o, O, i_ - // fallthrough: ['default'], - fallthrough: [], - attach: attachVimMap, - detach: detachVimMap - // call: cmKey - }; - - CodeMirror.keyMap['vim-replace'] = { - Backspace: 'goCharLeft', - fallthrough: ['vim-insert'], - attach: attachVimMap, - detach: detachVimMap - // call: cmKey - }; - - function executeMacroRegister(cm, vim, macroModeState, registerName) { - var register = vimGlobalState.registerController.getRegister(registerName); - if (registerName == ':') { - // Read-only register containing last Ex command. - if (register.keyBuffer[0]) { - exCommandDispatcher.processCommand(cm, register.keyBuffer[0]); - } - macroModeState.isPlaying = false; - return; - } - var keyBuffer = register.keyBuffer; - var imc = 0; - macroModeState.isPlaying = true; - macroModeState.replaySearchQueries = register.searchQueries.slice(0); - for (var i = 0; i < keyBuffer.length; i++) { - var text = keyBuffer[i]; - var match, key; - while (text) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - match = /<\w+-.+?>|<\w+>|./.exec(text); - key = match[0]; - text = text.substring(match.index + key.length); - CodeMirror.Vim.handleKey(cm, key, 'macro'); - if (vim.insertMode) { - var changes = register.insertModeChanges[imc++].changes; - vimGlobalState.macroModeState.lastInsertModeChanges.changes = changes; - repeatInsertModeChanges(cm, changes, 1); - exitInsertMode(cm); - } - } - } - macroModeState.isPlaying = false; - } - function logKey(macroModeState, key) { - if (macroModeState.isPlaying) { - return; - } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.pushText(key); - } - } - function logInsertModeChange(macroModeState) { - if (macroModeState.isPlaying) { - return; - } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register && register.pushInsertModeChanges) { - register.pushInsertModeChanges(macroModeState.lastInsertModeChanges); - } - } - function logSearchQuery(macroModeState, query) { - if (macroModeState.isPlaying) { - return; - } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register && register.pushSearchQuery) { - register.pushSearchQuery(query); - } - } - - /** - * Listens for changes made in insert mode. - * Should only be active in insert mode. - */ - function onChange(cm, changeObj) { - var macroModeState = vimGlobalState.macroModeState; - var lastChange = macroModeState.lastInsertModeChanges; - if (!macroModeState.isPlaying) { - while (changeObj) { - lastChange.expectCursorActivityForChange = true; - if (changeObj.origin == '+input' || changeObj.origin == 'paste' || changeObj.origin === undefined /* only in testing */) { - var text = changeObj.text.join('\n'); - if (lastChange.maybeReset) { - lastChange.changes = []; - lastChange.maybeReset = false; - } - if (cm.state.overwrite && !/\n/.test(text)) { - lastChange.changes.push([text]); - } else { - lastChange.changes.push(text); - } - } - // Change objects may be chained with next. - changeObj = changeObj.next; - } - } - } - - /** - * Listens for any kind of cursor activity on CodeMirror. - */ - function onCursorActivity(cm) { - var vim = cm.state.vim; - if (vim.insertMode) { - // Tracking cursor activity in insert mode (for macro support). - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { - return; - } - var lastChange = macroModeState.lastInsertModeChanges; - if (lastChange.expectCursorActivityForChange) { - lastChange.expectCursorActivityForChange = false; - } else { - // Cursor moved outside the context of an edit. Reset the change. - lastChange.maybeReset = true; - } - } else if (!cm.curOp.isVimOp) { - handleExternalSelection(cm, vim); - } - if (vim.visualMode) { - updateFakeCursor(cm); - } - } - function updateFakeCursor(cm) { - var vim = cm.state.vim; - var from = clipCursorToContent(cm, copyCursor(vim.sel.head)); - var to = offsetCursor(from, 0, 1); - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } - vim.fakeCursor = cm.markText(from, to, { - className: 'cm-animate-fat-cursor' - }); - } - function handleExternalSelection(cm, vim) { - var anchor = cm.getCursor('anchor'); - var head = cm.getCursor('head'); - // Enter or exit visual mode to match mouse selection. - if (vim.visualMode && !cm.somethingSelected()) { - exitVisualMode(cm, false); - } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) { - vim.visualMode = true; - vim.visualLine = false; - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'visual' - }); - } - if (vim.visualMode) { - // Bind CodeMirror selection model to vim selection model. - // Mouse selections are considered visual characterwise. - var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0; - var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0; - head = offsetCursor(head, 0, headOffset); - anchor = offsetCursor(anchor, 0, anchorOffset); - vim.sel = { - anchor: anchor, - head: head - }; - updateMark(cm, vim, '<', cursorMin(head, anchor)); - updateMark(cm, vim, '>', cursorMax(head, anchor)); - } else if (!vim.insertMode) { - // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse. - vim.lastHPos = cm.getCursor().ch; - } - } - - /** Wrapper for special keys pressed in insert mode */ - function InsertModeKey(keyName) { - this.keyName = keyName; - } - - /** - * Handles raw key down events from the text area. - * - Should only be active in insert mode. - * - For recording deletes in insert mode. - */ - function onKeyEventTargetKeyDown(e) { - var macroModeState = vimGlobalState.macroModeState; - var lastChange = macroModeState.lastInsertModeChanges; - var keyName = CodeMirror.keyName(e); - if (!keyName) { - return; - } - function onKeyFound() { - if (lastChange.maybeReset) { - lastChange.changes = []; - lastChange.maybeReset = false; - } - lastChange.changes.push(new InsertModeKey(keyName)); - return true; - } - if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) { - CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound); - } - } - - /** - * Repeats the last edit, which includes exactly 1 command and at most 1 - * insert. Operator and motion commands are read from lastEditInputState, - * while action commands are read from lastEditActionCommand. - * - * If repeatForInsert is true, then the function was called by - * exitInsertMode to repeat the insert mode changes the user just made. The - * corresponding enterInsertMode call was made with a count. - */ - function repeatLastEdit(cm, vim, repeat, repeatForInsert) { - var macroModeState = vimGlobalState.macroModeState; - macroModeState.isPlaying = true; - var isAction = !!vim.lastEditActionCommand; - var cachedInputState = vim.inputState; - function repeatCommand() { - if (isAction) { - commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand); - } else { - commandDispatcher.evalInput(cm, vim); - } - } - function repeatInsert(repeat) { - if (macroModeState.lastInsertModeChanges.changes.length > 0) { - // For some reason, repeat cw in desktop VIM does not repeat - // insert mode changes. Will conform to that behavior. - repeat = !vim.lastEditActionCommand ? 1 : repeat; - var changeObject = macroModeState.lastInsertModeChanges; - repeatInsertModeChanges(cm, changeObject.changes, repeat); - } - } - vim.inputState = vim.lastEditInputState; - if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) { - // o and O repeat have to be interlaced with insert repeats so that the - // insertions appear on separate lines instead of the last line. - for (var i = 0; i < repeat; i++) { - repeatCommand(); - repeatInsert(1); - } - } else { - if (!repeatForInsert) { - // Hack to get the cursor to end up at the right place. If I is - // repeated in insert mode repeat, cursor will be 1 insert - // change set left of where it should be. - repeatCommand(); - } - repeatInsert(repeat); - } - vim.inputState = cachedInputState; - if (vim.insertMode && !repeatForInsert) { - // Don't exit insert mode twice. If repeatForInsert is set, then we - // were called by an exitInsertMode call lower on the stack. - exitInsertMode(cm); - } - macroModeState.isPlaying = false; - } - function repeatInsertModeChanges(cm, changes, repeat) { - function keyHandler(binding) { - if (typeof binding === 'string') { - CodeMirror.commands[binding](cm); - } else { - binding(cm); - } - return true; - } - var head = cm.getCursor('head'); - var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; - if (inVisualBlock) { - // Set up block selection again for repeating the changes. - var vim = cm.state.vim; - var lastSel = vim.lastSelection; - var offset = getOffset(lastSel.anchor, lastSel.head); - selectForInsert(cm, head, offset.line + 1); - repeat = cm.listSelections().length; - cm.setCursor(head); - } - for (var i = 0; i < repeat; i++) { - if (inVisualBlock) { - cm.setCursor(offsetCursor(head, i, 0)); - } - for (var j = 0; j < changes.length; j++) { - var change = changes[j]; - if (change instanceof InsertModeKey) { - CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler); - } else if (typeof change === 'string') { - var cur = cm.getCursor(); - cm.replaceRange(change, cur, cur); - } else { - var start = cm.getCursor(); - var end = offsetCursor(start, 0, change[0].length); - cm.replaceRange(change[0], start, end); - } - } - } - if (inVisualBlock) { - cm.setCursor(offsetCursor(head, 0, 1)); - } - } - resetVimGlobalState(); - vimApi.commandDispatcher = commandDispatcher; - vimApi.exCommandDispatcher = exCommandDispatcher; - return vimApi; - }; - - // Initialize Vim and make it available as an API. - return CodeMirror.Vim = Vim(); -}; \ No newline at end of file diff --git a/lib/keymap.js.map b/lib/keymap.js.map deleted file mode 100644 index 3aa949f..0000000 --- a/lib/keymap.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"keymap.js","names":["logger","require","clipboard","module","exports","CodeMirror","defaultKeymap","_defaultKeymap","keys","type","toKeys","context","action","motion","motionArgs","linewise","toJumplist","forward","wordEnd","bigWord","inclusive","explicitRepeat","toFirstChar","repeatOffset","isEdit","actionArgs","after","matchIndent","sameLine","operator","operatorArgs","indentRight","toLower","operatorMotionArgs","visualLine","shouldMoveCursor","insertAt","interlaceInsertRepeat","blockwise","replace","position","increase","backtrack","textObjectInner","searchArgs","querySrc","wholeWordOnly","defaultExCommandMap","name","shortName","possiblyAsync","excludeFromCommandHistory","Pos","Vim","enterVimMode","cm","setOption","signal","mode","on","onCursorActivity","maybeInitVimState","getInputField","getOnPasteFn","leaveVimMode","off","state","vim","detachVimMap","next","keyMap","rmClass","getWrapperElement","attach","attachVimMap","prev","addClass","defineOption","val","getOption","Init","test","cmKey","key","undefined","vimKey","cmKeyToVimKey","cmd","findKey","modifiers","Shift","Ctrl","Alt","Cmd","Mod","specialKeys","Enter","Backspace","Delete","Insert","charAt","pieces","split","lastPiece","length","hasCharacter","i","piece","isUpperCase","toLowerCase","join","onPasteFn","insertMode","setCursor","offsetCursor","getCursor","actions","enterInsertMode","numberRegex","wordCharTest","isWordChar","ch","bigWordCharTest","makeKeyRange","start","size","push","String","fromCharCode","upperCaseAlphabet","lowerCaseAlphabet","numbers","validMarks","concat","validRegisters","isLine","line","firstLine","lastLine","isLowerCase","k","isMatchableSymbol","indexOf","isNumber","isWhiteSpaceString","inArray","arr","options","defaultValue","aliases","callback","Error","value","cfg","option","scope","local","createCircularJumpList","pointer","head","tail","buffer","Array","add","oldCur","newCur","current","curMark","useNextSlot","cursor","trashMark","clear","setBookmark","markPos","find","cursorEqual","move","offset","mark","inc","cachedCursor","createInsertModeChanges","c","changes","expectCursorActivityForChange","MacroModeState","latestRegister","isPlaying","isRecording","replaySearchQueries","onRecordingDone","lastInsertModeChanges","prototype","exitMacroRecordMode","macroModeState","vimGlobalState","enterMacroRecordMode","registerName","register","registerController","getRegister","openDialog","bottom","inputState","InputState","lastEditInputState","lastEditActionCommand","lastHPos","lastHSPos","lastMotion","marks","fakeCursor","insertModeRepeat","visualMode","visualBlock","lastSelection","lastPastedText","sel","resetVimGlobalState","searchQuery","searchIsReversed","lastSubstituteReplacePart","jumpList","lastCharacterSearch","increment","selectedCharacter","RegisterController","searchHistoryController","HistoryController","exCommandHistoryController","optionName","lastInsertModeKeyTimer","vimApi","buildKeyMap","getRegisterController","getVimGlobalState","suppressErrorLogging","InsertModeKey","map","lhs","rhs","ctx","exCommandDispatcher","unmap","defineEx","prefix","func","exCommands","commandMap_","handleKey","origin","command","handleMacroRecording","clearInputState","logKey","handleEsc","exitVisualMode","exitInsertMode","doKeyToKey","match","exec","substring","index","handleKeyInsertMode","keyBuffer","debug","keysAreChars","commandDispatcher","matchCommand","slice","thisMatch","window","clearTimeout","setTimeout","selections","listSelections","here","replaceRange","pop","handleKeyNonInsertMode","keysMatcher","pushRepeatDigit","operation","curOp","isVimOp","processCommand","e","console","handleEx","input","defineMotion","defineAction","defineOperator","mapCommand","_mapCommand","defineRegister","prefixRepeat","motionRepeat","n","getRepeat","repeat","parseInt","reason","Register","text","insertModeChanges","searchQueries","setText","pushText","pushInsertModeChanges","pushSearchQuery","query","toString","registers","unnamedRegister","isValidRegister","reg","writeText","shiftNumericRegisters_","append","historyBuffer","iterator","initialPrefix","nextMatch","up","dir","element","j","pushInput","splice","reset","matches","commandMatches","full","partial","bestMatch","character","lastChar","repeatOverride","processMotion","processOperator","processOperatorMotion","processAction","processSearch","processEx","copyArgs","evalInput","repeatIsExplicit","recordLastEdit","getSearchCursor","getSearchState","setReversed","promptPrefix","originalQuery","getQuery","originalScrollPos","getScrollInfo","handleQuery","ignoreCase","smartCase","updateSearchQuery","showConfirm","onPromptClose","scrollTo","left","top","logSearchQuery","onPromptKeyUp","close","keyName","target","selectionEnd","selectionStart","Math","min","parsedQuery","scrollIntoView","findNext","clearSearchHighlight","onPromptKeyDown","e_stop","focus","shift","showPrompt","onClose","desc","searchPromptDesc","onKeyUp","onKeyDown","word","expandWordUnderCursor","isKeyword","getLine","end","escapeRegex","exArgs","origHead","copyCursor","clipCursorToContent","origAnchor","anchor","oldHead","oldAnchor","newHead","newAnchor","noRepeat","motionResult","motions","recordJumpPosition","Infinity","updateCmSelection","updateMark","cursorIsBefore","lastSel","lineOffset","abs","chOffset","curStart","curEnd","cmSel","cursorMin","cursorMax","makeCmSelection","ranges","lineLength","tmp","expandSelectionToLine","clipToLine","exclusive","setSelections","primary","operatorMoveTo","operators","actionCommand","moveToTopLine","_head","getUserVisibleLines","findFirstNonWhiteSpaceCharacter","moveToMiddleLine","range","floor","moveToBottomLine","expandToLine","_cm","cur","isReversed","highlightSearchMatches","goToMark","pos","getMarkPos","moveToOtherHighlightedEnd","jumpToMark","best","isWrongDirection","equal","between","cursorIsBetween","moveByCharacters","moveByLines","endCh","moveByDisplayLines","moveByScroll","moveToColumn","moveToEol","first","last","moveToStartOfLine","charCoords","res","findPosV","hitSide","lastCharCoords","goalCoords","coordsChar","resCoords","moveByPage","moveByParagraph","findParagraph","scrollbox","clientHeight","defaultTextHeight","orig","dest","moveByWords","moveToWord","moveTillCharacter","moveToCharacter","recordLastCharacterSearch","moveToSymbol","findSymbol","retval","clipPos","moveToFirstNonWhiteSpaceCharacter","moveToMatchedSymbol","lineText","symbol","style","getTokenTypeAt","matched","findMatchingBracket","to","moveToLineOrEdgeOfDocument","lineNum","textObjectManipulation","mirroredPairs","selfPaired","selectCompanionObject","findBeginningAndEnd","expandSelection","repeatLastCharacterSearch","lastSearch","moveH","fn","fillArray","times","change","args","finalHead","inVisualBlock","getRange","lastState","prevLineEnd","Number","MAX_VALUE","wasLastLine","commands","newlineAndIndent","getSelection","replacement","replaceSelections","delete","includeLineBreak","indent","startLine","endLine","indentLine","changeCase","getSelections","swapped","toSwap","toUpperCase","yank","endPos","jumpListWalk","scroll","lineHeight","delta","newPos","cursorCoords","ceil","newBottom","scrollToCursor","height","y","replayMacro","executeMacroRegister","toggleOverwrite","overwrite","classList","remove","JSON","stringify","max","onChange","onKeyEventTargetKeyDown","selectForInsert","toggleVisualMode","subMode","reselectLastSelection","_actionArgs","updateLastSelection","anchorMark","headMark","joinLines","finalCh","curFinalPos","newLineAndEnterInsertMode","newlineFn","newlineAndIndentContinueComment","paste","tabSize","whitespaceLength","str","tabs","spaces","currentLine","chompedText","wasChomped","firstIndent","wspace","newIndent","quotient","curPosFinal","idx","lastSelectionCurEnd","selectedArea","getSelectedAreaRange","selectedText","emptyStrings","selectBlock","posFromIndex","indexFromPos","lastCh","extendLineToColumn","undo","repeatFn","redo","setRegister","setMark","markName","replaceWith","replaceTo","replaceWithStr","incrementNumberToken","lineStr","re","numberStr","token","number","from","repeatLastEdit","maxCh","ret","prop","hasOwnProperty","offsetLine","offsetCh","getOffset","commandMatch","pressed","mapped","prefixLen","pressedPrefix","mappedPrefix","cur1","cur2","arguments","apply","call","cur3","cur1before2","cur2before3","trim","s","column","isClipped","curHead","primIndex","getIndex","wasClipped","base","baseCh","headCh","newDir","lineHead","atAnchor","atHead","getCurrentSelectedAreaRange","getLastSelectedAreaRange","block","width","setSelection","updateFakeCursor","headOffset","anchorOffset","right","getHead","moveHead","selection","lines","firstNonWS","search","_forward","noSymbol","wordStart","symbolToMode","m","M","findSymbolModes","bracket","isComplete","nextCh","symb","depth","reverseSymb","section","init","curMoveThrough","comment","found","method","preprocess","lineCount","curCh","lineLen","findWord","emptyLineIsWord","charTests","stop","foundWord","words","eodCh","shortCircuit","firstWord","lastWord","charIdxInLine","includeChar","lastIndexOf","isEmpty","isBoundary","any","startState","bracketRegexp","openSym","curChar","scanForBracket","bracketRegex","chars","len","firstIndex","SearchState","setQuery","getOverlay","searchOverlay","setOverlay","overlay","reversed","getScrollbarAnnotate","annotate","setScrollbarAnnotate","searchState_","dialog","template","shortText","selectValueOnOpen","prompt","splitBySlash","argString","slashes","findUnescapedSlashes","tokens","escapeNextChar","translateRegex","specials","unescape","out","specialComesNext","charUnescapes","translateRegexReplace","unescapes","unescapeRegexReplace","stream","StringStream","output","eol","peek","matcher","parseQuery","lastSearchRegister","RegExp","regexPart","forceIgnoreCase","flagsPart","regexp","openNotification","duration","alert","makePrompt","raw","regexEqual","r1","r2","props","rawQuery","source","matchSol","sol","skipToEnd","backUp","searchState","removeOverlay","addOverlay","showMatchesOnScrollbar","isInRange","scrollInfo","occludeToleranceTop","occludeToleranceBottom","bottomY","history","doc","done","event","ExCommandDispatcher","buildCommandMap_","opt_params","that","_processCommand","commandHistoryRegister","previousCommand","inputStream","params","parseInput_","commandName","matchCommand_","parseCommandArgs_","toInput","result","eatWhile","eat","lineEnd","parseLineSpec_","numberMatch","parseLineSpecOffset_","offsetMatch","delim","argDelimiter","user","mapping","unshift","colorscheme","mapArgs","imap","nmap","vmap","set","setArgs","setCfg","expr","forceGet","optionIsBoolean","oldValue","message","setOptionReturn","setlocal","setglobal","regArgs","regInfo","sort","reverse","unique","pattern","parseArgs","eatSpace","opts","decimal","hex","octal","substr","err","lineStart","radix","numPart","textPart","matchPart","compareFn","a","b","anum","bnum","comparePatternFn","textOld","global","matchedLines","content","nextCommand","substitute","replacePart","trailing","count","confirm","startPos","doReplace","write","save","nohlsearch","delmarks","sym","startMark","finishMark","charCodeAt","finish","searchCursor","exMode","lastPos","replaceAll","newText","_value","savedCallback","detach","insertModeChangeRegister","lastChange","selLength","logInsertModeChange","extra","fallthrough","imc","repeatInsertModeChanges","changeObj","maybeReset","handleExternalSelection","markText","className","somethingSelected","onKeyFound","lookupKey","repeatForInsert","isAction","cachedInputState","repeatCommand","repeatInsert","changeObject","keyHandler","binding"],"sources":["../src/keymap.js"],"sourcesContent":["// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n/**\n * Supported keybindings:\n * Too many to list. Refer to defaultKeyMap below.\n *\n * Supported Ex commands:\n * Refer to defaultExCommandMap below.\n *\n * Registers: unnamed, -, a-z, A-Z, 0-9\n * (Does not respect the special case for number registers when delete\n * operator is made with these commands: %, (, ), , /, ?, n, N, {, } )\n * TODO: Implement the remaining registers.\n *\n * Marks: a-z, A-Z, and 0-9\n * TODO: Implement the remaining special marks. They have more complex\n * behavior.\n *\n * Events:\n * 'vim-mode-change' - raised on the editor anytime the current mode changes,\n * Event object: {mode: \"visual\", subMode: \"linewise\"}\n *\n * Code structure:\n * 1. Default keymap\n * 2. Variable declarations and short basic helpers\n * 3. Instance (External API) implementation\n * 4. Internal state tracking objects (input state, counter) implementation\n * and instantiation\n * 5. Key handler (the main command dispatcher) implementation\n * 6. Motion, operator, and action implementations\n * 7. Helper functions for the key handler, motions, operators, and actions\n * 8. Set up Vim to work as a keymap for CodeMirror.\n * 9. Ex command implementations.\n */\nconst { logger } = require('inkdrop')\nconst { clipboard } = require('electron')\n\nmodule.exports = function (CodeMirror) {\n var defaultKeymap = []\n var _defaultKeymap = [\n // Key to key mapping. This goes first to make it possible to override\n // existing mappings.\n { keys: '', type: 'keyToKey', toKeys: 'h' },\n { keys: '', type: 'keyToKey', toKeys: 'l' },\n { keys: '', type: 'keyToKey', toKeys: 'k' },\n { keys: '', type: 'keyToKey', toKeys: 'j' },\n { keys: '', type: 'keyToKey', toKeys: 'l' },\n { keys: '', type: 'keyToKey', toKeys: 'h', context: 'normal' },\n //\n { keys: '', type: 'keyToKey', toKeys: 'W' },\n { keys: '', type: 'keyToKey', toKeys: 'B', context: 'normal' },\n { keys: '', type: 'keyToKey', toKeys: 'w' },\n { keys: '', type: 'keyToKey', toKeys: 'b', context: 'normal' },\n { keys: '', type: 'keyToKey', toKeys: 'j' },\n { keys: '', type: 'keyToKey', toKeys: 'k' },\n { keys: '', type: 'keyToKey', toKeys: '' },\n { keys: '', type: 'keyToKey', toKeys: '' },\n { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' },\n { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' },\n { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' },\n { keys: 's', type: 'keyToKey', toKeys: 'c', context: 'visual' },\n { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' },\n { keys: 'S', type: 'keyToKey', toKeys: 'VdO', context: 'visual' },\n { keys: '', type: 'keyToKey', toKeys: '0' },\n { keys: '', type: 'keyToKey', toKeys: '$' },\n { keys: '', type: 'keyToKey', toKeys: '' },\n { keys: '', type: 'keyToKey', toKeys: '' },\n { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' },\n {\n keys: '',\n type: 'action',\n action: 'toggleOverwrite',\n context: 'insert'\n },\n // Motions\n {\n keys: 'H',\n type: 'motion',\n motion: 'moveToTopLine',\n motionArgs: { linewise: true, toJumplist: true }\n },\n {\n keys: 'M',\n type: 'motion',\n motion: 'moveToMiddleLine',\n motionArgs: { linewise: true, toJumplist: true }\n },\n {\n keys: 'L',\n type: 'motion',\n motion: 'moveToBottomLine',\n motionArgs: { linewise: true, toJumplist: true }\n },\n {\n keys: 'h',\n type: 'motion',\n motion: 'moveByCharacters',\n motionArgs: { forward: false }\n },\n {\n keys: 'l',\n type: 'motion',\n motion: 'moveByCharacters',\n motionArgs: { forward: true }\n },\n {\n keys: 'j',\n type: 'motion',\n motion: 'moveByLines',\n motionArgs: { forward: true, linewise: true }\n },\n {\n keys: 'k',\n type: 'motion',\n motion: 'moveByLines',\n motionArgs: { forward: false, linewise: true }\n },\n {\n keys: 'gj',\n type: 'motion',\n motion: 'moveByDisplayLines',\n motionArgs: { forward: true }\n },\n {\n keys: 'gk',\n type: 'motion',\n motion: 'moveByDisplayLines',\n motionArgs: { forward: false }\n },\n {\n keys: 'w',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: { forward: true, wordEnd: false }\n },\n {\n keys: 'W',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: { forward: true, wordEnd: false, bigWord: true }\n },\n {\n keys: 'e',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: { forward: true, wordEnd: true, inclusive: true }\n },\n {\n keys: 'E',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: {\n forward: true,\n wordEnd: true,\n bigWord: true,\n inclusive: true\n }\n },\n {\n keys: 'b',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: { forward: false, wordEnd: false }\n },\n {\n keys: 'B',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: { forward: false, wordEnd: false, bigWord: true }\n },\n {\n keys: 'ge',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: { forward: false, wordEnd: true, inclusive: true }\n },\n {\n keys: 'gE',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: {\n forward: false,\n wordEnd: true,\n bigWord: true,\n inclusive: true\n }\n },\n {\n keys: '{',\n type: 'motion',\n motion: 'moveByParagraph',\n motionArgs: { forward: false, toJumplist: true }\n },\n {\n keys: '}',\n type: 'motion',\n motion: 'moveByParagraph',\n motionArgs: { forward: true, toJumplist: true }\n },\n {\n keys: '',\n type: 'motion',\n motion: 'moveByPage',\n motionArgs: { forward: true }\n },\n {\n keys: '',\n type: 'motion',\n motion: 'moveByPage',\n motionArgs: { forward: false }\n },\n {\n keys: '',\n type: 'motion',\n motion: 'moveByScroll',\n motionArgs: { forward: true, explicitRepeat: true }\n },\n {\n keys: '',\n type: 'motion',\n motion: 'moveByScroll',\n motionArgs: { forward: false, explicitRepeat: true }\n },\n {\n keys: 'gg',\n type: 'motion',\n motion: 'moveToLineOrEdgeOfDocument',\n motionArgs: {\n forward: false,\n explicitRepeat: true,\n linewise: true,\n toJumplist: true\n }\n },\n {\n keys: 'G',\n type: 'motion',\n motion: 'moveToLineOrEdgeOfDocument',\n motionArgs: {\n forward: true,\n explicitRepeat: true,\n linewise: true,\n toJumplist: true\n }\n },\n { keys: '0', type: 'motion', motion: 'moveToStartOfLine' },\n { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' },\n {\n keys: '+',\n type: 'motion',\n motion: 'moveByLines',\n motionArgs: { forward: true, toFirstChar: true }\n },\n {\n keys: '-',\n type: 'motion',\n motion: 'moveByLines',\n motionArgs: { forward: false, toFirstChar: true }\n },\n {\n keys: '_',\n type: 'motion',\n motion: 'moveByLines',\n motionArgs: { forward: true, toFirstChar: true, repeatOffset: -1 }\n },\n {\n keys: '$',\n type: 'motion',\n motion: 'moveToEol',\n motionArgs: { inclusive: true }\n },\n {\n keys: '%',\n type: 'motion',\n motion: 'moveToMatchedSymbol',\n motionArgs: { inclusive: true, toJumplist: true }\n },\n {\n keys: 'f',\n type: 'motion',\n motion: 'moveToCharacter',\n motionArgs: { forward: true, inclusive: true }\n },\n {\n keys: 'F',\n type: 'motion',\n motion: 'moveToCharacter',\n motionArgs: { forward: false }\n },\n {\n keys: 't',\n type: 'motion',\n motion: 'moveTillCharacter',\n motionArgs: { forward: true, inclusive: true }\n },\n {\n keys: 'T',\n type: 'motion',\n motion: 'moveTillCharacter',\n motionArgs: { forward: false }\n },\n {\n keys: ';',\n type: 'motion',\n motion: 'repeatLastCharacterSearch',\n motionArgs: { forward: true }\n },\n {\n keys: ',',\n type: 'motion',\n motion: 'repeatLastCharacterSearch',\n motionArgs: { forward: false }\n },\n {\n keys: \"'\",\n type: 'motion',\n motion: 'goToMark',\n motionArgs: { toJumplist: true, linewise: true }\n },\n {\n keys: '`',\n type: 'motion',\n motion: 'goToMark',\n motionArgs: { toJumplist: true }\n },\n {\n keys: ']`',\n type: 'motion',\n motion: 'jumpToMark',\n motionArgs: { forward: true }\n },\n {\n keys: '[`',\n type: 'motion',\n motion: 'jumpToMark',\n motionArgs: { forward: false }\n },\n {\n keys: \"]'\",\n type: 'motion',\n motion: 'jumpToMark',\n motionArgs: { forward: true, linewise: true }\n },\n {\n keys: \"['\",\n type: 'motion',\n motion: 'jumpToMark',\n motionArgs: { forward: false, linewise: true }\n },\n // the next two aren't motions but must come before more general motion declarations\n {\n keys: ']p',\n type: 'action',\n action: 'paste',\n isEdit: true,\n actionArgs: { after: true, isEdit: true, matchIndent: true }\n },\n {\n keys: '[p',\n type: 'action',\n action: 'paste',\n isEdit: true,\n actionArgs: { after: false, isEdit: true, matchIndent: true }\n },\n {\n keys: ']',\n type: 'motion',\n motion: 'moveToSymbol',\n motionArgs: { forward: true, toJumplist: true }\n },\n {\n keys: '[',\n type: 'motion',\n motion: 'moveToSymbol',\n motionArgs: { forward: false, toJumplist: true }\n },\n { keys: '|', type: 'motion', motion: 'moveToColumn' },\n {\n keys: 'o',\n type: 'motion',\n motion: 'moveToOtherHighlightedEnd',\n context: 'visual'\n },\n {\n keys: 'O',\n type: 'motion',\n motion: 'moveToOtherHighlightedEnd',\n motionArgs: { sameLine: true },\n context: 'visual'\n },\n // Operators\n { keys: 'd', type: 'operator', operator: 'delete' },\n { keys: 'y', type: 'operator', operator: 'yank' },\n { keys: 'c', type: 'operator', operator: 'change' },\n {\n keys: '>',\n type: 'operator',\n operator: 'indent',\n operatorArgs: { indentRight: true }\n },\n {\n keys: '<',\n type: 'operator',\n operator: 'indent',\n operatorArgs: { indentRight: false }\n },\n { keys: 'g~', type: 'operator', operator: 'changeCase' },\n {\n keys: 'gu',\n type: 'operator',\n operator: 'changeCase',\n operatorArgs: { toLower: true },\n isEdit: true\n },\n {\n keys: 'gU',\n type: 'operator',\n operator: 'changeCase',\n operatorArgs: { toLower: false },\n isEdit: true\n },\n {\n keys: 'n',\n type: 'motion',\n motion: 'findNext',\n motionArgs: { forward: true, toJumplist: true }\n },\n {\n keys: 'N',\n type: 'motion',\n motion: 'findNext',\n motionArgs: { forward: false, toJumplist: true }\n },\n // Operator-Motion dual commands\n {\n keys: 'x',\n type: 'operatorMotion',\n operator: 'delete',\n motion: 'moveByCharacters',\n motionArgs: { forward: true },\n operatorMotionArgs: { visualLine: false }\n },\n {\n keys: 'X',\n type: 'operatorMotion',\n operator: 'delete',\n motion: 'moveByCharacters',\n motionArgs: { forward: false },\n operatorMotionArgs: { visualLine: true }\n },\n {\n keys: 'D',\n type: 'operatorMotion',\n operator: 'delete',\n motion: 'moveToEol',\n motionArgs: { inclusive: true },\n context: 'normal'\n },\n {\n keys: 'D',\n type: 'operator',\n operator: 'delete',\n operatorArgs: { linewise: true },\n context: 'visual'\n },\n {\n keys: 'Y',\n type: 'operatorMotion',\n operator: 'yank',\n motion: 'expandToLine',\n motionArgs: { linewise: true },\n context: 'normal'\n },\n {\n keys: 'Y',\n type: 'operator',\n operator: 'yank',\n operatorArgs: { linewise: true },\n context: 'visual'\n },\n {\n keys: 'C',\n type: 'operatorMotion',\n operator: 'change',\n motion: 'moveToEol',\n motionArgs: { inclusive: true },\n context: 'normal'\n },\n {\n keys: 'C',\n type: 'operator',\n operator: 'change',\n operatorArgs: { linewise: true },\n context: 'visual'\n },\n {\n keys: '~',\n type: 'operatorMotion',\n operator: 'changeCase',\n motion: 'moveByCharacters',\n motionArgs: { forward: true },\n operatorArgs: { shouldMoveCursor: true },\n context: 'normal'\n },\n { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual' },\n {\n keys: '',\n type: 'operatorMotion',\n operator: 'delete',\n motion: 'moveByWords',\n motionArgs: { forward: false, wordEnd: false },\n context: 'insert'\n },\n // Actions\n {\n keys: '',\n type: 'action',\n action: 'jumpListWalk',\n actionArgs: { forward: true }\n },\n {\n keys: '',\n type: 'action',\n action: 'jumpListWalk',\n actionArgs: { forward: false }\n },\n {\n keys: '',\n type: 'action',\n action: 'scroll',\n actionArgs: { forward: true, linewise: true }\n },\n {\n keys: '',\n type: 'action',\n action: 'scroll',\n actionArgs: { forward: false, linewise: true }\n },\n {\n keys: 'a',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { insertAt: 'charAfter' },\n context: 'normal'\n },\n {\n keys: 'A',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { insertAt: 'eol' },\n context: 'normal'\n },\n {\n keys: 'A',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { insertAt: 'endOfSelectedArea' },\n context: 'visual'\n },\n {\n keys: 'i',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { insertAt: 'inplace' },\n context: 'normal'\n },\n {\n keys: 'I',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { insertAt: 'firstNonBlank' },\n context: 'normal'\n },\n {\n keys: 'I',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { insertAt: 'startOfSelectedArea' },\n context: 'visual'\n },\n {\n keys: 'o',\n type: 'action',\n action: 'newLineAndEnterInsertMode',\n isEdit: true,\n interlaceInsertRepeat: true,\n actionArgs: { after: true },\n context: 'normal'\n },\n {\n keys: 'O',\n type: 'action',\n action: 'newLineAndEnterInsertMode',\n isEdit: true,\n interlaceInsertRepeat: true,\n actionArgs: { after: false },\n context: 'normal'\n },\n { keys: 'v', type: 'action', action: 'toggleVisualMode' },\n {\n keys: 'V',\n type: 'action',\n action: 'toggleVisualMode',\n actionArgs: { linewise: true }\n },\n {\n keys: '',\n type: 'action',\n action: 'toggleVisualMode',\n actionArgs: { blockwise: true }\n },\n {\n keys: '',\n type: 'action',\n action: 'toggleVisualMode',\n actionArgs: { blockwise: true }\n },\n { keys: 'gv', type: 'action', action: 'reselectLastSelection' },\n { keys: 'J', type: 'action', action: 'joinLines', isEdit: true },\n {\n keys: 'p',\n type: 'action',\n action: 'paste',\n isEdit: true,\n actionArgs: { after: true, isEdit: true }\n },\n {\n keys: 'P',\n type: 'action',\n action: 'paste',\n isEdit: true,\n actionArgs: { after: false, isEdit: true }\n },\n { keys: 'r', type: 'action', action: 'replace', isEdit: true },\n { keys: '@', type: 'action', action: 'replayMacro' },\n { keys: 'q', type: 'action', action: 'enterMacroRecordMode' },\n // Handle Replace-mode as a special case of insert mode.\n {\n keys: 'R',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { replace: true }\n },\n { keys: 'u', type: 'action', action: 'undo', context: 'normal' },\n {\n keys: 'u',\n type: 'operator',\n operator: 'changeCase',\n operatorArgs: { toLower: true },\n context: 'visual',\n isEdit: true\n },\n {\n keys: 'U',\n type: 'operator',\n operator: 'changeCase',\n operatorArgs: { toLower: false },\n context: 'visual',\n isEdit: true\n },\n { keys: '', type: 'action', action: 'redo' },\n { keys: 'm', type: 'action', action: 'setMark' },\n { keys: '\"', type: 'action', action: 'setRegister' },\n {\n keys: 'zz',\n type: 'action',\n action: 'scrollToCursor',\n actionArgs: { position: 'center' }\n },\n {\n keys: 'z.',\n type: 'action',\n action: 'scrollToCursor',\n actionArgs: { position: 'center' },\n motion: 'moveToFirstNonWhiteSpaceCharacter'\n },\n {\n keys: 'zt',\n type: 'action',\n action: 'scrollToCursor',\n actionArgs: { position: 'top' }\n },\n {\n keys: 'z',\n type: 'action',\n action: 'scrollToCursor',\n actionArgs: { position: 'top' },\n motion: 'moveToFirstNonWhiteSpaceCharacter'\n },\n {\n keys: 'z-',\n type: 'action',\n action: 'scrollToCursor',\n actionArgs: { position: 'bottom' }\n },\n {\n keys: 'zb',\n type: 'action',\n action: 'scrollToCursor',\n actionArgs: { position: 'bottom' },\n motion: 'moveToFirstNonWhiteSpaceCharacter'\n },\n { keys: '.', type: 'action', action: 'repeatLastEdit' },\n {\n keys: '',\n type: 'action',\n action: 'incrementNumberToken',\n isEdit: true,\n actionArgs: { increase: true, backtrack: false }\n },\n {\n keys: '',\n type: 'action',\n action: 'incrementNumberToken',\n isEdit: true,\n actionArgs: { increase: false, backtrack: false }\n },\n {\n keys: '',\n type: 'action',\n action: 'indent',\n actionArgs: { indentRight: true },\n context: 'insert'\n },\n {\n keys: '',\n type: 'action',\n action: 'indent',\n actionArgs: { indentRight: false },\n context: 'insert'\n },\n // Text object motions\n { keys: 'a', type: 'motion', motion: 'textObjectManipulation' },\n {\n keys: 'i',\n type: 'motion',\n motion: 'textObjectManipulation',\n motionArgs: { textObjectInner: true }\n },\n // Search\n {\n keys: '/',\n type: 'search',\n searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }\n },\n {\n keys: '?',\n type: 'search',\n searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }\n },\n {\n keys: '*',\n type: 'search',\n searchArgs: {\n forward: true,\n querySrc: 'wordUnderCursor',\n wholeWordOnly: true,\n toJumplist: true\n }\n },\n {\n keys: '#',\n type: 'search',\n searchArgs: {\n forward: false,\n querySrc: 'wordUnderCursor',\n wholeWordOnly: true,\n toJumplist: true\n }\n },\n {\n keys: 'g*',\n type: 'search',\n searchArgs: {\n forward: true,\n querySrc: 'wordUnderCursor',\n toJumplist: true\n }\n },\n {\n keys: 'g#',\n type: 'search',\n searchArgs: {\n forward: false,\n querySrc: 'wordUnderCursor',\n toJumplist: true\n }\n },\n // Ex command\n { keys: ':', type: 'ex' }\n ]\n\n /**\n * Ex commands\n * Care must be taken when adding to the default Ex command map. For any\n * pair of commands that have a shared prefix, at least one of their\n * shortNames must not match the prefix of the other command.\n */\n var defaultExCommandMap = [\n { name: 'colorscheme', shortName: 'colo' },\n { name: 'map' },\n { name: 'imap', shortName: 'im' },\n { name: 'nmap', shortName: 'nm' },\n { name: 'vmap', shortName: 'vm' },\n { name: 'unmap' },\n { name: 'write', shortName: 'w' },\n { name: 'undo', shortName: 'u' },\n { name: 'redo', shortName: 'red' },\n { name: 'set', shortName: 'se' },\n { name: 'set', shortName: 'se' },\n { name: 'setlocal', shortName: 'setl' },\n { name: 'setglobal', shortName: 'setg' },\n { name: 'sort', shortName: 'sor' },\n { name: 'substitute', shortName: 's', possiblyAsync: true },\n { name: 'nohlsearch', shortName: 'noh' },\n { name: 'yank', shortName: 'y' },\n { name: 'delmarks', shortName: 'delm' },\n { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true },\n { name: 'global', shortName: 'g' }\n ]\n\n var Pos = CodeMirror.Pos\n\n var Vim = function () {\n function enterVimMode(cm) {\n cm.setOption('disableInput', true)\n cm.setOption('showCursorWhenSelecting', false)\n CodeMirror.signal(cm, 'vim-mode-change', { mode: 'normal' })\n cm.on('cursorActivity', onCursorActivity)\n maybeInitVimState(cm)\n CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm))\n }\n\n function leaveVimMode(cm) {\n cm.setOption('disableInput', false)\n cm.off('cursorActivity', onCursorActivity)\n CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm))\n cm.state.vim = null\n }\n\n function detachVimMap(cm, next) {\n if (this == CodeMirror.keyMap.vim) {\n CodeMirror.rmClass(cm.getWrapperElement(), 'cm-fat-cursor')\n }\n\n if (!next || next.attach != attachVimMap) {\n leaveVimMode(cm)\n }\n }\n function attachVimMap(cm, prev) {\n if (this == CodeMirror.keyMap.vim) {\n CodeMirror.addClass(cm.getWrapperElement(), 'cm-fat-cursor')\n }\n\n if (!prev || prev.attach != attachVimMap) {\n enterVimMode(cm)\n }\n }\n\n // Deprecated, simply setting the keymap works again.\n CodeMirror.defineOption('vimMode', false, function (cm, val, prev) {\n if (val && cm.getOption('keyMap') != 'vim') {\n cm.setOption('keyMap', 'vim')\n } else if (\n !val &&\n prev != CodeMirror.Init &&\n /^vim/.test(cm.getOption('keyMap'))\n ) {\n cm.setOption('keyMap', 'default')\n }\n })\n\n function cmKey(key, cm) {\n if (!cm) {\n return undefined\n }\n if (this[key]) {\n return this[key]\n }\n var vimKey = cmKeyToVimKey(key)\n if (!vimKey) {\n return false\n }\n var cmd = CodeMirror.Vim.findKey(cm, vimKey)\n if (typeof cmd === 'function') {\n CodeMirror.signal(cm, 'vim-keypress', vimKey)\n }\n return cmd\n }\n\n var modifiers = { Shift: 'S', Ctrl: 'C', Alt: 'A', Cmd: 'D', Mod: 'A' }\n var specialKeys = {\n Enter: 'CR',\n Backspace: 'BS',\n Delete: 'Del',\n Insert: 'Ins'\n }\n function cmKeyToVimKey(key) {\n if (key.charAt(0) == \"'\") {\n // Keypress character binding of format \"'a'\"\n return key.charAt(1)\n }\n var pieces = key.split(/-(?!$)/)\n var lastPiece = pieces[pieces.length - 1]\n if (pieces.length == 1 && pieces[0].length == 1) {\n // No-modifier bindings use literal character bindings above. Skip.\n return false\n } else if (\n pieces.length == 2 &&\n pieces[0] == 'Shift' &&\n lastPiece.length == 1\n ) {\n // Ignore Shift+char bindings as they should be handled by literal character.\n return false\n }\n var hasCharacter = false\n for (var i = 0; i < pieces.length; i++) {\n var piece = pieces[i]\n if (piece in modifiers) {\n pieces[i] = modifiers[piece]\n } else {\n hasCharacter = true\n }\n if (piece in specialKeys) {\n pieces[i] = specialKeys[piece]\n }\n }\n if (!hasCharacter) {\n // Vim does not support modifier only keys.\n return false\n }\n // TODO: Current bindings expect the character to be lower case, but\n // it looks like vim key notation uses upper case.\n if (isUpperCase(lastPiece)) {\n pieces[pieces.length - 1] = lastPiece.toLowerCase()\n }\n return '<' + pieces.join('-') + '>'\n }\n\n function getOnPasteFn(cm) {\n var vim = cm.state.vim\n if (!vim.onPasteFn) {\n vim.onPasteFn = function () {\n if (!vim.insertMode) {\n cm.setCursor(offsetCursor(cm.getCursor(), 0, 1))\n actions.enterInsertMode(cm, {}, vim)\n }\n }\n }\n return vim.onPasteFn\n }\n\n var numberRegex = /[\\d]/\n var wordCharTest = [\n CodeMirror.isWordChar,\n function (ch) {\n return ch && !CodeMirror.isWordChar(ch) && !/\\s/.test(ch)\n }\n ],\n bigWordCharTest = [\n function (ch) {\n return /\\S/.test(ch)\n }\n ]\n function makeKeyRange(start, size) {\n var keys = []\n for (var i = start; i < start + size; i++) {\n keys.push(String.fromCharCode(i))\n }\n return keys\n }\n var upperCaseAlphabet = makeKeyRange(65, 26)\n var lowerCaseAlphabet = makeKeyRange(97, 26)\n var numbers = makeKeyRange(48, 10)\n var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, [\n '<',\n '>'\n ])\n var validRegisters = [].concat(\n upperCaseAlphabet,\n lowerCaseAlphabet,\n numbers,\n ['-', '\"', '.', ':', '/']\n )\n\n function isLine(cm, line) {\n return line >= cm.firstLine() && line <= cm.lastLine()\n }\n function isLowerCase(k) {\n return /^[a-z]$/.test(k)\n }\n function isMatchableSymbol(k) {\n return '()[]{}'.indexOf(k) != -1\n }\n function isNumber(k) {\n return numberRegex.test(k)\n }\n function isUpperCase(k) {\n return /^[A-Z]$/.test(k)\n }\n function isWhiteSpaceString(k) {\n return /^\\s*$/.test(k)\n }\n function inArray(val, arr) {\n for (var i = 0; i < arr.length; i++) {\n if (arr[i] == val) {\n return true\n }\n }\n return false\n }\n\n var options = {}\n function defineOption(name, defaultValue, type, aliases, callback) {\n if (defaultValue === undefined && !callback) {\n throw Error('defaultValue is required unless callback is provided')\n }\n if (!type) {\n type = 'string'\n }\n options[name] = {\n type: type,\n defaultValue: defaultValue,\n callback: callback\n }\n if (aliases) {\n for (var i = 0; i < aliases.length; i++) {\n options[aliases[i]] = options[name]\n }\n }\n if (defaultValue) {\n setOption(name, defaultValue)\n }\n }\n\n function setOption(name, value, cm, cfg) {\n var option = options[name]\n cfg = cfg || {}\n var scope = cfg.scope\n if (!option) {\n return new Error('Unknown option: ' + name)\n }\n if (option.type == 'boolean') {\n if (value && value !== true) {\n return new Error('Invalid argument: ' + name + '=' + value)\n } else if (value !== false) {\n // Boolean options are set to true if value is not defined.\n value = true\n }\n }\n if (option.callback) {\n if (scope !== 'local') {\n option.callback(value, undefined)\n }\n if (scope !== 'global' && cm) {\n option.callback(value, cm)\n }\n } else {\n if (scope !== 'local') {\n option.value = option.type == 'boolean' ? !!value : value\n }\n if (scope !== 'global' && cm) {\n cm.state.vim.options[name] = { value: value }\n }\n }\n }\n\n function getOption(name, cm, cfg) {\n var option = options[name]\n cfg = cfg || {}\n var scope = cfg.scope\n if (!option) {\n return new Error('Unknown option: ' + name)\n }\n if (option.callback) {\n var local = cm && option.callback(undefined, cm)\n if (scope !== 'global' && local !== undefined) {\n return local\n }\n if (scope !== 'local') {\n return option.callback()\n }\n } else {\n var local = scope !== 'global' && cm && cm.state.vim.options[name]\n return (local || (scope !== 'local' && option) || {}).value\n }\n }\n\n defineOption('filetype', undefined, 'string', ['ft'], function (name, cm) {\n // Option is local. Do nothing for global.\n if (cm === undefined) {\n return\n }\n // The 'filetype' option proxies to the CodeMirror 'mode' option.\n if (name === undefined) {\n var mode = cm.getOption('mode')\n return mode == 'null' ? '' : mode\n } else {\n var mode = name == '' ? 'null' : name\n cm.setOption('mode', mode)\n }\n })\n\n var createCircularJumpList = function () {\n var size = 100\n var pointer = -1\n var head = 0\n var tail = 0\n var buffer = new Array(size)\n function add(cm, oldCur, newCur) {\n var current = pointer % size\n var curMark = buffer[current]\n function useNextSlot(cursor) {\n var next = ++pointer % size\n var trashMark = buffer[next]\n if (trashMark) {\n trashMark.clear()\n }\n buffer[next] = cm.setBookmark(cursor)\n }\n if (curMark) {\n var markPos = curMark.find()\n // avoid recording redundant cursor position\n if (markPos && !cursorEqual(markPos, oldCur)) {\n useNextSlot(oldCur)\n }\n } else {\n useNextSlot(oldCur)\n }\n useNextSlot(newCur)\n head = pointer\n tail = pointer - size + 1\n if (tail < 0) {\n tail = 0\n }\n }\n function move(cm, offset) {\n pointer += offset\n if (pointer > head) {\n pointer = head\n } else if (pointer < tail) {\n pointer = tail\n }\n var mark = buffer[(size + pointer) % size]\n // skip marks that are temporarily removed from text buffer\n if (mark && !mark.find()) {\n var inc = offset > 0 ? 1 : -1\n var newCur\n var oldCur = cm.getCursor()\n do {\n pointer += inc\n mark = buffer[(size + pointer) % size]\n // skip marks that are the same as current position\n if (\n mark &&\n (newCur = mark.find()) &&\n !cursorEqual(oldCur, newCur)\n ) {\n break\n }\n } while (pointer < head && pointer > tail)\n }\n return mark\n }\n return {\n cachedCursor: undefined, // used for # and * jumps\n add: add,\n move: move\n }\n }\n\n // Returns an object to track the changes associated insert mode. It\n // clones the object that is passed in, or creates an empty object one if\n // none is provided.\n var createInsertModeChanges = function (c) {\n if (c) {\n // Copy construction\n return {\n changes: c.changes,\n expectCursorActivityForChange: c.expectCursorActivityForChange\n }\n }\n return {\n // Change list\n changes: [],\n // Set to true on change, false on cursorActivity.\n expectCursorActivityForChange: false\n }\n }\n\n function MacroModeState() {\n this.latestRegister = undefined\n this.isPlaying = false\n this.isRecording = false\n this.replaySearchQueries = []\n this.onRecordingDone = undefined\n this.lastInsertModeChanges = createInsertModeChanges()\n }\n MacroModeState.prototype = {\n exitMacroRecordMode: function () {\n var macroModeState = vimGlobalState.macroModeState\n if (macroModeState.onRecordingDone) {\n macroModeState.onRecordingDone() // close dialog\n }\n macroModeState.onRecordingDone = undefined\n macroModeState.isRecording = false\n },\n enterMacroRecordMode: function (cm, registerName) {\n var register =\n vimGlobalState.registerController.getRegister(registerName)\n if (register) {\n register.clear()\n this.latestRegister = registerName\n if (cm.openDialog) {\n this.onRecordingDone = cm.openDialog(\n '(recording)[' + registerName + ']',\n null,\n { bottom: true }\n )\n }\n this.isRecording = true\n }\n }\n }\n\n function maybeInitVimState(cm) {\n if (!cm.state.vim) {\n // Store instance state in the CodeMirror object.\n cm.state.vim = {\n inputState: new InputState(),\n // Vim's input state that triggered the last edit, used to repeat\n // motions and operators with '.'.\n lastEditInputState: undefined,\n // Vim's action command before the last edit, used to repeat actions\n // with '.' and insert mode repeat.\n lastEditActionCommand: undefined,\n // When using jk for navigation, if you move from a longer line to a\n // shorter line, the cursor may clip to the end of the shorter line.\n // If j is pressed again and cursor goes to the next line, the\n // cursor should go back to its horizontal position on the longer\n // line if it can. This is to keep track of the horizontal position.\n lastHPos: -1,\n // Doing the same with screen-position for gj/gk\n lastHSPos: -1,\n // The last motion command run. Cleared if a non-motion command gets\n // executed in between.\n lastMotion: null,\n marks: {},\n // Mark for rendering fake cursor for visual mode.\n fakeCursor: null,\n insertMode: false,\n // Repeat count for changes made in insert mode, triggered by key\n // sequences like 3,i. Only exists when insertMode is true.\n insertModeRepeat: undefined,\n visualMode: false,\n // If we are in visual line mode. No effect if visualMode is false.\n visualLine: false,\n visualBlock: false,\n lastSelection: null,\n lastPastedText: null,\n sel: {},\n // Buffer-local/window-local values of vim options.\n options: {}\n }\n }\n return cm.state.vim\n }\n var vimGlobalState\n function resetVimGlobalState() {\n vimGlobalState = {\n // The current search query.\n searchQuery: null,\n // Whether we are searching backwards.\n searchIsReversed: false,\n // Replace part of the last substituted pattern\n lastSubstituteReplacePart: undefined,\n jumpList: createCircularJumpList(),\n macroModeState: new MacroModeState(),\n // Recording latest f, t, F or T motion command.\n lastCharacterSearch: {\n increment: 0,\n forward: true,\n selectedCharacter: ''\n },\n registerController: new RegisterController({}),\n // search history buffer\n searchHistoryController: new HistoryController(),\n // ex Command history buffer\n exCommandHistoryController: new HistoryController()\n }\n for (var optionName in options) {\n var option = options[optionName]\n option.value = option.defaultValue\n }\n }\n\n var lastInsertModeKeyTimer\n var vimApi = {\n buildKeyMap: function () {\n // TODO: Convert keymap into dictionary format for fast lookup.\n },\n // Testing hook, though it might be useful to expose the register\n // controller anyways.\n getRegisterController: function () {\n return vimGlobalState.registerController\n },\n resetVimGlobalState: resetVimGlobalState,\n getVimGlobalState: function () {\n return vimGlobalState\n },\n maybeInitVimState: maybeInitVimState,\n\n suppressErrorLogging: false,\n\n InsertModeKey: InsertModeKey,\n map: function (lhs, rhs, ctx) {\n // Add user defined key bindings.\n exCommandDispatcher.map(lhs, rhs, ctx)\n },\n unmap: function (lhs, ctx) {\n exCommandDispatcher.unmap(lhs, ctx)\n },\n // TODO: Expose setOption and getOption as instance methods. Need to decide how to namespace\n // them, or somehow make them work with the existing CodeMirror setOption/getOption API.\n setOption: setOption,\n getOption: getOption,\n defineOption: defineOption,\n defineEx: function (name, prefix, func) {\n if (!prefix) {\n prefix = name\n } else if (name.indexOf(prefix) !== 0) {\n throw new Error(\n '(Vim.defineEx) \"' +\n prefix +\n '\" is not a prefix of \"' +\n name +\n '\", command not registered'\n )\n }\n exCommands[name] = func\n exCommandDispatcher.commandMap_[prefix] = {\n name: name,\n shortName: prefix,\n type: 'api'\n }\n },\n handleKey: function (cm, key, origin) {\n var command = this.findKey(cm, key, origin)\n if (typeof command === 'function') {\n return command()\n }\n },\n /**\n * This is the outermost function called by CodeMirror, after keys have\n * been mapped to their Vim equivalents.\n *\n * Finds a command based on the key (and cached keys if there is a\n * multi-key sequence). Returns `undefined` if no key is matched, a noop\n * function if a partial match is found (multi-key), and a function to\n * execute the bound command if a a key is matched. The function always\n * returns true.\n */\n findKey: function (cm, key, origin) {\n var vim = maybeInitVimState(cm)\n function handleMacroRecording() {\n var macroModeState = vimGlobalState.macroModeState\n if (macroModeState.isRecording) {\n if (key == 'q') {\n macroModeState.exitMacroRecordMode()\n clearInputState(cm)\n return true\n }\n if (origin != 'mapping') {\n logKey(macroModeState, key)\n }\n }\n }\n function handleEsc() {\n if (key == '') {\n // Clear input state and get back to normal mode.\n clearInputState(cm)\n if (vim.visualMode) {\n exitVisualMode(cm)\n } else if (vim.insertMode) {\n exitInsertMode(cm)\n }\n return true\n }\n }\n function doKeyToKey(keys) {\n // TODO: prevent infinite recursion.\n var match\n while (keys) {\n // Pull off one command key, which is either a single character\n // or a special sequence wrapped in '<' and '>', e.g. ''.\n match = /<\\w+-.+?>|<\\w+>|./.exec(keys)\n key = match[0]\n keys = keys.substring(match.index + key.length)\n CodeMirror.Vim.handleKey(cm, key, 'mapping')\n }\n }\n\n function handleKeyInsertMode() {\n if (handleEsc()) {\n return true\n }\n\n var keys = (vim.inputState.keyBuffer = vim.inputState.keyBuffer + key)\n logger.debug('keyBuffer:', keys)\n var keysAreChars = key.length == 1\n var match = commandDispatcher.matchCommand(\n keys,\n defaultKeymap,\n vim.inputState,\n 'insert'\n )\n // Need to check all key substrings in insert mode.\n while (keys.length > 1 && match.type !== 'full') {\n var keys = (vim.inputState.keyBuffer = keys.slice(1))\n var thisMatch = commandDispatcher.matchCommand(\n keys,\n defaultKeymap,\n vim.inputState,\n 'insert'\n )\n if (thisMatch.type !== 'none') {\n match = thisMatch\n }\n }\n if (match.type === 'none') {\n clearInputState(cm)\n return false\n } else if (match.type === 'partial') {\n if (lastInsertModeKeyTimer) {\n window.clearTimeout(lastInsertModeKeyTimer)\n }\n lastInsertModeKeyTimer = window.setTimeout(() => {\n if (vim.insertMode && vim.inputState.keyBuffer) {\n clearInputState(cm)\n }\n }, getOption('insertModeEscKeysTimeout'))\n return !keysAreChars\n }\n\n if (lastInsertModeKeyTimer) {\n window.clearTimeout(lastInsertModeKeyTimer)\n }\n if (keysAreChars) {\n var selections = cm.listSelections()\n for (var i = 0; i < selections.length; i++) {\n var here = selections[i].head\n cm.replaceRange(\n '',\n offsetCursor(here, 0, -(keys.length - 1)),\n here,\n '+input'\n )\n }\n vimGlobalState.macroModeState.lastInsertModeChanges.changes.pop()\n }\n clearInputState(cm)\n return match.command\n }\n\n function handleKeyNonInsertMode() {\n if (handleMacroRecording() || handleEsc()) {\n return true\n }\n\n var keys = (vim.inputState.keyBuffer = vim.inputState.keyBuffer + key)\n if (/^[1-9]\\d*$/.test(keys)) {\n return true\n }\n\n var keysMatcher = /^(\\d*)(.*)$/.exec(keys)\n if (!keysMatcher) {\n clearInputState(cm)\n return false\n }\n var context = vim.visualMode ? 'visual' : 'normal'\n var match = commandDispatcher.matchCommand(\n keysMatcher[2] || keysMatcher[1],\n defaultKeymap,\n vim.inputState,\n context\n )\n if (match.type === 'none') {\n clearInputState(cm)\n return false\n } else if (match.type === 'partial') {\n return true\n }\n\n vim.inputState.keyBuffer = ''\n keysMatcher = /^(\\d*)(.*)$/.exec(keys)\n if (keysMatcher[1] && keysMatcher[1] !== '0') {\n vim.inputState.pushRepeatDigit(keysMatcher[1])\n }\n return match.command\n }\n\n var command\n if (vim.insertMode) {\n command = handleKeyInsertMode()\n } else {\n command = handleKeyNonInsertMode()\n }\n\n logger.debug(\n 'keyBuffer::::',\n command,\n vim.inputState.keyBuffer,\n vim.inputState.operator,\n vim.inputState.operatorArgs\n )\n\n if (command === false) {\n return undefined\n } else if (command === true) {\n // TODO: Look into using CodeMirror's multi-key handling.\n // Return no-op since we are caching the key. Counts as handled, but\n // don't want act on it just yet.\n return function () {\n return true\n }\n } else {\n return function () {\n return cm.operation(function () {\n cm.curOp.isVimOp = true\n try {\n if (command.type === 'keyToKey') {\n doKeyToKey(command.toKeys)\n } else {\n commandDispatcher.processCommand(cm, vim, command)\n }\n } catch (e) {\n // clear VIM state in case it's in a bad state.\n cm.state.vim = undefined\n maybeInitVimState(cm)\n if (!CodeMirror.Vim.suppressErrorLogging) {\n console['log'](e)\n }\n throw e\n }\n return true\n })\n }\n }\n },\n handleEx: function (cm, input) {\n exCommandDispatcher.processCommand(cm, input)\n },\n\n defineMotion: defineMotion,\n defineAction: defineAction,\n defineOperator: defineOperator,\n mapCommand: mapCommand,\n _mapCommand: _mapCommand,\n\n defineRegister: defineRegister,\n\n exitVisualMode: exitVisualMode,\n exitInsertMode: exitInsertMode,\n clearInputState: clearInputState,\n\n cmKeyToVimKey: cmKeyToVimKey\n }\n\n // Represents the current input state.\n function InputState() {\n this.prefixRepeat = []\n this.motionRepeat = []\n\n this.operator = null\n this.operatorArgs = null\n this.motion = null\n this.motionArgs = null\n this.keyBuffer = [] // For matching multi-key commands.\n this.registerName = null // Defaults to the unnamed register.\n }\n InputState.prototype.pushRepeatDigit = function (n) {\n if (!this.operator) {\n this.prefixRepeat = this.prefixRepeat.concat(n)\n } else {\n this.motionRepeat = this.motionRepeat.concat(n)\n }\n }\n InputState.prototype.getRepeat = function () {\n var repeat = 0\n if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) {\n repeat = 1\n if (this.prefixRepeat.length > 0) {\n repeat *= parseInt(this.prefixRepeat.join(''), 10)\n }\n if (this.motionRepeat.length > 0) {\n repeat *= parseInt(this.motionRepeat.join(''), 10)\n }\n }\n return repeat\n }\n\n function clearInputState(cm, reason) {\n cm.state.vim.inputState = new InputState()\n CodeMirror.signal(cm, 'vim-command-done', reason)\n }\n\n /*\n * Register stores information about copy and paste registers. Besides\n * text, a register must store whether it is linewise (i.e., when it is\n * pasted, should it insert itself into a new line, or should the text be\n * inserted at the cursor position.)\n */\n function Register(text, linewise, blockwise) {\n this.clear()\n this.keyBuffer = [text || '']\n this.insertModeChanges = []\n this.searchQueries = []\n this.linewise = !!linewise\n this.blockwise = !!blockwise\n }\n Register.prototype = {\n setText: function (text, linewise, blockwise) {\n this.keyBuffer = [text || '']\n this.linewise = !!linewise\n this.blockwise = !!blockwise\n },\n pushText: function (text, linewise) {\n // if this register has ever been set to linewise, use linewise.\n if (linewise) {\n if (!this.linewise) {\n this.keyBuffer.push('\\n')\n }\n this.linewise = true\n }\n this.keyBuffer.push(text)\n },\n pushInsertModeChanges: function (changes) {\n this.insertModeChanges.push(createInsertModeChanges(changes))\n },\n pushSearchQuery: function (query) {\n this.searchQueries.push(query)\n },\n clear: function () {\n this.keyBuffer = []\n this.insertModeChanges = []\n this.searchQueries = []\n this.linewise = false\n },\n toString: function () {\n return this.keyBuffer.join('')\n }\n }\n\n /**\n * Defines an external register.\n *\n * The name should be a single character that will be used to reference the register.\n * The register should support setText, pushText, clear, and toString(). See Register\n * for a reference implementation.\n */\n function defineRegister(name, register) {\n var registers = vimGlobalState.registerController.registers\n if (!name || name.length != 1) {\n throw Error('Register name must be 1 character')\n }\n if (registers[name]) {\n throw Error('Register already defined ' + name)\n }\n registers[name] = register\n validRegisters.push(name)\n }\n\n /*\n * vim registers allow you to keep many independent copy and paste buffers.\n * See http://usevim.com/2012/04/13/registers/ for an introduction.\n *\n * RegisterController keeps the state of all the registers. An initial\n * state may be passed in. The unnamed register '\"' will always be\n * overridden.\n */\n function RegisterController(registers) {\n this.registers = registers\n this.unnamedRegister = registers['\"'] = new Register()\n registers['.'] = new Register()\n registers[':'] = new Register()\n registers['/'] = new Register()\n }\n RegisterController.prototype = {\n pushText: function (registerName, operator, text, linewise, blockwise) {\n if (linewise && text.charAt(text.length - 1) !== '\\n') {\n text += '\\n'\n }\n // Lowercase and uppercase registers refer to the same register.\n // Uppercase just means append.\n var register = this.isValidRegister(registerName)\n ? this.getRegister(registerName)\n : null\n // if no register/an invalid register was specified, things go to the\n // default registers\n if (!register) {\n switch (operator) {\n case 'yank':\n // The 0 register contains the text from the most recent yank.\n const reg = new Register(text, linewise, blockwise)\n logger.debug('yanked:', reg)\n this.registers['0'] = reg\n clipboard.writeText(reg.keyBuffer[0])\n break\n case 'delete':\n case 'change':\n clipboard.writeText(text)\n if (text.indexOf('\\n') == -1) {\n // Delete less than 1 line. Update the small delete register.\n this.registers['-'] = new Register(text, linewise)\n } else {\n // Shift down the contents of the numbered registers and put the\n // deleted text into register 1.\n this.shiftNumericRegisters_()\n this.registers['1'] = new Register(text, linewise)\n }\n break\n }\n // Make sure the unnamed register is set to what just happened\n this.unnamedRegister.setText(text, linewise, blockwise)\n return\n }\n\n // If we've gotten to this point, we've actually specified a register\n var append = isUpperCase(registerName)\n if (append) {\n register.pushText(text, linewise)\n } else {\n register.setText(text, linewise, blockwise)\n }\n // The unnamed register always has the same value as the last used\n // register.\n this.unnamedRegister.setText(register.toString(), linewise)\n },\n // Gets the register named @name. If one of @name doesn't already exist,\n // create it. If @name is invalid, return the unnamedRegister.\n getRegister: function (name) {\n if (!this.isValidRegister(name)) {\n return this.unnamedRegister\n }\n name = name.toLowerCase()\n if (!this.registers[name]) {\n this.registers[name] = new Register()\n }\n return this.registers[name]\n },\n isValidRegister: function (name) {\n return name && inArray(name, validRegisters)\n },\n shiftNumericRegisters_: function () {\n for (var i = 9; i >= 2; i--) {\n this.registers[i] = this.getRegister('' + (i - 1))\n }\n }\n }\n function HistoryController() {\n this.historyBuffer = []\n this.iterator = 0\n this.initialPrefix = null\n }\n HistoryController.prototype = {\n // the input argument here acts a user entered prefix for a small time\n // until we start autocompletion in which case it is the autocompleted.\n nextMatch: function (input, up) {\n var historyBuffer = this.historyBuffer\n var dir = up ? -1 : 1\n if (this.initialPrefix === null) this.initialPrefix = input\n for (\n var i = this.iterator + dir;\n up ? i >= 0 : i < historyBuffer.length;\n i += dir\n ) {\n var element = historyBuffer[i]\n for (var j = 0; j <= element.length; j++) {\n if (this.initialPrefix == element.substring(0, j)) {\n this.iterator = i\n return element\n }\n }\n }\n // should return the user input in case we reach the end of buffer.\n if (i >= historyBuffer.length) {\n this.iterator = historyBuffer.length\n return this.initialPrefix\n }\n // return the last autocompleted query or exCommand as it is.\n if (i < 0) return input\n },\n pushInput: function (input) {\n var index = this.historyBuffer.indexOf(input)\n if (index > -1) this.historyBuffer.splice(index, 1)\n if (input.length) this.historyBuffer.push(input)\n },\n reset: function () {\n this.initialPrefix = null\n this.iterator = this.historyBuffer.length\n }\n }\n var commandDispatcher = {\n matchCommand: function (keys, keyMap, inputState, context) {\n var matches = commandMatches(keys, keyMap, context, inputState)\n if (!matches.full && !matches.partial) {\n return { type: 'none' }\n } else if (!matches.full && matches.partial) {\n return { type: 'partial' }\n }\n\n var bestMatch\n for (var i = 0; i < matches.full.length; i++) {\n var match = matches.full[i]\n if (!bestMatch) {\n bestMatch = match\n }\n }\n if (bestMatch.keys.slice(-11) == '') {\n var character = lastChar(keys)\n if (!character) return { type: 'none' }\n inputState.selectedCharacter = character\n }\n return { type: 'full', command: bestMatch }\n },\n processCommand: function (cm, vim, command) {\n vim.inputState.repeatOverride = command.repeatOverride\n switch (command.type) {\n case 'motion':\n this.processMotion(cm, vim, command)\n break\n case 'operator':\n this.processOperator(cm, vim, command)\n break\n case 'operatorMotion':\n this.processOperatorMotion(cm, vim, command)\n break\n case 'action':\n this.processAction(cm, vim, command)\n break\n case 'search':\n this.processSearch(cm, vim, command)\n break\n case 'ex':\n case 'keyToEx':\n this.processEx(cm, vim, command)\n break\n default:\n break\n }\n },\n processMotion: function (cm, vim, command) {\n vim.inputState.motion = command.motion\n vim.inputState.motionArgs = copyArgs(command.motionArgs)\n this.evalInput(cm, vim)\n },\n processOperator: function (cm, vim, command) {\n var inputState = vim.inputState\n if (inputState.operator) {\n if (inputState.operator === command.operator) {\n // Typing an operator twice like 'dd' makes the operator operate\n // linewise\n inputState.motion = 'expandToLine'\n inputState.motionArgs = { linewise: true }\n this.evalInput(cm, vim)\n return\n } else {\n // 2 different operators in a row doesn't make sense.\n clearInputState(cm)\n }\n }\n inputState.operator = command.operator\n inputState.operatorArgs = copyArgs(command.operatorArgs)\n if (vim.visualMode) {\n // Operating on a selection in visual mode. We don't need a motion.\n this.evalInput(cm, vim)\n }\n },\n processOperatorMotion: function (cm, vim, command) {\n var visualMode = vim.visualMode\n var operatorMotionArgs = copyArgs(command.operatorMotionArgs)\n if (operatorMotionArgs) {\n // Operator motions may have special behavior in visual mode.\n if (visualMode && operatorMotionArgs.visualLine) {\n vim.visualLine = true\n }\n }\n this.processOperator(cm, vim, command)\n if (!visualMode) {\n this.processMotion(cm, vim, command)\n }\n },\n processAction: function (cm, vim, command) {\n var inputState = vim.inputState\n var repeat = inputState.getRepeat()\n var repeatIsExplicit = !!repeat\n var actionArgs = copyArgs(command.actionArgs) || {}\n if (inputState.selectedCharacter) {\n actionArgs.selectedCharacter = inputState.selectedCharacter\n }\n // Actions may or may not have motions and operators. Do these first.\n if (command.operator) {\n this.processOperator(cm, vim, command)\n }\n if (command.motion) {\n this.processMotion(cm, vim, command)\n }\n if (command.motion || command.operator) {\n this.evalInput(cm, vim)\n }\n actionArgs.repeat = repeat || 1\n actionArgs.repeatIsExplicit = repeatIsExplicit\n actionArgs.registerName = inputState.registerName\n clearInputState(cm)\n vim.lastMotion = null\n if (command.isEdit) {\n this.recordLastEdit(vim, inputState, command)\n }\n actions[command.action](cm, actionArgs, vim)\n },\n processSearch: function (cm, vim, command) {\n if (!cm.getSearchCursor) {\n // Search depends on SearchCursor.\n return\n }\n var forward = command.searchArgs.forward\n var wholeWordOnly = command.searchArgs.wholeWordOnly\n getSearchState(cm).setReversed(!forward)\n var promptPrefix = forward ? '/' : '?'\n var originalQuery = getSearchState(cm).getQuery()\n var originalScrollPos = cm.getScrollInfo()\n function handleQuery(query, ignoreCase, smartCase) {\n vimGlobalState.searchHistoryController.pushInput(query)\n vimGlobalState.searchHistoryController.reset()\n try {\n updateSearchQuery(cm, query, ignoreCase, smartCase)\n } catch (e) {\n showConfirm(cm, 'Invalid regex: ' + query)\n clearInputState(cm)\n return\n }\n commandDispatcher.processMotion(cm, vim, {\n type: 'motion',\n motion: 'findNext',\n motionArgs: {\n forward: true,\n toJumplist: command.searchArgs.toJumplist\n }\n })\n }\n function onPromptClose(query) {\n cm.scrollTo(originalScrollPos.left, originalScrollPos.top)\n handleQuery(query, true /** ignoreCase */, true /** smartCase */)\n var macroModeState = vimGlobalState.macroModeState\n if (macroModeState.isRecording) {\n logSearchQuery(macroModeState, query)\n }\n }\n function onPromptKeyUp(e, query, close) {\n var keyName = CodeMirror.keyName(e),\n up,\n offset\n if (keyName == 'Up' || keyName == 'Down') {\n up = keyName == 'Up'\n offset = e.target ? e.target.selectionEnd : 0\n query =\n vimGlobalState.searchHistoryController.nextMatch(query, up) || ''\n close(query)\n if (offset && e.target)\n e.target.selectionEnd = e.target.selectionStart = Math.min(\n offset,\n e.target.value.length\n )\n } else {\n if (\n keyName != 'Left' &&\n keyName != 'Right' &&\n keyName != 'Ctrl' &&\n keyName != 'Alt' &&\n keyName != 'Shift'\n ) {\n vimGlobalState.searchHistoryController.reset()\n }\n }\n var parsedQuery\n try {\n parsedQuery = updateSearchQuery(\n cm,\n query,\n true /** ignoreCase */,\n true /** smartCase */\n )\n } catch (e) {\n // Swallow bad regexes for incremental search.\n }\n if (parsedQuery) {\n cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30)\n } else {\n clearSearchHighlight(cm)\n cm.scrollTo(originalScrollPos.left, originalScrollPos.top)\n }\n }\n function onPromptKeyDown(e, query, close) {\n var keyName = CodeMirror.keyName(e)\n if (\n keyName == 'Esc' ||\n keyName == 'Ctrl-C' ||\n keyName == 'Ctrl-[' ||\n (keyName == 'Backspace' && query == '')\n ) {\n vimGlobalState.searchHistoryController.pushInput(query)\n vimGlobalState.searchHistoryController.reset()\n updateSearchQuery(cm, originalQuery)\n clearSearchHighlight(cm)\n cm.scrollTo(originalScrollPos.left, originalScrollPos.top)\n CodeMirror.e_stop(e)\n clearInputState(cm)\n close()\n cm.focus()\n } else if (keyName == 'Up' || keyName == 'Down') {\n CodeMirror.e_stop(e)\n } else if (keyName == 'Ctrl-U') {\n // Ctrl-U clears input.\n CodeMirror.e_stop(e)\n close('')\n }\n }\n switch (command.searchArgs.querySrc) {\n case 'prompt':\n var macroModeState = vimGlobalState.macroModeState\n if (macroModeState.isPlaying) {\n var query = macroModeState.replaySearchQueries.shift()\n handleQuery(query, true /** ignoreCase */, false /** smartCase */)\n } else {\n showPrompt(cm, {\n onClose: onPromptClose,\n prefix: promptPrefix,\n desc: searchPromptDesc,\n onKeyUp: onPromptKeyUp,\n onKeyDown: onPromptKeyDown\n })\n }\n break\n case 'wordUnderCursor':\n var word = expandWordUnderCursor(\n cm,\n false /** inclusive */,\n true /** forward */,\n false /** bigWord */,\n true /** noSymbol */\n )\n var isKeyword = true\n if (!word) {\n word = expandWordUnderCursor(\n cm,\n false /** inclusive */,\n true /** forward */,\n false /** bigWord */,\n false /** noSymbol */\n )\n isKeyword = false\n }\n if (!word) {\n return\n }\n var query = cm\n .getLine(word.start.line)\n .substring(word.start.ch, word.end.ch)\n if (isKeyword && wholeWordOnly) {\n query = '\\\\b' + query + '\\\\b'\n } else {\n query = escapeRegex(query)\n }\n\n // cachedCursor is used to save the old position of the cursor\n // when * or # causes vim to seek for the nearest word and shift\n // the cursor before entering the motion.\n vimGlobalState.jumpList.cachedCursor = cm.getCursor()\n cm.setCursor(word.start)\n\n handleQuery(query, true /** ignoreCase */, false /** smartCase */)\n break\n }\n },\n processEx: function (cm, vim, command) {\n function onPromptClose(input) {\n // Give the prompt some time to close so that if processCommand shows\n // an error, the elements don't overlap.\n vimGlobalState.exCommandHistoryController.pushInput(input)\n vimGlobalState.exCommandHistoryController.reset()\n exCommandDispatcher.processCommand(cm, input)\n }\n function onPromptKeyDown(e, input, close) {\n var keyName = CodeMirror.keyName(e),\n up,\n offset\n if (\n keyName === 'Esc' ||\n keyName === 'Ctrl-C' ||\n keyName === 'Ctrl-[' ||\n (keyName === 'Backspace' && input === '')\n ) {\n vimGlobalState.exCommandHistoryController.pushInput(input)\n vimGlobalState.exCommandHistoryController.reset()\n CodeMirror.e_stop(e)\n clearInputState(cm)\n close()\n cm.focus()\n }\n if (keyName === 'Up' || keyName === 'Down') {\n CodeMirror.e_stop(e)\n up = keyName === 'Up'\n offset = e.target ? e.target.selectionEnd : 0\n input =\n vimGlobalState.exCommandHistoryController.nextMatch(input, up) ||\n ''\n close(input)\n if (offset && e.target)\n e.target.selectionEnd = e.target.selectionStart = Math.min(\n offset,\n e.target.value.length\n )\n } else if (keyName === 'Ctrl-U') {\n // Ctrl-U clears input.\n CodeMirror.e_stop(e)\n close('')\n } else {\n if (\n keyName !== 'Left' &&\n keyName !== 'Right' &&\n keyName !== 'Ctrl' &&\n keyName !== 'Alt' &&\n keyName !== 'Shift'\n ) {\n vimGlobalState.exCommandHistoryController.reset()\n }\n }\n }\n if (command.type === 'keyToEx') {\n // Handle user defined Ex to Ex mappings\n exCommandDispatcher.processCommand(cm, command.exArgs.input)\n } else {\n if (vim.visualMode) {\n showPrompt(cm, {\n onClose: onPromptClose,\n prefix: ':',\n value: \"'<,'>\",\n onKeyDown: onPromptKeyDown\n })\n } else {\n showPrompt(cm, {\n onClose: onPromptClose,\n prefix: ':',\n onKeyDown: onPromptKeyDown\n })\n }\n }\n },\n evalInput: function (cm, vim) {\n // If the motion command is set, execute both the operator and motion.\n // Otherwise return.\n var inputState = vim.inputState\n var motion = inputState.motion\n var motionArgs = inputState.motionArgs || {}\n var operator = inputState.operator\n var operatorArgs = inputState.operatorArgs || {}\n var registerName = inputState.registerName\n var sel = vim.sel\n // TODO: Make sure cm and vim selections are identical outside visual mode.\n var origHead = copyCursor(\n vim.visualMode\n ? clipCursorToContent(cm, sel.head)\n : cm.getCursor('head')\n )\n var origAnchor = copyCursor(\n vim.visualMode\n ? clipCursorToContent(cm, sel.anchor)\n : cm.getCursor('anchor')\n )\n var oldHead = copyCursor(origHead)\n var oldAnchor = copyCursor(origAnchor)\n var newHead, newAnchor\n var repeat\n if (operator) {\n this.recordLastEdit(vim, inputState)\n }\n if (inputState.repeatOverride !== undefined) {\n // If repeatOverride is specified, that takes precedence over the\n // input state's repeat. Used by Ex mode and can be user defined.\n repeat = inputState.repeatOverride\n } else {\n repeat = inputState.getRepeat()\n }\n if (repeat > 0 && motionArgs.explicitRepeat) {\n motionArgs.repeatIsExplicit = true\n } else if (\n motionArgs.noRepeat ||\n (!motionArgs.explicitRepeat && repeat === 0)\n ) {\n repeat = 1\n motionArgs.repeatIsExplicit = false\n }\n if (inputState.selectedCharacter) {\n // If there is a character input, stick it in all of the arg arrays.\n motionArgs.selectedCharacter = operatorArgs.selectedCharacter =\n inputState.selectedCharacter\n }\n motionArgs.repeat = repeat\n clearInputState(cm)\n if (motion) {\n var motionResult = motions[motion](cm, origHead, motionArgs, vim)\n vim.lastMotion = motions[motion]\n if (!motionResult) {\n return\n }\n if (motionArgs.toJumplist) {\n var jumpList = vimGlobalState.jumpList\n // if the current motion is # or *, use cachedCursor\n var cachedCursor = jumpList.cachedCursor\n if (cachedCursor) {\n recordJumpPosition(cm, cachedCursor, motionResult)\n delete jumpList.cachedCursor\n } else {\n recordJumpPosition(cm, origHead, motionResult)\n }\n }\n if (motionResult instanceof Array) {\n newAnchor = motionResult[0]\n newHead = motionResult[1]\n } else {\n newHead = motionResult\n }\n // TODO: Handle null returns from motion commands better.\n if (!newHead) {\n newHead = copyCursor(origHead)\n }\n if (vim.visualMode) {\n if (!(vim.visualBlock && newHead.ch === Infinity)) {\n newHead = clipCursorToContent(cm, newHead, vim.visualBlock)\n }\n if (newAnchor) {\n newAnchor = clipCursorToContent(cm, newAnchor, true)\n }\n newAnchor = newAnchor || oldAnchor\n sel.anchor = newAnchor\n sel.head = newHead\n updateCmSelection(cm)\n updateMark(\n cm,\n vim,\n '<',\n cursorIsBefore(newAnchor, newHead) ? newAnchor : newHead\n )\n updateMark(\n cm,\n vim,\n '>',\n cursorIsBefore(newAnchor, newHead) ? newHead : newAnchor\n )\n } else if (!operator) {\n newHead = clipCursorToContent(cm, newHead)\n cm.setCursor(newHead.line, newHead.ch)\n }\n }\n if (operator) {\n if (operatorArgs.lastSel) {\n // Replaying a visual mode operation\n newAnchor = oldAnchor\n var lastSel = operatorArgs.lastSel\n var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line)\n var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch)\n if (lastSel.visualLine) {\n // Linewise Visual mode: The same number of lines.\n newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch)\n } else if (lastSel.visualBlock) {\n // Blockwise Visual mode: The same number of lines and columns.\n newHead = Pos(\n oldAnchor.line + lineOffset,\n oldAnchor.ch + chOffset\n )\n } else if (lastSel.head.line == lastSel.anchor.line) {\n // Normal Visual mode within one line: The same number of characters.\n newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset)\n } else {\n // Normal Visual mode with several lines: The same number of lines, in the\n // last line the same number of characters as in the last line the last time.\n newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch)\n }\n vim.visualMode = true\n vim.visualLine = lastSel.visualLine\n vim.visualBlock = lastSel.visualBlock\n sel = vim.sel = {\n anchor: newAnchor,\n head: newHead\n }\n updateCmSelection(cm)\n } else if (vim.visualMode) {\n operatorArgs.lastSel = {\n anchor: copyCursor(sel.anchor),\n head: copyCursor(sel.head),\n visualBlock: vim.visualBlock,\n visualLine: vim.visualLine\n }\n }\n var curStart, curEnd, linewise, mode\n var cmSel\n if (vim.visualMode) {\n // Init visual op\n curStart = cursorMin(sel.head, sel.anchor)\n curEnd = cursorMax(sel.head, sel.anchor)\n linewise = vim.visualLine || operatorArgs.linewise\n mode = vim.visualBlock ? 'block' : linewise ? 'line' : 'char'\n cmSel = makeCmSelection(\n cm,\n {\n anchor: curStart,\n head: curEnd\n },\n mode\n )\n if (linewise) {\n var ranges = cmSel.ranges\n if (mode == 'block') {\n // Linewise operators in visual block mode extend to end of line\n for (var i = 0; i < ranges.length; i++) {\n ranges[i].head.ch = lineLength(cm, ranges[i].head.line)\n }\n } else if (mode == 'line') {\n ranges[0].head = Pos(ranges[0].head.line + 1, 0)\n }\n }\n } else {\n // Init motion op\n curStart = copyCursor(newAnchor || oldAnchor)\n curEnd = copyCursor(newHead || oldHead)\n if (cursorIsBefore(curEnd, curStart)) {\n var tmp = curStart\n curStart = curEnd\n curEnd = tmp\n }\n linewise = motionArgs.linewise || operatorArgs.linewise\n if (linewise) {\n // Expand selection to entire line.\n expandSelectionToLine(cm, curStart, curEnd)\n } else if (motionArgs.forward) {\n // Clip to trailing newlines only if the motion goes forward.\n clipToLine(cm, curStart, curEnd)\n }\n mode = 'char'\n var exclusive = !motionArgs.inclusive || linewise\n cmSel = makeCmSelection(\n cm,\n {\n anchor: curStart,\n head: curEnd\n },\n mode,\n exclusive\n )\n }\n cm.setSelections(cmSel.ranges, cmSel.primary)\n vim.lastMotion = null\n operatorArgs.repeat = repeat // For indent in visual mode.\n operatorArgs.registerName = registerName\n // Keep track of linewise as it affects how paste and change behave.\n operatorArgs.linewise = linewise\n var operatorMoveTo = operators[operator](\n cm,\n operatorArgs,\n cmSel.ranges,\n oldAnchor,\n newHead\n )\n if (vim.visualMode) {\n exitVisualMode(cm, operatorMoveTo != null)\n }\n if (operatorMoveTo) {\n cm.setCursor(operatorMoveTo)\n }\n }\n },\n recordLastEdit: function (vim, inputState, actionCommand) {\n var macroModeState = vimGlobalState.macroModeState\n if (macroModeState.isPlaying) {\n return\n }\n vim.lastEditInputState = inputState\n vim.lastEditActionCommand = actionCommand\n macroModeState.lastInsertModeChanges.changes = []\n macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false\n }\n }\n\n /**\n * typedef {Object{line:number,ch:number}} Cursor An object containing the\n * position of the cursor.\n */\n // All of the functions below return Cursor objects.\n var motions = {\n moveToTopLine: function (cm, _head, motionArgs) {\n var line = getUserVisibleLines(cm).top + motionArgs.repeat - 1\n return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)))\n },\n moveToMiddleLine: function (cm) {\n var range = getUserVisibleLines(cm)\n var line = Math.floor((range.top + range.bottom) * 0.5)\n return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)))\n },\n moveToBottomLine: function (cm, _head, motionArgs) {\n var line = getUserVisibleLines(cm).bottom - motionArgs.repeat + 1\n return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)))\n },\n expandToLine: function (_cm, head, motionArgs) {\n // Expands forward to end of line, and then to next line if repeat is\n // >1. Does not handle backward motion!\n var cur = head\n return Pos(cur.line + motionArgs.repeat - 1, Infinity)\n },\n findNext: function (cm, _head, motionArgs) {\n var state = getSearchState(cm)\n var query = state.getQuery()\n if (!query) {\n return\n }\n var prev = !motionArgs.forward\n // If search is initiated with ? instead of /, negate direction.\n prev = state.isReversed() ? !prev : prev\n highlightSearchMatches(cm, query)\n return findNext(cm, prev /** prev */, query, motionArgs.repeat)\n },\n goToMark: function (cm, _head, motionArgs, vim) {\n var pos = getMarkPos(cm, vim, motionArgs.selectedCharacter)\n if (pos) {\n return motionArgs.linewise\n ? {\n line: pos.line,\n ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line))\n }\n : pos\n }\n return null\n },\n moveToOtherHighlightedEnd: function (cm, _head, motionArgs, vim) {\n if (vim.visualBlock && motionArgs.sameLine) {\n var sel = vim.sel\n return [\n clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)),\n clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch))\n ]\n } else {\n return [vim.sel.head, vim.sel.anchor]\n }\n },\n jumpToMark: function (cm, head, motionArgs, vim) {\n var best = head\n for (var i = 0; i < motionArgs.repeat; i++) {\n var cursor = best\n for (var key in vim.marks) {\n if (!isLowerCase(key)) {\n continue\n }\n var mark = vim.marks[key].find()\n var isWrongDirection = motionArgs.forward\n ? cursorIsBefore(mark, cursor)\n : cursorIsBefore(cursor, mark)\n\n if (isWrongDirection) {\n continue\n }\n if (motionArgs.linewise && mark.line == cursor.line) {\n continue\n }\n\n var equal = cursorEqual(cursor, best)\n var between = motionArgs.forward\n ? cursorIsBetween(cursor, mark, best)\n : cursorIsBetween(best, mark, cursor)\n\n if (equal || between) {\n best = mark\n }\n }\n }\n\n if (motionArgs.linewise) {\n // Vim places the cursor on the first non-whitespace character of\n // the line if there is one, else it places the cursor at the end\n // of the line, regardless of whether a mark was found.\n best = Pos(\n best.line,\n findFirstNonWhiteSpaceCharacter(cm.getLine(best.line))\n )\n }\n return best\n },\n moveByCharacters: function (_cm, head, motionArgs) {\n var cur = head\n var repeat = motionArgs.repeat\n var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat\n return Pos(cur.line, ch)\n },\n moveByLines: function (cm, head, motionArgs, vim) {\n var cur = head\n var endCh = cur.ch\n // Depending what our last motion was, we may want to do different\n // things. If our last motion was moving vertically, we want to\n // preserve the HPos from our last horizontal move. If our last motion\n // was going to the end of a line, moving vertically we should go to\n // the end of the line, etc.\n switch (vim.lastMotion) {\n case this.moveByLines:\n case this.moveByDisplayLines:\n case this.moveByScroll:\n case this.moveToColumn:\n case this.moveToEol:\n endCh = vim.lastHPos\n break\n default:\n vim.lastHPos = endCh\n }\n var repeat = motionArgs.repeat + (motionArgs.repeatOffset || 0)\n var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat\n var first = cm.firstLine()\n var last = cm.lastLine()\n // Vim go to line begin or line end when cursor at first/last line and\n // move to previous/next line is triggered.\n if (line < first && cur.line == first) {\n return this.moveToStartOfLine(cm, head, motionArgs, vim)\n } else if (line > last && cur.line == last) {\n return this.moveToEol(cm, head, motionArgs, vim)\n }\n if (motionArgs.toFirstChar) {\n endCh = findFirstNonWhiteSpaceCharacter(cm.getLine(line))\n vim.lastHPos = endCh\n }\n vim.lastHSPos = cm.charCoords(Pos(line, endCh), 'div').left\n return Pos(line, endCh)\n },\n moveByDisplayLines: function (cm, head, motionArgs, vim) {\n var cur = head\n switch (vim.lastMotion) {\n case this.moveByDisplayLines:\n case this.moveByScroll:\n case this.moveByLines:\n case this.moveToColumn:\n case this.moveToEol:\n break\n default:\n vim.lastHSPos = cm.charCoords(cur, 'div').left\n }\n var repeat = motionArgs.repeat\n var res = cm.findPosV(\n cur,\n motionArgs.forward ? repeat : -repeat,\n 'line',\n vim.lastHSPos\n )\n if (res.hitSide) {\n if (motionArgs.forward) {\n var lastCharCoords = cm.charCoords(res, 'div')\n var goalCoords = {\n top: lastCharCoords.top + 8,\n left: vim.lastHSPos\n }\n var res = cm.coordsChar(goalCoords, 'div')\n } else {\n var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div')\n resCoords.left = vim.lastHSPos\n res = cm.coordsChar(resCoords, 'div')\n }\n }\n vim.lastHPos = res.ch\n return res\n },\n moveByPage: function (cm, head, motionArgs) {\n // CodeMirror only exposes functions that move the cursor page down, so\n // doing this bad hack to move the cursor and move it back. evalInput\n // will move the cursor to where it should be in the end.\n var curStart = head\n var repeat = motionArgs.repeat\n return cm.findPosV(\n curStart,\n motionArgs.forward ? repeat : -repeat,\n 'page'\n )\n },\n moveByParagraph: function (cm, head, motionArgs) {\n var dir = motionArgs.forward ? 1 : -1\n return findParagraph(cm, head, motionArgs.repeat, dir)\n },\n moveByScroll: function (cm, head, motionArgs, vim) {\n var scrollbox = cm.getScrollInfo()\n var curEnd = null\n var repeat = motionArgs.repeat\n if (!repeat) {\n repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight())\n }\n var orig = cm.charCoords(head, 'local')\n motionArgs.repeat = repeat\n var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim)\n if (!curEnd) {\n return null\n }\n var dest = cm.charCoords(curEnd, 'local')\n cm.scrollTo(null, scrollbox.top + dest.top - orig.top)\n return curEnd\n },\n moveByWords: function (cm, head, motionArgs) {\n return moveToWord(\n cm,\n head,\n motionArgs.repeat,\n !!motionArgs.forward,\n !!motionArgs.wordEnd,\n !!motionArgs.bigWord\n )\n },\n moveTillCharacter: function (cm, _head, motionArgs) {\n var repeat = motionArgs.repeat\n var curEnd = moveToCharacter(\n cm,\n repeat,\n motionArgs.forward,\n motionArgs.selectedCharacter\n )\n var increment = motionArgs.forward ? -1 : 1\n recordLastCharacterSearch(increment, motionArgs)\n if (!curEnd) return null\n curEnd.ch += increment\n return curEnd\n },\n moveToCharacter: function (cm, head, motionArgs) {\n var repeat = motionArgs.repeat\n recordLastCharacterSearch(0, motionArgs)\n logger.debug('moveToCharacter:', motionArgs)\n return (\n moveToCharacter(\n cm,\n repeat,\n motionArgs.forward,\n motionArgs.selectedCharacter\n ) || head\n )\n },\n moveToSymbol: function (cm, head, motionArgs) {\n var repeat = motionArgs.repeat\n return (\n findSymbol(\n cm,\n repeat,\n motionArgs.forward,\n motionArgs.selectedCharacter\n ) || head\n )\n },\n moveToColumn: function (cm, head, motionArgs, vim) {\n var repeat = motionArgs.repeat\n // repeat is equivalent to which column we want to move to!\n vim.lastHPos = repeat - 1\n vim.lastHSPos = cm.charCoords(head, 'div').left\n return moveToColumn(cm, repeat)\n },\n moveToEol: function (cm, head, motionArgs, vim) {\n var cur = head\n vim.lastHPos = Infinity\n var retval = Pos(cur.line + motionArgs.repeat - 1, Infinity)\n var end = cm.clipPos(retval)\n end.ch--\n vim.lastHSPos = cm.charCoords(end, 'div').left\n return retval\n },\n moveToFirstNonWhiteSpaceCharacter: function (cm, head) {\n // Go to the start of the line where the text begins, or the end for\n // whitespace-only lines\n var cursor = head\n return Pos(\n cursor.line,\n findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))\n )\n },\n moveToMatchedSymbol: function (cm, head) {\n var cursor = head\n var line = cursor.line\n var ch = cursor.ch\n var lineText = cm.getLine(line)\n var symbol\n for (; ch < lineText.length; ch++) {\n symbol = lineText.charAt(ch)\n if (symbol && isMatchableSymbol(symbol)) {\n var style = cm.getTokenTypeAt(Pos(line, ch + 1))\n if (style !== 'string' && style !== 'comment') {\n break\n }\n }\n }\n if (ch < lineText.length) {\n var matched = cm.findMatchingBracket(Pos(line, ch))\n return matched.to\n } else {\n return cursor\n }\n },\n moveToStartOfLine: function (_cm, head) {\n return Pos(head.line, 0)\n },\n moveToLineOrEdgeOfDocument: function (cm, _head, motionArgs) {\n var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine()\n if (motionArgs.repeatIsExplicit) {\n lineNum = motionArgs.repeat - cm.getOption('firstLineNumber')\n }\n return Pos(\n lineNum,\n findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))\n )\n },\n textObjectManipulation: function (cm, head, motionArgs, vim) {\n // TODO: lots of possible exceptions that can be thrown here. Try da(\n // outside of a () block.\n\n // TODO: adding <> >< to this map doesn't work, presumably because\n // they're operators\n var mirroredPairs = {\n '(': ')',\n ')': '(',\n '{': '}',\n '}': '{',\n '[': ']',\n ']': '['\n }\n var selfPaired = { \"'\": true, '\"': true }\n\n var character = motionArgs.selectedCharacter\n // 'b' refers to '()' block.\n // 'B' refers to '{}' block.\n if (character == 'b') {\n character = '('\n } else if (character == 'B') {\n character = '{'\n }\n\n // Inclusive is the difference between a and i\n // TODO: Instead of using the additional text object map to perform text\n // object operations, merge the map into the defaultKeyMap and use\n // motionArgs to define behavior. Define separate entries for 'aw',\n // 'iw', 'a[', 'i[', etc.\n var inclusive = !motionArgs.textObjectInner\n\n var tmp\n if (mirroredPairs[character]) {\n tmp = selectCompanionObject(cm, head, character, inclusive)\n } else if (selfPaired[character]) {\n tmp = findBeginningAndEnd(cm, head, character, inclusive)\n } else if (character === 'W') {\n tmp = expandWordUnderCursor(\n cm,\n inclusive,\n true /** forward */,\n true /** bigWord */\n )\n } else if (character === 'w') {\n tmp = expandWordUnderCursor(\n cm,\n inclusive,\n true /** forward */,\n false /** bigWord */\n )\n } else if (character === 'p') {\n tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive)\n motionArgs.linewise = true\n if (vim.visualMode) {\n if (!vim.visualLine) {\n vim.visualLine = true\n }\n } else {\n var operatorArgs = vim.inputState.operatorArgs\n if (operatorArgs) {\n operatorArgs.linewise = true\n }\n tmp.end.line--\n }\n } else {\n // No text object defined for this, don't move.\n return null\n }\n\n if (!cm.state.vim.visualMode) {\n return [tmp.start, tmp.end]\n } else {\n return expandSelection(cm, tmp.start, tmp.end)\n }\n },\n\n repeatLastCharacterSearch: function (cm, head, motionArgs) {\n var lastSearch = vimGlobalState.lastCharacterSearch\n var repeat = motionArgs.repeat\n var forward = motionArgs.forward === lastSearch.forward\n var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1)\n cm.moveH(-increment, 'char')\n motionArgs.inclusive = !!forward\n var curEnd = moveToCharacter(\n cm,\n repeat,\n forward,\n lastSearch.selectedCharacter\n )\n if (!curEnd) {\n cm.moveH(increment, 'char')\n return head\n }\n curEnd.ch += increment\n return curEnd\n }\n }\n\n function defineMotion(name, fn) {\n motions[name] = fn\n }\n\n function fillArray(val, times) {\n var arr = []\n for (var i = 0; i < times; i++) {\n arr.push(val)\n }\n return arr\n }\n /**\n * An operator acts on a text selection. It receives the list of selections\n * as input. The corresponding CodeMirror selection is guaranteed to\n * match the input selection.\n */\n var operators = {\n change: function (cm, args, ranges) {\n var finalHead, text\n var vim = cm.state.vim\n vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock =\n vim.visualBlock\n if (!vim.visualMode) {\n var anchor = ranges[0].anchor,\n head = ranges[0].head\n text = cm.getRange(anchor, head)\n var lastState = vim.lastEditInputState || {}\n if (lastState.motion == 'moveByWords' && !isWhiteSpaceString(text)) {\n // Exclude trailing whitespace if the range is not all whitespace.\n var match = /\\s+$/.exec(text)\n if (match && lastState.motionArgs && lastState.motionArgs.forward) {\n head = offsetCursor(head, 0, -match[0].length)\n text = text.slice(0, -match[0].length)\n }\n }\n var prevLineEnd = new Pos(anchor.line - 1, Number.MAX_VALUE)\n var wasLastLine = cm.firstLine() == cm.lastLine()\n if (head.line > cm.lastLine() && args.linewise && !wasLastLine) {\n cm.replaceRange('', prevLineEnd, head)\n } else {\n cm.replaceRange('', anchor, head)\n }\n if (args.linewise) {\n // Push the next line back down, if there is a next line.\n if (!wasLastLine) {\n cm.setCursor(prevLineEnd)\n CodeMirror.commands.newlineAndIndent(cm)\n }\n // make sure cursor ends up at the end of the line.\n anchor.ch = Number.MAX_VALUE\n }\n finalHead = anchor\n } else {\n text = cm.getSelection()\n var replacement = fillArray('', ranges.length)\n cm.replaceSelections(replacement)\n finalHead = cursorMin(ranges[0].head, ranges[0].anchor)\n }\n vimGlobalState.registerController.pushText(\n args.registerName,\n 'change',\n text,\n args.linewise,\n ranges.length > 1\n )\n actions.enterInsertMode(cm, { head: finalHead }, cm.state.vim)\n },\n // delete is a javascript keyword.\n delete: function (cm, args, ranges) {\n var finalHead, text\n var vim = cm.state.vim\n if (!vim.visualBlock) {\n var anchor = ranges[0].anchor,\n head = ranges[0].head\n if (\n args.linewise &&\n head.line != cm.firstLine() &&\n anchor.line == cm.lastLine() &&\n anchor.line == head.line - 1\n ) {\n // Special case for dd on last line (and first line).\n if (anchor.line == cm.firstLine()) {\n anchor.ch = 0\n } else {\n anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1))\n }\n }\n text = cm.getRange(anchor, head)\n cm.replaceRange('', anchor, head)\n finalHead = anchor\n if (args.linewise) {\n finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor)\n }\n } else {\n text = cm.getSelection()\n var replacement = fillArray('', ranges.length)\n cm.replaceSelections(replacement)\n finalHead = ranges[0].anchor\n }\n vimGlobalState.registerController.pushText(\n args.registerName,\n 'delete',\n text,\n args.linewise,\n vim.visualBlock\n )\n var includeLineBreak = vim.insertMode\n return clipCursorToContent(cm, finalHead, includeLineBreak)\n },\n indent: function (cm, args, ranges) {\n var vim = cm.state.vim\n var startLine = ranges[0].anchor.line\n var endLine = vim.visualBlock\n ? ranges[ranges.length - 1].anchor.line\n : ranges[0].head.line\n // In visual mode, n> shifts the selection right n times, instead of\n // shifting n lines right once.\n var repeat = vim.visualMode ? args.repeat : 1\n if (args.linewise) {\n // The only way to delete a newline is to delete until the start of\n // the next line, so in linewise mode evalInput will include the next\n // line. We don't want this in indent, so we go back a line.\n endLine--\n }\n for (var i = startLine; i <= endLine; i++) {\n for (var j = 0; j < repeat; j++) {\n cm.indentLine(i, args.indentRight)\n }\n }\n return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor)\n },\n changeCase: function (cm, args, ranges, oldAnchor, newHead) {\n var selections = cm.getSelections()\n var swapped = []\n var toLower = args.toLower\n for (var j = 0; j < selections.length; j++) {\n var toSwap = selections[j]\n var text = ''\n if (toLower === true) {\n text = toSwap.toLowerCase()\n } else if (toLower === false) {\n text = toSwap.toUpperCase()\n } else {\n for (var i = 0; i < toSwap.length; i++) {\n var character = toSwap.charAt(i)\n text += isUpperCase(character)\n ? character.toLowerCase()\n : character.toUpperCase()\n }\n }\n swapped.push(text)\n }\n cm.replaceSelections(swapped)\n if (args.shouldMoveCursor) {\n return newHead\n } else if (\n !cm.state.vim.visualMode &&\n args.linewise &&\n ranges[0].anchor.line + 1 == ranges[0].head.line\n ) {\n return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor)\n } else if (args.linewise) {\n return oldAnchor\n } else {\n return cursorMin(ranges[0].anchor, ranges[0].head)\n }\n },\n yank: function (cm, args, ranges, oldAnchor) {\n var vim = cm.state.vim\n var text = cm.getSelection()\n var endPos = vim.visualMode\n ? cursorMin(\n vim.sel.anchor,\n vim.sel.head,\n ranges[0].head,\n ranges[0].anchor\n )\n : oldAnchor\n vimGlobalState.registerController.pushText(\n args.registerName,\n 'yank',\n text,\n args.linewise,\n vim.visualBlock\n )\n return endPos\n }\n }\n\n function defineOperator(name, fn) {\n operators[name] = fn\n }\n\n var actions = {\n jumpListWalk: function (cm, actionArgs, vim) {\n if (vim.visualMode) {\n return\n }\n var repeat = actionArgs.repeat\n var forward = actionArgs.forward\n var jumpList = vimGlobalState.jumpList\n\n var mark = jumpList.move(cm, forward ? repeat : -repeat)\n var markPos = mark ? mark.find() : undefined\n markPos = markPos || cm.getCursor()\n cm.setCursor(markPos)\n },\n scroll: function (cm, actionArgs, vim) {\n if (vim.visualMode) {\n return\n }\n var repeat = actionArgs.repeat || 1\n var lineHeight = cm.defaultTextHeight()\n var top = cm.getScrollInfo().top\n var delta = lineHeight * repeat\n var newPos = actionArgs.forward ? top + delta : top - delta\n var cursor = copyCursor(cm.getCursor())\n var cursorCoords = cm.charCoords(cursor, 'local')\n if (actionArgs.forward) {\n if (newPos > cursorCoords.top) {\n cursor.line += (newPos - cursorCoords.top) / lineHeight\n cursor.line = Math.ceil(cursor.line)\n cm.setCursor(cursor)\n cursorCoords = cm.charCoords(cursor, 'local')\n cm.scrollTo(null, cursorCoords.top)\n } else {\n // Cursor stays within bounds. Just reposition the scroll window.\n cm.scrollTo(null, newPos)\n }\n } else {\n var newBottom = newPos + cm.getScrollInfo().clientHeight\n if (newBottom < cursorCoords.bottom) {\n cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight\n cursor.line = Math.floor(cursor.line)\n cm.setCursor(cursor)\n cursorCoords = cm.charCoords(cursor, 'local')\n cm.scrollTo(\n null,\n cursorCoords.bottom - cm.getScrollInfo().clientHeight\n )\n } else {\n // Cursor stays within bounds. Just reposition the scroll window.\n cm.scrollTo(null, newPos)\n }\n }\n },\n scrollToCursor: function (cm, actionArgs) {\n var lineNum = cm.getCursor().line\n var charCoords = cm.charCoords(Pos(lineNum, 0), 'local')\n var height = cm.getScrollInfo().clientHeight\n var y = charCoords.top\n var lineHeight = charCoords.bottom - y\n switch (actionArgs.position) {\n case 'center':\n y = y - height / 2 + lineHeight\n break\n case 'bottom':\n y = y - height + lineHeight\n break\n }\n cm.scrollTo(null, y)\n },\n replayMacro: function (cm, actionArgs, vim) {\n var registerName = actionArgs.selectedCharacter\n var repeat = actionArgs.repeat\n var macroModeState = vimGlobalState.macroModeState\n if (registerName == '@') {\n registerName = macroModeState.latestRegister\n }\n while (repeat--) {\n executeMacroRegister(cm, vim, macroModeState, registerName)\n }\n },\n enterMacroRecordMode: function (cm, actionArgs) {\n var macroModeState = vimGlobalState.macroModeState\n var registerName = actionArgs.selectedCharacter\n if (vimGlobalState.registerController.isValidRegister(registerName)) {\n macroModeState.enterMacroRecordMode(cm, registerName)\n }\n },\n toggleOverwrite: function (cm) {\n if (!cm.state.overwrite) {\n cm.toggleOverwrite(true)\n cm.setOption('keyMap', 'vim-replace')\n CodeMirror.signal(cm, 'vim-mode-change', { mode: 'replace' })\n } else {\n cm.toggleOverwrite(false)\n cm.setOption('keyMap', 'vim-insert')\n CodeMirror.signal(cm, 'vim-mode-change', { mode: 'insert' })\n }\n },\n enterInsertMode: function (cm, actionArgs, vim) {\n if (cm.getOption('readOnly')) {\n return\n }\n cm.getWrapperElement().classList.add('insert-mode')\n cm.getWrapperElement().classList.remove('visual-mode')\n cm.getWrapperElement().classList.remove('normal-mode')\n vim.insertMode = true\n vim.insertModeRepeat = (actionArgs && actionArgs.repeat) || 1\n var insertAt = actionArgs ? actionArgs.insertAt : null\n var sel = vim.sel\n var head = actionArgs.head || cm.getCursor('head')\n var height = cm.listSelections().length\n if (insertAt == 'eol') {\n head = Pos(head.line, lineLength(cm, head.line))\n } else if (insertAt == 'charAfter') {\n head = offsetCursor(head, 0, 1)\n } else if (insertAt == 'firstNonBlank') {\n head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head)\n } else if (insertAt == 'startOfSelectedArea') {\n logger.debug('startOfSelectedArea:', vim.visualBlock)\n logger.debug('sel:', JSON.stringify(sel, null, 2))\n if (!vim.visualBlock) {\n if (sel.head.line < sel.anchor.line) {\n head = sel.head\n } else {\n head = Pos(sel.anchor.line, 0)\n }\n } else {\n head = Pos(\n Math.min(sel.head.line, sel.anchor.line),\n Math.min(sel.head.ch, sel.anchor.ch)\n )\n height = Math.abs(sel.head.line - sel.anchor.line) + 1\n }\n } else if (insertAt == 'endOfSelectedArea') {\n if (!vim.visualBlock) {\n if (sel.head.line >= sel.anchor.line) {\n head = offsetCursor(sel.head, 0, 1)\n } else {\n head = Pos(sel.anchor.line, 0)\n }\n } else {\n head = Pos(\n Math.min(sel.head.line, sel.anchor.line),\n Math.max(sel.head.ch + 1, sel.anchor.ch)\n )\n height = Math.abs(sel.head.line - sel.anchor.line) + 1\n }\n } else if (insertAt == 'inplace') {\n if (vim.visualMode) {\n return\n }\n }\n cm.setOption('disableInput', false)\n if (vim.visualMode) {\n exitVisualMode(cm)\n }\n if (actionArgs && actionArgs.replace) {\n // Handle Replace-mode as a special case of insert mode.\n cm.toggleOverwrite(true)\n cm.setOption('keyMap', 'vim-replace')\n CodeMirror.signal(cm, 'vim-mode-change', { mode: 'replace' })\n } else {\n cm.toggleOverwrite(false)\n cm.setOption('keyMap', 'vim-insert')\n CodeMirror.signal(cm, 'vim-mode-change', { mode: 'insert' })\n }\n if (!vimGlobalState.macroModeState.isPlaying) {\n // Only record if not replaying.\n cm.on('change', onChange)\n CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown)\n }\n selectForInsert(cm, head, height)\n },\n toggleVisualMode: function (cm, actionArgs, vim) {\n logger.debug('toggleVisualMode', actionArgs)\n var repeat = actionArgs.repeat\n var anchor = cm.getCursor()\n var head\n // TODO: The repeat should actually select number of characters/lines\n // equal to the repeat times the size of the previous visual\n // operation.\n if (!vim.visualMode) {\n // Entering visual mode\n vim.visualMode = true\n vim.visualLine = !!actionArgs.linewise\n vim.visualBlock = !!actionArgs.blockwise\n head = clipCursorToContent(\n cm,\n Pos(anchor.line, anchor.ch + repeat - 1),\n true /** includeLineBreak */\n )\n vim.sel = {\n anchor: anchor,\n head: head\n }\n CodeMirror.signal(cm, 'vim-mode-change', {\n mode: 'visual',\n subMode: vim.visualLine\n ? 'linewise'\n : vim.visualBlock\n ? 'blockwise'\n : ''\n })\n updateCmSelection(cm)\n updateMark(cm, vim, '<', cursorMin(anchor, head))\n updateMark(cm, vim, '>', cursorMax(anchor, head))\n } else if (\n vim.visualLine ^ actionArgs.linewise ||\n vim.visualBlock ^ actionArgs.blockwise\n ) {\n // Toggling between modes\n vim.visualLine = !!actionArgs.linewise\n vim.visualBlock = !!actionArgs.blockwise\n CodeMirror.signal(cm, 'vim-mode-change', {\n mode: 'visual',\n subMode: vim.visualLine\n ? 'linewise'\n : vim.visualBlock\n ? 'blockwise'\n : ''\n })\n updateCmSelection(cm)\n } else {\n exitVisualMode(cm)\n }\n },\n reselectLastSelection: function (cm, _actionArgs, vim) {\n var lastSelection = vim.lastSelection\n if (vim.visualMode) {\n updateLastSelection(cm, vim)\n }\n if (lastSelection) {\n var anchor = lastSelection.anchorMark.find()\n var head = lastSelection.headMark.find()\n if (!anchor || !head) {\n // If the marks have been destroyed due to edits, do nothing.\n return\n }\n vim.sel = {\n anchor: anchor,\n head: head\n }\n vim.visualMode = true\n vim.visualLine = lastSelection.visualLine\n vim.visualBlock = lastSelection.visualBlock\n updateCmSelection(cm)\n updateMark(cm, vim, '<', cursorMin(anchor, head))\n updateMark(cm, vim, '>', cursorMax(anchor, head))\n CodeMirror.signal(cm, 'vim-mode-change', {\n mode: 'visual',\n subMode: vim.visualLine\n ? 'linewise'\n : vim.visualBlock\n ? 'blockwise'\n : ''\n })\n }\n },\n joinLines: function (cm, actionArgs, vim) {\n var curStart, curEnd\n if (vim.visualMode) {\n curStart = cm.getCursor('anchor')\n curEnd = cm.getCursor('head')\n if (cursorIsBefore(curEnd, curStart)) {\n var tmp = curEnd\n curEnd = curStart\n curStart = tmp\n }\n curEnd.ch = lineLength(cm, curEnd.line) - 1\n } else {\n // Repeat is the number of lines to join. Minimum 2 lines.\n var repeat = Math.max(actionArgs.repeat, 2)\n curStart = cm.getCursor()\n curEnd = clipCursorToContent(\n cm,\n Pos(curStart.line + repeat - 1, Infinity)\n )\n }\n var finalCh = 0\n for (var i = curStart.line; i < curEnd.line; i++) {\n finalCh = lineLength(cm, curStart.line)\n var tmp = Pos(curStart.line + 1, lineLength(cm, curStart.line + 1))\n var text = cm.getRange(curStart, tmp)\n text = text.replace(/\\n\\s*/g, ' ')\n cm.replaceRange(text, curStart, tmp)\n }\n var curFinalPos = Pos(curStart.line, finalCh)\n if (vim.visualMode) {\n exitVisualMode(cm, false)\n }\n cm.setCursor(curFinalPos)\n },\n newLineAndEnterInsertMode: function (cm, actionArgs, vim) {\n vim.insertMode = true\n var insertAt = copyCursor(cm.getCursor())\n if (insertAt.line === cm.firstLine() && !actionArgs.after) {\n // Special case for inserting newline before start of document.\n cm.replaceRange('\\n', Pos(cm.firstLine(), 0))\n cm.setCursor(cm.firstLine(), 0)\n } else {\n insertAt.line = actionArgs.after ? insertAt.line : insertAt.line - 1\n insertAt.ch = lineLength(cm, insertAt.line)\n cm.setCursor(insertAt)\n var newlineFn =\n CodeMirror.commands.newlineAndIndentContinueComment ||\n CodeMirror.commands.newlineAndIndent\n newlineFn(cm)\n }\n this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim)\n },\n paste: function (cm, actionArgs, vim) {\n var cur = copyCursor(cm.getCursor())\n var register = vimGlobalState.registerController.getRegister(\n actionArgs.registerName\n )\n var text = register.toString()\n if (!text) {\n return\n }\n if (actionArgs.matchIndent) {\n var tabSize = cm.getOption('tabSize')\n // length that considers tabs and tabSize\n var whitespaceLength = function (str) {\n var tabs = str.split('\\t').length - 1\n var spaces = str.split(' ').length - 1\n return tabs * tabSize + spaces * 1\n }\n var currentLine = cm.getLine(cm.getCursor().line)\n var indent = whitespaceLength(currentLine.match(/^\\s*/)[0])\n // chomp last newline b/c don't want it to match /^\\s*/gm\n var chompedText = text.replace(/\\n$/, '')\n var wasChomped = text !== chompedText\n var firstIndent = whitespaceLength(text.match(/^\\s*/)[0])\n var text = chompedText.replace(/^\\s*/gm, function (wspace) {\n var newIndent = indent + (whitespaceLength(wspace) - firstIndent)\n if (newIndent < 0) {\n return ''\n } else if (cm.getOption('indentWithTabs')) {\n var quotient = Math.floor(newIndent / tabSize)\n return Array(quotient + 1).join('\\t')\n } else {\n return Array(newIndent + 1).join(' ')\n }\n })\n text += wasChomped ? '\\n' : ''\n }\n if (actionArgs.repeat > 1) {\n var text = Array(actionArgs.repeat + 1).join(text)\n }\n var linewise = register.linewise\n var blockwise = register.blockwise\n if (linewise) {\n if (vim.visualMode) {\n text = vim.visualLine\n ? text.slice(0, -1)\n : '\\n' + text.slice(0, text.length - 1) + '\\n'\n } else if (actionArgs.after) {\n // Move the newline at the end to the start instead, and paste just\n // before the newline character of the line we are on right now.\n text = '\\n' + text.slice(0, text.length - 1)\n cur.ch = lineLength(cm, cur.line)\n } else {\n cur.ch = 0\n }\n } else {\n if (blockwise) {\n text = text.split('\\n')\n for (var i = 0; i < text.length; i++) {\n text[i] = text[i] == '' ? ' ' : text[i]\n }\n }\n cur.ch += actionArgs.after ? 1 : 0\n }\n var curPosFinal\n var idx\n if (vim.visualMode) {\n // save the pasted text for reselection if the need arises\n vim.lastPastedText = text\n var lastSelectionCurEnd\n var selectedArea = getSelectedAreaRange(cm, vim)\n var selectionStart = selectedArea[0]\n var selectionEnd = selectedArea[1]\n var selectedText = cm.getSelection()\n var selections = cm.listSelections()\n var emptyStrings = new Array(selections.length).join('1').split('1')\n // save the curEnd marker before it get cleared due to cm.replaceRange.\n if (vim.lastSelection) {\n lastSelectionCurEnd = vim.lastSelection.headMark.find()\n }\n // push the previously selected text to unnamed register\n vimGlobalState.registerController.unnamedRegister.setText(\n selectedText\n )\n if (blockwise) {\n // first delete the selected text\n cm.replaceSelections(emptyStrings)\n // Set new selections as per the block length of the yanked text\n selectionEnd = Pos(\n selectionStart.line + text.length - 1,\n selectionStart.ch\n )\n cm.setCursor(selectionStart)\n selectBlock(cm, selectionEnd)\n cm.replaceSelections(text)\n curPosFinal = selectionStart\n } else if (vim.visualBlock) {\n cm.replaceSelections(emptyStrings)\n cm.setCursor(selectionStart)\n cm.replaceRange(text, selectionStart, selectionStart)\n curPosFinal = selectionStart\n } else {\n cm.replaceRange(text, selectionStart, selectionEnd)\n curPosFinal = cm.posFromIndex(\n cm.indexFromPos(selectionStart) + text.length - 1\n )\n }\n // restore the the curEnd marker\n if (lastSelectionCurEnd) {\n vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd)\n }\n if (linewise) {\n curPosFinal.ch = 0\n }\n } else {\n if (blockwise) {\n cm.setCursor(cur)\n for (var i = 0; i < text.length; i++) {\n var line = cur.line + i\n if (line > cm.lastLine()) {\n cm.replaceRange('\\n', Pos(line, 0))\n }\n var lastCh = lineLength(cm, line)\n if (lastCh < cur.ch) {\n extendLineToColumn(cm, line, cur.ch)\n }\n }\n cm.setCursor(cur)\n selectBlock(cm, Pos(cur.line + text.length - 1, cur.ch))\n cm.replaceSelections(text)\n curPosFinal = cur\n } else {\n cm.replaceRange(text, cur)\n // Now fine tune the cursor to where we want it.\n if (linewise && actionArgs.after) {\n curPosFinal = Pos(\n cur.line + 1,\n findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1))\n )\n } else if (linewise && !actionArgs.after) {\n curPosFinal = Pos(\n cur.line,\n findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line))\n )\n } else if (!linewise && actionArgs.after) {\n idx = cm.indexFromPos(cur)\n curPosFinal = cm.posFromIndex(idx + text.length - 1)\n } else {\n idx = cm.indexFromPos(cur)\n curPosFinal = cm.posFromIndex(idx + text.length)\n }\n }\n }\n if (vim.visualMode) {\n exitVisualMode(cm, false)\n }\n cm.setCursor(curPosFinal)\n },\n undo: function (cm, actionArgs) {\n cm.operation(function () {\n repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)()\n cm.setCursor(cm.getCursor('anchor'))\n })\n },\n redo: function (cm, actionArgs) {\n repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)()\n },\n setRegister: function (_cm, actionArgs, vim) {\n vim.inputState.registerName = actionArgs.selectedCharacter\n },\n setMark: function (cm, actionArgs, vim) {\n var markName = actionArgs.selectedCharacter\n updateMark(cm, vim, markName, cm.getCursor())\n },\n replace: function (cm, actionArgs, vim) {\n var replaceWith = actionArgs.selectedCharacter\n var curStart = cm.getCursor()\n var replaceTo\n var curEnd\n var selections = cm.listSelections()\n if (vim.visualMode) {\n curStart = cm.getCursor('start')\n curEnd = cm.getCursor('end')\n } else {\n var line = cm.getLine(curStart.line)\n replaceTo = curStart.ch + actionArgs.repeat\n if (replaceTo > line.length) {\n replaceTo = line.length\n }\n curEnd = Pos(curStart.line, replaceTo)\n }\n if (replaceWith == '\\n') {\n if (!vim.visualMode)\n cm.replaceRange('', curStart, curEnd)\n // special case, where vim help says to replace by just one line-break\n ;(\n CodeMirror.commands.newlineAndIndentContinueComment ||\n CodeMirror.commands.newlineAndIndent\n )(cm)\n } else {\n var replaceWithStr = cm.getRange(curStart, curEnd)\n // replace all characters in range by selected, but keep linebreaks\n replaceWithStr = replaceWithStr.replace(/[^\\n]/g, replaceWith)\n if (vim.visualBlock) {\n // Tabs are split in visua block before replacing\n var spaces = new Array(cm.getOption('tabSize') + 1).join(' ')\n replaceWithStr = cm.getSelection()\n replaceWithStr = replaceWithStr\n .replace(/\\t/g, spaces)\n .replace(/[^\\n]/g, replaceWith)\n .split('\\n')\n cm.replaceSelections(replaceWithStr)\n } else {\n cm.replaceRange(replaceWithStr, curStart, curEnd)\n }\n if (vim.visualMode) {\n curStart = cursorIsBefore(selections[0].anchor, selections[0].head)\n ? selections[0].anchor\n : selections[0].head\n cm.setCursor(curStart)\n exitVisualMode(cm, false)\n } else {\n cm.setCursor(offsetCursor(curEnd, 0, -1))\n }\n }\n },\n incrementNumberToken: function (cm, actionArgs) {\n var cur = cm.getCursor()\n var lineStr = cm.getLine(cur.line)\n var re = /-?\\d+/g\n var match\n var start\n var end\n var numberStr\n var token\n while ((match = re.exec(lineStr)) !== null) {\n token = match[0]\n start = match.index\n end = start + token.length\n if (cur.ch < end) break\n }\n if (!actionArgs.backtrack && end <= cur.ch) return\n if (token) {\n var increment = actionArgs.increase ? 1 : -1\n var number = parseInt(token) + increment * actionArgs.repeat\n var from = Pos(cur.line, start)\n var to = Pos(cur.line, end)\n numberStr = number.toString()\n cm.replaceRange(numberStr, from, to)\n } else {\n return\n }\n cm.setCursor(Pos(cur.line, start + numberStr.length - 1))\n },\n repeatLastEdit: function (cm, actionArgs, vim) {\n var lastEditInputState = vim.lastEditInputState\n if (!lastEditInputState) {\n return\n }\n var repeat = actionArgs.repeat\n if (repeat && actionArgs.repeatIsExplicit) {\n vim.lastEditInputState.repeatOverride = repeat\n } else {\n repeat = vim.lastEditInputState.repeatOverride || repeat\n }\n repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */)\n },\n indent: function (cm, actionArgs) {\n cm.indentLine(cm.getCursor().line, actionArgs.indentRight)\n },\n exitInsertMode: exitInsertMode\n }\n\n function defineAction(name, fn) {\n actions[name] = fn\n }\n\n /*\n * Below are miscellaneous utility functions used by vim.js\n */\n\n /**\n * Clips cursor to ensure that line is within the buffer's range\n * If includeLineBreak is true, then allow cur.ch == lineLength.\n */\n function clipCursorToContent(cm, cur, includeLineBreak) {\n var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine())\n var maxCh = lineLength(cm, line) - 1\n maxCh = includeLineBreak ? maxCh + 1 : maxCh\n var ch = Math.min(Math.max(0, cur.ch), maxCh)\n return Pos(line, ch)\n }\n function copyArgs(args) {\n var ret = {}\n for (var prop in args) {\n if (args.hasOwnProperty(prop)) {\n ret[prop] = args[prop]\n }\n }\n return ret\n }\n function offsetCursor(cur, offsetLine, offsetCh) {\n if (typeof offsetLine === 'object') {\n offsetCh = offsetLine.ch\n offsetLine = offsetLine.line\n }\n return Pos(cur.line + offsetLine, cur.ch + offsetCh)\n }\n function getOffset(anchor, head) {\n return {\n line: head.line - anchor.line,\n ch: head.line - anchor.line\n }\n }\n function commandMatches(keys, keyMap, context, inputState) {\n // Partial matches are not applied. They inform the key handler\n // that the current key sequence is a subsequence of a valid key\n // sequence, so that the key buffer is not cleared.\n var match,\n partial = [],\n full = []\n for (var i = 0; i < keyMap.length; i++) {\n var command = keyMap[i]\n if (\n (context == 'insert' && command.context != 'insert') ||\n (command.context && command.context != context) ||\n (inputState.operator && command.type == 'action') ||\n !(match = commandMatch(keys, command.keys))\n ) {\n continue\n }\n if (match == 'partial') {\n partial.push(command)\n }\n if (match == 'full') {\n full.push(command)\n }\n }\n return {\n partial: partial.length && partial,\n full: full.length && full\n }\n }\n function commandMatch(pressed, mapped) {\n if (mapped.slice(-11) == '') {\n // Last character matches anything.\n var prefixLen = mapped.length - 11\n var pressedPrefix = pressed.slice(0, prefixLen)\n var mappedPrefix = mapped.slice(0, prefixLen)\n return pressedPrefix == mappedPrefix && pressed.length > prefixLen\n ? 'full'\n : mappedPrefix.indexOf(pressedPrefix) == 0\n ? 'partial'\n : false\n } else {\n return pressed == mapped\n ? 'full'\n : mapped.indexOf(pressed) == 0\n ? 'partial'\n : false\n }\n }\n function lastChar(keys) {\n var match = /^.*(<[^>]+>)$/.exec(keys)\n var selectedCharacter = match ? match[1] : keys.slice(-1)\n if (selectedCharacter.length > 1) {\n switch (selectedCharacter) {\n case '':\n selectedCharacter = '\\n'\n break\n case '':\n selectedCharacter = ' '\n break\n default:\n selectedCharacter = ''\n break\n }\n }\n return selectedCharacter\n }\n function repeatFn(cm, fn, repeat) {\n return function () {\n for (var i = 0; i < repeat; i++) {\n fn(cm)\n }\n }\n }\n function copyCursor(cur) {\n return Pos(cur.line, cur.ch)\n }\n function cursorEqual(cur1, cur2) {\n return cur1.ch == cur2.ch && cur1.line == cur2.line\n }\n function cursorIsBefore(cur1, cur2) {\n if (cur1.line < cur2.line) {\n return true\n }\n if (cur1.line == cur2.line && cur1.ch < cur2.ch) {\n return true\n }\n return false\n }\n function cursorMin(cur1, cur2) {\n if (arguments.length > 2) {\n cur2 = cursorMin.apply(\n undefined,\n Array.prototype.slice.call(arguments, 1)\n )\n }\n return cursorIsBefore(cur1, cur2) ? cur1 : cur2\n }\n function cursorMax(cur1, cur2) {\n if (arguments.length > 2) {\n cur2 = cursorMax.apply(\n undefined,\n Array.prototype.slice.call(arguments, 1)\n )\n }\n return cursorIsBefore(cur1, cur2) ? cur2 : cur1\n }\n function cursorIsBetween(cur1, cur2, cur3) {\n // returns true if cur2 is between cur1 and cur3.\n var cur1before2 = cursorIsBefore(cur1, cur2)\n var cur2before3 = cursorIsBefore(cur2, cur3)\n return cur1before2 && cur2before3\n }\n function lineLength(cm, lineNum) {\n return cm.getLine(lineNum).length\n }\n function trim(s) {\n if (s.trim) {\n return s.trim()\n }\n return s.replace(/^\\s+|\\s+$/g, '')\n }\n function escapeRegex(s) {\n return s.replace(/([.?*+$\\[\\]\\/\\\\(){}|\\-])/g, '\\\\$1')\n }\n function extendLineToColumn(cm, lineNum, column) {\n var endCh = lineLength(cm, lineNum)\n var spaces = new Array(column - endCh + 1).join(' ')\n cm.setCursor(Pos(lineNum, endCh))\n cm.replaceRange(spaces, cm.getCursor())\n }\n // This functions selects a rectangular block\n // of text with selectionEnd as any of its corner\n // Height of block:\n // Difference in selectionEnd.line and first/last selection.line\n // Width of the block:\n // Distance between selectionEnd.ch and any(first considered here) selection.ch\n function selectBlock(cm, selectionEnd) {\n var selections = [],\n ranges = cm.listSelections()\n var head = copyCursor(cm.clipPos(selectionEnd))\n var isClipped = !cursorEqual(selectionEnd, head)\n var curHead = cm.getCursor('head')\n var primIndex = getIndex(ranges, curHead)\n var wasClipped = cursorEqual(\n ranges[primIndex].head,\n ranges[primIndex].anchor\n )\n var max = ranges.length - 1\n var index = max - primIndex > primIndex ? max : 0\n var base = ranges[index].anchor\n\n var firstLine = Math.min(base.line, head.line)\n var lastLine = Math.max(base.line, head.line)\n var baseCh = base.ch,\n headCh = head.ch\n\n var dir = ranges[index].head.ch - baseCh\n var newDir = headCh - baseCh\n if (dir > 0 && newDir <= 0) {\n baseCh++\n if (!isClipped) {\n headCh--\n }\n } else if (dir < 0 && newDir >= 0) {\n baseCh--\n if (!wasClipped) {\n headCh++\n }\n } else if (dir < 0 && newDir == -1) {\n baseCh--\n headCh++\n }\n for (var line = firstLine; line <= lastLine; line++) {\n var range = {\n anchor: new Pos(line, baseCh),\n head: new Pos(line, headCh)\n }\n selections.push(range)\n }\n cm.setSelections(selections)\n selectionEnd.ch = headCh\n base.ch = baseCh\n return base\n }\n function selectForInsert(cm, head, height) {\n var sel = []\n for (var i = 0; i < height; i++) {\n var lineHead = offsetCursor(head, i, 0)\n sel.push({ anchor: lineHead, head: lineHead })\n }\n cm.setSelections(sel, 0)\n }\n // getIndex returns the index of the cursor in the selections.\n function getIndex(ranges, cursor, end) {\n for (var i = 0; i < ranges.length; i++) {\n var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor)\n var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor)\n if (atAnchor || atHead) {\n return i\n }\n }\n return -1\n }\n function getSelectedAreaRange(cm, vim) {\n var lastSelection = vim.lastSelection\n var getCurrentSelectedAreaRange = function () {\n var selections = cm.listSelections()\n var start = selections[0]\n var end = selections[selections.length - 1]\n var selectionStart = cursorIsBefore(start.anchor, start.head)\n ? start.anchor\n : start.head\n var selectionEnd = cursorIsBefore(end.anchor, end.head)\n ? end.head\n : end.anchor\n return [selectionStart, selectionEnd]\n }\n var getLastSelectedAreaRange = function () {\n var selectionStart = cm.getCursor()\n var selectionEnd = cm.getCursor()\n var block = lastSelection.visualBlock\n if (block) {\n var width = block.width\n var height = block.height\n selectionEnd = Pos(\n selectionStart.line + height,\n selectionStart.ch + width\n )\n var selections = []\n // selectBlock creates a 'proper' rectangular block.\n // We do not want that in all cases, so we manually set selections.\n for (var i = selectionStart.line; i < selectionEnd.line; i++) {\n var anchor = Pos(i, selectionStart.ch)\n var head = Pos(i, selectionEnd.ch)\n var range = { anchor: anchor, head: head }\n selections.push(range)\n }\n cm.setSelections(selections)\n } else {\n var start = lastSelection.anchorMark.find()\n var end = lastSelection.headMark.find()\n var line = end.line - start.line\n var ch = end.ch - start.ch\n selectionEnd = {\n line: selectionEnd.line + line,\n ch: line ? selectionEnd.ch : ch + selectionEnd.ch\n }\n if (lastSelection.visualLine) {\n selectionStart = Pos(selectionStart.line, 0)\n selectionEnd = Pos(\n selectionEnd.line,\n lineLength(cm, selectionEnd.line)\n )\n }\n cm.setSelection(selectionStart, selectionEnd)\n }\n return [selectionStart, selectionEnd]\n }\n if (!vim.visualMode) {\n // In case of replaying the action.\n return getLastSelectedAreaRange()\n } else {\n return getCurrentSelectedAreaRange()\n }\n }\n // Updates the previous selection with the current selection's values. This\n // should only be called in visual mode.\n function updateLastSelection(cm, vim) {\n var anchor = vim.sel.anchor\n var head = vim.sel.head\n // To accommodate the effect of lastPastedText in the last selection\n if (vim.lastPastedText) {\n head = cm.posFromIndex(\n cm.indexFromPos(anchor) + vim.lastPastedText.length\n )\n vim.lastPastedText = null\n }\n vim.lastSelection = {\n anchorMark: cm.setBookmark(anchor),\n headMark: cm.setBookmark(head),\n anchor: copyCursor(anchor),\n head: copyCursor(head),\n visualMode: vim.visualMode,\n visualLine: vim.visualLine,\n visualBlock: vim.visualBlock\n }\n }\n function expandSelection(cm, start, end) {\n var sel = cm.state.vim.sel\n var head = sel.head\n var anchor = sel.anchor\n var tmp\n if (cursorIsBefore(end, start)) {\n tmp = end\n end = start\n start = tmp\n }\n if (cursorIsBefore(head, anchor)) {\n head = cursorMin(start, head)\n anchor = cursorMax(anchor, end)\n } else {\n anchor = cursorMin(start, anchor)\n head = cursorMax(head, end)\n head = offsetCursor(head, 0, -1)\n if (head.ch == -1 && head.line != cm.firstLine()) {\n head = Pos(head.line - 1, lineLength(cm, head.line - 1))\n }\n }\n return [anchor, head]\n }\n /**\n * Updates the CodeMirror selection to match the provided vim selection.\n * If no arguments are given, it uses the current vim selection state.\n */\n function updateCmSelection(cm, sel, mode) {\n var vim = cm.state.vim\n sel = sel || vim.sel\n var mode =\n mode || vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char'\n var cmSel = makeCmSelection(cm, sel, mode)\n cm.setSelections(cmSel.ranges, cmSel.primary)\n updateFakeCursor(cm)\n }\n function makeCmSelection(cm, sel, mode, exclusive) {\n var head = copyCursor(sel.head)\n var anchor = copyCursor(sel.anchor)\n if (mode == 'char') {\n var headOffset =\n !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0\n var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0\n head = offsetCursor(sel.head, 0, headOffset)\n anchor = offsetCursor(sel.anchor, 0, anchorOffset)\n return {\n ranges: [{ anchor: anchor, head: head }],\n primary: 0\n }\n } else if (mode == 'line') {\n if (!cursorIsBefore(sel.head, sel.anchor)) {\n anchor.ch = 0\n\n var lastLine = cm.lastLine()\n if (head.line > lastLine) {\n head.line = lastLine\n }\n head.ch = lineLength(cm, head.line)\n } else {\n head.ch = 0\n anchor.ch = lineLength(cm, anchor.line)\n }\n return {\n ranges: [{ anchor: anchor, head: head }],\n primary: 0\n }\n } else if (mode == 'block') {\n var top = Math.min(anchor.line, head.line),\n left = Math.min(anchor.ch, head.ch),\n bottom = Math.max(anchor.line, head.line),\n right = Math.max(anchor.ch, head.ch) + 1\n var height = bottom - top + 1\n var primary = head.line == top ? 0 : height - 1\n var ranges = []\n for (var i = 0; i < height; i++) {\n ranges.push({\n anchor: Pos(top + i, left),\n head: Pos(top + i, right)\n })\n }\n return {\n ranges: ranges,\n primary: primary\n }\n }\n }\n function getHead(cm) {\n var cur = cm.getCursor('head')\n if (cm.getSelection().length == 1) {\n // Small corner case when only 1 character is selected. The \"real\"\n // head is the left of head and anchor.\n cur = cursorMin(cur, cm.getCursor('anchor'))\n }\n return cur\n }\n\n /**\n * If moveHead is set to false, the CodeMirror selection will not be\n * touched. The caller assumes the responsibility of putting the cursor\n * in the right place.\n */\n function exitVisualMode(cm, moveHead) {\n var vim = cm.state.vim\n if (moveHead !== false) {\n cm.setCursor(clipCursorToContent(cm, vim.sel.head))\n }\n updateLastSelection(cm, vim)\n vim.visualMode = false\n vim.visualLine = false\n vim.visualBlock = false\n CodeMirror.signal(cm, 'vim-mode-change', { mode: 'normal' })\n if (vim.fakeCursor) {\n vim.fakeCursor.clear()\n }\n }\n\n // Remove any trailing newlines from the selection. For\n // example, with the caret at the start of the last word on the line,\n // 'dw' should word, but not the newline, while 'w' should advance the\n // caret to the first character of the next line.\n function clipToLine(cm, curStart, curEnd) {\n var selection = cm.getRange(curStart, curEnd)\n // Only clip if the selection ends with trailing newline + whitespace\n if (/\\n\\s*$/.test(selection)) {\n var lines = selection.split('\\n')\n // We know this is all whitespace.\n lines.pop()\n\n // Cases:\n // 1. Last word is an empty line - do not clip the trailing '\\n'\n // 2. Last word is not an empty line - clip the trailing '\\n'\n var line\n // Find the line containing the last word, and clip all whitespace up\n // to it.\n for (\n var line = lines.pop();\n lines.length > 0 && line && isWhiteSpaceString(line);\n line = lines.pop()\n ) {\n curEnd.line--\n curEnd.ch = 0\n }\n // If the last word is not an empty line, clip an additional newline\n if (line) {\n curEnd.line--\n curEnd.ch = lineLength(cm, curEnd.line)\n } else {\n curEnd.ch = 0\n }\n }\n }\n\n // Expand the selection to line ends.\n function expandSelectionToLine(_cm, curStart, curEnd) {\n curStart.ch = 0\n curEnd.ch = 0\n curEnd.line++\n }\n\n function findFirstNonWhiteSpaceCharacter(text) {\n if (!text) {\n return 0\n }\n var firstNonWS = text.search(/\\S/)\n return firstNonWS == -1 ? text.length : firstNonWS\n }\n\n function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) {\n var cur = getHead(cm)\n var line = cm.getLine(cur.line)\n var idx = cur.ch\n\n // Seek to first word or non-whitespace character, depending on if\n // noSymbol is true.\n var test = noSymbol ? wordCharTest[0] : bigWordCharTest[0]\n while (!test(line.charAt(idx))) {\n idx++\n if (idx >= line.length) {\n return null\n }\n }\n\n if (bigWord) {\n test = bigWordCharTest[0]\n } else {\n test = wordCharTest[0]\n if (!test(line.charAt(idx))) {\n test = wordCharTest[1]\n }\n }\n\n var end = idx,\n start = idx\n while (test(line.charAt(end)) && end < line.length) {\n end++\n }\n while (test(line.charAt(start)) && start >= 0) {\n start--\n }\n start++\n\n if (inclusive) {\n // If present, include all whitespace after word.\n // Otherwise, include all whitespace before word, except indentation.\n var wordEnd = end\n while (/\\s/.test(line.charAt(end)) && end < line.length) {\n end++\n }\n if (wordEnd == end) {\n var wordStart = start\n while (/\\s/.test(line.charAt(start - 1)) && start > 0) {\n start--\n }\n if (!start) {\n start = wordStart\n }\n }\n }\n return { start: Pos(cur.line, start), end: Pos(cur.line, end) }\n }\n\n function recordJumpPosition(cm, oldCur, newCur) {\n if (!cursorEqual(oldCur, newCur)) {\n vimGlobalState.jumpList.add(cm, oldCur, newCur)\n }\n }\n\n function recordLastCharacterSearch(increment, args) {\n vimGlobalState.lastCharacterSearch.increment = increment\n vimGlobalState.lastCharacterSearch.forward = args.forward\n vimGlobalState.lastCharacterSearch.selectedCharacter =\n args.selectedCharacter\n }\n\n var symbolToMode = {\n '(': 'bracket',\n ')': 'bracket',\n '{': 'bracket',\n '}': 'bracket',\n '[': 'section',\n ']': 'section',\n '*': 'comment',\n '/': 'comment',\n m: 'method',\n M: 'method',\n '#': 'preprocess'\n }\n var findSymbolModes = {\n bracket: {\n isComplete: function (state) {\n if (state.nextCh === state.symb) {\n state.depth++\n if (state.depth >= 1) return true\n } else if (state.nextCh === state.reverseSymb) {\n state.depth--\n }\n return false\n }\n },\n section: {\n init: function (state) {\n state.curMoveThrough = true\n state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}'\n },\n isComplete: function (state) {\n return state.index === 0 && state.nextCh === state.symb\n }\n },\n comment: {\n isComplete: function (state) {\n var found = state.lastCh === '*' && state.nextCh === '/'\n state.lastCh = state.nextCh\n return found\n }\n },\n // TODO: The original Vim implementation only operates on level 1 and 2.\n // The current implementation doesn't check for code block level and\n // therefore it operates on any levels.\n method: {\n init: function (state) {\n state.symb = state.symb === 'm' ? '{' : '}'\n state.reverseSymb = state.symb === '{' ? '}' : '{'\n },\n isComplete: function (state) {\n if (state.nextCh === state.symb) return true\n return false\n }\n },\n preprocess: {\n init: function (state) {\n state.index = 0\n },\n isComplete: function (state) {\n if (state.nextCh === '#') {\n var token = state.lineText.match(/#(\\w+)/)[1]\n if (token === 'endif') {\n if (state.forward && state.depth === 0) {\n return true\n }\n state.depth++\n } else if (token === 'if') {\n if (!state.forward && state.depth === 0) {\n return true\n }\n state.depth--\n }\n if (token === 'else' && state.depth === 0) return true\n }\n return false\n }\n }\n }\n function findSymbol(cm, repeat, forward, symb) {\n var cur = copyCursor(cm.getCursor())\n var increment = forward ? 1 : -1\n var endLine = forward ? cm.lineCount() : -1\n var curCh = cur.ch\n var line = cur.line\n var lineText = cm.getLine(line)\n var state = {\n lineText: lineText,\n nextCh: lineText.charAt(curCh),\n lastCh: null,\n index: curCh,\n symb: symb,\n reverseSymb: (forward\n ? { ')': '(', '}': '{' }\n : { '(': ')', '{': '}' })[symb],\n forward: forward,\n depth: 0,\n curMoveThrough: false\n }\n var mode = symbolToMode[symb]\n if (!mode) return cur\n var init = findSymbolModes[mode].init\n var isComplete = findSymbolModes[mode].isComplete\n if (init) {\n init(state)\n }\n while (line !== endLine && repeat) {\n state.index += increment\n state.nextCh = state.lineText.charAt(state.index)\n if (!state.nextCh) {\n line += increment\n state.lineText = cm.getLine(line) || ''\n if (increment > 0) {\n state.index = 0\n } else {\n var lineLen = state.lineText.length\n state.index = lineLen > 0 ? lineLen - 1 : 0\n }\n state.nextCh = state.lineText.charAt(state.index)\n }\n if (isComplete(state)) {\n cur.line = line\n cur.ch = state.index\n repeat--\n }\n }\n if (state.nextCh || state.curMoveThrough) {\n return Pos(line, state.index)\n }\n return cur\n }\n\n /**\n * Returns the boundaries of the next word. If the cursor in the middle of\n * the word, then returns the boundaries of the current word, starting at\n * the cursor. If the cursor is at the start/end of a word, and we are going\n * forward/backward, respectively, find the boundaries of the next word.\n *\n * @param {CodeMirror} cm CodeMirror object.\n * @param {Cursor} cur The cursor position.\n * @param {boolean} forward True to search forward. False to search\n * backward.\n * @param {boolean} bigWord True if punctuation count as part of the word.\n * False if only [a-zA-Z0-9] characters count as part of the word.\n * @param {boolean} emptyLineIsWord True if empty lines should be treated\n * as words.\n * @return {Object{from:number, to:number, line: number}} The boundaries of\n * the word, or null if there are no more words.\n */\n function findWord(cm, cur, forward, bigWord, emptyLineIsWord) {\n var lineNum = cur.line\n var pos = cur.ch\n var line = cm.getLine(lineNum)\n var dir = forward ? 1 : -1\n var charTests = bigWord ? bigWordCharTest : wordCharTest\n\n if (emptyLineIsWord && line == '') {\n lineNum += dir\n line = cm.getLine(lineNum)\n if (!isLine(cm, lineNum)) {\n return null\n }\n pos = forward ? 0 : line.length\n }\n\n while (true) {\n if (emptyLineIsWord && line == '') {\n return { from: 0, to: 0, line: lineNum }\n }\n var stop = dir > 0 ? line.length : -1\n var wordStart = stop,\n wordEnd = stop\n // Find bounds of next word.\n while (pos != stop) {\n var foundWord = false\n for (var i = 0; i < charTests.length && !foundWord; ++i) {\n if (charTests[i](line.charAt(pos))) {\n wordStart = pos\n // Advance to end of word.\n while (pos != stop && charTests[i](line.charAt(pos))) {\n pos += dir\n }\n wordEnd = pos\n foundWord = wordStart != wordEnd\n if (\n wordStart == cur.ch &&\n lineNum == cur.line &&\n wordEnd == wordStart + dir\n ) {\n // We started at the end of a word. Find the next one.\n continue\n } else {\n return {\n from: Math.min(wordStart, wordEnd + 1),\n to: Math.max(wordStart, wordEnd),\n line: lineNum\n }\n }\n }\n }\n if (!foundWord) {\n pos += dir\n }\n }\n // Advance to next/prev line.\n lineNum += dir\n if (!isLine(cm, lineNum)) {\n return null\n }\n line = cm.getLine(lineNum)\n pos = dir > 0 ? 0 : line.length\n }\n }\n\n /**\n * @param {CodeMirror} cm CodeMirror object.\n * @param {Pos} cur The position to start from.\n * @param {int} repeat Number of words to move past.\n * @param {boolean} forward True to search forward. False to search\n * backward.\n * @param {boolean} wordEnd True to move to end of word. False to move to\n * beginning of word.\n * @param {boolean} bigWord True if punctuation count as part of the word.\n * False if only alphabet characters count as part of the word.\n * @return {Cursor} The position the cursor should move to.\n */\n function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) {\n var curStart = copyCursor(cur)\n var words = []\n if ((forward && !wordEnd) || (!forward && wordEnd)) {\n repeat++\n }\n // For 'e', empty lines are not considered words, go figure.\n var emptyLineIsWord = !(forward && wordEnd)\n for (var i = 0; i < repeat; i++) {\n var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord)\n if (!word) {\n var eodCh = lineLength(cm, cm.lastLine())\n words.push(\n forward\n ? { line: cm.lastLine(), from: eodCh, to: eodCh }\n : { line: 0, from: 0, to: 0 }\n )\n break\n }\n words.push(word)\n cur = Pos(word.line, forward ? word.to - 1 : word.from)\n }\n var shortCircuit = words.length != repeat\n var firstWord = words[0]\n var lastWord = words.pop()\n if (forward && !wordEnd) {\n // w\n if (\n !shortCircuit &&\n (firstWord.from != curStart.ch || firstWord.line != curStart.line)\n ) {\n // We did not start in the middle of a word. Discard the extra word at the end.\n lastWord = words.pop()\n }\n return Pos(lastWord.line, lastWord.from)\n } else if (forward && wordEnd) {\n return Pos(lastWord.line, lastWord.to - 1)\n } else if (!forward && wordEnd) {\n // ge\n if (\n !shortCircuit &&\n (firstWord.to != curStart.ch || firstWord.line != curStart.line)\n ) {\n // We did not start in the middle of a word. Discard the extra word at the end.\n lastWord = words.pop()\n }\n return Pos(lastWord.line, lastWord.to)\n } else {\n // b\n return Pos(lastWord.line, lastWord.from)\n }\n }\n\n function moveToCharacter(cm, repeat, forward, character) {\n var cur = cm.getCursor()\n var start = cur.ch\n var idx\n for (var i = 0; i < repeat; i++) {\n var line = cm.getLine(cur.line)\n idx = charIdxInLine(start, line, character, forward, true)\n if (idx == -1) {\n return null\n }\n start = idx\n }\n return Pos(cm.getCursor().line, idx)\n }\n\n function moveToColumn(cm, repeat) {\n // repeat is always >= 1, so repeat - 1 always corresponds\n // to the column we want to go to.\n var line = cm.getCursor().line\n return clipCursorToContent(cm, Pos(line, repeat - 1))\n }\n\n function updateMark(cm, vim, markName, pos) {\n if (!inArray(markName, validMarks)) {\n return\n }\n if (vim.marks[markName]) {\n vim.marks[markName].clear()\n }\n vim.marks[markName] = cm.setBookmark(pos)\n }\n\n function charIdxInLine(start, line, character, forward, includeChar) {\n // Search for char in line.\n // motion_options: {forward, includeChar}\n // If includeChar = true, include it too.\n // If forward = true, search forward, else search backwards.\n // If char is not found on this line, do nothing\n var idx\n if (forward) {\n idx = line.indexOf(character, start + 1)\n if (idx != -1 && !includeChar) {\n idx -= 1\n }\n } else {\n idx = line.lastIndexOf(character, start - 1)\n if (idx != -1 && !includeChar) {\n idx += 1\n }\n }\n return idx\n }\n\n function findParagraph(cm, head, repeat, dir, inclusive) {\n var line = head.line\n var min = cm.firstLine()\n var max = cm.lastLine()\n var start,\n end,\n i = line\n function isEmpty(i) {\n return !cm.getLine(i)\n }\n function isBoundary(i, dir, any) {\n if (any) {\n return isEmpty(i) != isEmpty(i + dir)\n }\n return !isEmpty(i) && isEmpty(i + dir)\n }\n if (dir) {\n while (min <= i && i <= max && repeat > 0) {\n if (isBoundary(i, dir)) {\n repeat--\n }\n i += dir\n }\n return new Pos(i, 0)\n }\n\n var vim = cm.state.vim\n if (vim.visualLine && isBoundary(line, 1, true)) {\n var anchor = vim.sel.anchor\n if (isBoundary(anchor.line, -1, true)) {\n if (!inclusive || anchor.line != line) {\n line += 1\n }\n }\n }\n var startState = isEmpty(line)\n for (i = line; i <= max && repeat; i++) {\n if (isBoundary(i, 1, true)) {\n if (!inclusive || isEmpty(i) != startState) {\n repeat--\n }\n }\n }\n end = new Pos(i, 0)\n // select boundary before paragraph for the last one\n if (i > max && !startState) {\n startState = true\n } else {\n inclusive = false\n }\n for (i = line; i > min; i--) {\n if (!inclusive || isEmpty(i) == startState || i == line) {\n if (isBoundary(i, -1, true)) {\n break\n }\n }\n }\n start = new Pos(i, 0)\n return { start: start, end: end }\n }\n\n // TODO: perhaps this finagling of start and end positions belonds\n // in codemirror/replaceRange?\n function selectCompanionObject(cm, head, symb, inclusive) {\n var cur = head,\n start,\n end\n\n var bracketRegexp = {\n '(': /[()]/,\n ')': /[()]/,\n '[': /[[\\]]/,\n ']': /[[\\]]/,\n '{': /[{}]/,\n '}': /[{}]/\n }[symb]\n var openSym = {\n '(': '(',\n ')': '(',\n '[': '[',\n ']': '[',\n '{': '{',\n '}': '{'\n }[symb]\n var curChar = cm.getLine(cur.line).charAt(cur.ch)\n // Due to the behavior of scanForBracket, we need to add an offset if the\n // cursor is on a matching open bracket.\n var offset = curChar === openSym ? 1 : 0\n\n start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, undefined, {\n bracketRegex: bracketRegexp\n })\n end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, undefined, {\n bracketRegex: bracketRegexp\n })\n\n if (!start || !end) {\n return { start: cur, end: cur }\n }\n\n start = start.pos\n end = end.pos\n\n if (\n (start.line == end.line && start.ch > end.ch) ||\n start.line > end.line\n ) {\n var tmp = start\n start = end\n end = tmp\n }\n\n if (inclusive) {\n end.ch += 1\n } else {\n start.ch += 1\n }\n\n return { start: start, end: end }\n }\n\n // Takes in a symbol and a cursor and tries to simulate text objects that\n // have identical opening and closing symbols\n // TODO support across multiple lines\n function findBeginningAndEnd(cm, head, symb, inclusive) {\n var cur = copyCursor(head)\n var line = cm.getLine(cur.line)\n var chars = line.split('')\n var start, end, i, len\n var firstIndex = chars.indexOf(symb)\n\n // the decision tree is to always look backwards for the beginning first,\n // but if the cursor is in front of the first instance of the symb,\n // then move the cursor forward\n if (cur.ch < firstIndex) {\n cur.ch = firstIndex\n // Why is this line even here???\n // cm.setCursor(cur.line, firstIndex+1);\n }\n // otherwise if the cursor is currently on the closing symbol\n else if (firstIndex < cur.ch && chars[cur.ch] == symb) {\n end = cur.ch // assign end to the current cursor\n --cur.ch // make sure to look backwards\n }\n\n // if we're currently on the symbol, we've got a start\n if (chars[cur.ch] == symb && !end) {\n start = cur.ch + 1 // assign start to ahead of the cursor\n } else {\n // go backwards to find the start\n for (i = cur.ch; i > -1 && !start; i--) {\n if (chars[i] == symb) {\n start = i + 1\n }\n }\n }\n\n // look forwards for the end symbol\n if (start && !end) {\n for (i = start, len = chars.length; i < len && !end; i++) {\n if (chars[i] == symb) {\n end = i\n }\n }\n }\n\n // nothing found\n if (!start || !end) {\n return { start: cur, end: cur }\n }\n\n // include the symbols\n if (inclusive) {\n --start\n ++end\n }\n\n return {\n start: Pos(cur.line, start),\n end: Pos(cur.line, end)\n }\n }\n\n // Search functions\n defineOption('pcre', true, 'boolean')\n function SearchState() {}\n SearchState.prototype = {\n getQuery: function () {\n return vimGlobalState.query\n },\n setQuery: function (query) {\n vimGlobalState.query = query\n },\n getOverlay: function () {\n return this.searchOverlay\n },\n setOverlay: function (overlay) {\n this.searchOverlay = overlay\n },\n isReversed: function () {\n return vimGlobalState.isReversed\n },\n setReversed: function (reversed) {\n vimGlobalState.isReversed = reversed\n },\n getScrollbarAnnotate: function () {\n return this.annotate\n },\n setScrollbarAnnotate: function (annotate) {\n this.annotate = annotate\n }\n }\n function getSearchState(cm) {\n var vim = cm.state.vim\n return vim.searchState_ || (vim.searchState_ = new SearchState())\n }\n function dialog(cm, template, shortText, onClose, options) {\n if (cm.openDialog) {\n cm.openDialog(template, onClose, {\n bottom: true,\n value: options.value,\n onKeyDown: options.onKeyDown,\n onKeyUp: options.onKeyUp,\n selectValueOnOpen: false\n })\n } else {\n onClose(prompt(shortText, ''))\n }\n }\n function splitBySlash(argString) {\n var slashes = findUnescapedSlashes(argString) || []\n if (!slashes.length) return []\n var tokens = []\n // in case of strings like foo/bar\n if (slashes[0] !== 0) return\n for (var i = 0; i < slashes.length; i++) {\n if (typeof slashes[i] === 'number') {\n tokens.push(argString.substring(slashes[i] + 1, slashes[i + 1]))\n }\n }\n return tokens\n }\n\n function findUnescapedSlashes(str) {\n var escapeNextChar = false\n var slashes = []\n for (var i = 0; i < str.length; i++) {\n var c = str.charAt(i)\n if (!escapeNextChar && c == '/') {\n slashes.push(i)\n }\n escapeNextChar = !escapeNextChar && c == '\\\\'\n }\n return slashes\n }\n\n // Translates a search string from ex (vim) syntax into javascript form.\n function translateRegex(str) {\n // When these match, add a '\\' if unescaped or remove one if escaped.\n var specials = '|(){'\n // Remove, but never add, a '\\' for these.\n var unescape = '}'\n var escapeNextChar = false\n var out = []\n for (var i = -1; i < str.length; i++) {\n var c = str.charAt(i) || ''\n var n = str.charAt(i + 1) || ''\n var specialComesNext = n && specials.indexOf(n) != -1\n if (escapeNextChar) {\n if (c !== '\\\\' || !specialComesNext) {\n out.push(c)\n }\n escapeNextChar = false\n } else {\n if (c === '\\\\') {\n escapeNextChar = true\n // Treat the unescape list as special for removing, but not adding '\\'.\n if (n && unescape.indexOf(n) != -1) {\n specialComesNext = true\n }\n // Not passing this test means removing a '\\'.\n if (!specialComesNext || n === '\\\\') {\n out.push(c)\n }\n } else {\n out.push(c)\n if (specialComesNext && n !== '\\\\') {\n out.push('\\\\')\n }\n }\n }\n }\n return out.join('')\n }\n\n // Translates the replace part of a search and replace from ex (vim) syntax into\n // javascript form. Similar to translateRegex, but additionally fixes back references\n // (translates '\\[0..9]' to '$[0..9]') and follows different rules for escaping '$'.\n var charUnescapes = { '\\\\n': '\\n', '\\\\r': '\\r', '\\\\t': '\\t' }\n function translateRegexReplace(str) {\n var escapeNextChar = false\n var out = []\n for (var i = -1; i < str.length; i++) {\n var c = str.charAt(i) || ''\n var n = str.charAt(i + 1) || ''\n if (charUnescapes[c + n]) {\n out.push(charUnescapes[c + n])\n i++\n } else if (escapeNextChar) {\n // At any point in the loop, escapeNextChar is true if the previous\n // character was a '\\' and was not escaped.\n out.push(c)\n escapeNextChar = false\n } else {\n if (c === '\\\\') {\n escapeNextChar = true\n if (isNumber(n) || n === '$') {\n out.push('$')\n } else if (n !== '/' && n !== '\\\\') {\n out.push('\\\\')\n }\n } else {\n if (c === '$') {\n out.push('$')\n }\n out.push(c)\n if (n === '/') {\n out.push('\\\\')\n }\n }\n }\n }\n return out.join('')\n }\n\n // Unescape \\ and / in the replace part, for PCRE mode.\n var unescapes = {\n '\\\\/': '/',\n '\\\\\\\\': '\\\\',\n '\\\\n': '\\n',\n '\\\\r': '\\r',\n '\\\\t': '\\t'\n }\n function unescapeRegexReplace(str) {\n var stream = new CodeMirror.StringStream(str)\n var output = []\n while (!stream.eol()) {\n // Search for \\.\n while (stream.peek() && stream.peek() != '\\\\') {\n output.push(stream.next())\n }\n var matched = false\n for (var matcher in unescapes) {\n if (stream.match(matcher, true)) {\n matched = true\n output.push(unescapes[matcher])\n break\n }\n }\n if (!matched) {\n // Don't change anything\n output.push(stream.next())\n }\n }\n return output.join('')\n }\n\n /**\n * Extract the regular expression from the query and return a Regexp object.\n * Returns null if the query is blank.\n * If ignoreCase is passed in, the Regexp object will have the 'i' flag set.\n * If smartCase is passed in, and the query contains upper case letters,\n * then ignoreCase is overridden, and the 'i' flag will not be set.\n * If the query contains the /i in the flag part of the regular expression,\n * then both ignoreCase and smartCase are ignored, and 'i' will be passed\n * through to the Regex object.\n */\n function parseQuery(query, ignoreCase, smartCase) {\n // First update the last search register\n var lastSearchRegister =\n vimGlobalState.registerController.getRegister('/')\n lastSearchRegister.setText(query)\n // Check if the query is already a regex.\n if (query instanceof RegExp) {\n return query\n }\n // First try to extract regex + flags from the input. If no flags found,\n // extract just the regex. IE does not accept flags directly defined in\n // the regex string in the form /regex/flags\n var slashes = findUnescapedSlashes(query)\n var regexPart\n var forceIgnoreCase\n if (!slashes.length) {\n // Query looks like 'regexp'\n regexPart = query\n } else {\n // Query looks like 'regexp/...'\n regexPart = query.substring(0, slashes[0])\n var flagsPart = query.substring(slashes[0])\n forceIgnoreCase = flagsPart.indexOf('i') != -1\n }\n if (!regexPart) {\n return null\n }\n if (!getOption('pcre')) {\n regexPart = translateRegex(regexPart)\n }\n if (smartCase) {\n ignoreCase = /^[^A-Z]*$/.test(regexPart)\n }\n var regexp = new RegExp(\n regexPart,\n ignoreCase || forceIgnoreCase ? 'i' : undefined\n )\n return regexp\n }\n function showConfirm(cm, text) {\n if (cm.openNotification) {\n cm.openNotification('' + text + '', {\n bottom: true,\n duration: 5000\n })\n } else {\n alert(text)\n }\n }\n function makePrompt(prefix, desc) {\n var raw =\n '' +\n (prefix || '') +\n ''\n if (desc) {\n raw += ' ' + desc + ''\n }\n return raw\n }\n var searchPromptDesc = '(Javascript regexp)'\n function showPrompt(cm, options) {\n var shortText = (options.prefix || '') + ' ' + (options.desc || '')\n var prompt = makePrompt(options.prefix, options.desc)\n dialog(cm, prompt, shortText, options.onClose, options)\n }\n function regexEqual(r1, r2) {\n if (r1 instanceof RegExp && r2 instanceof RegExp) {\n var props = ['global', 'multiline', 'ignoreCase', 'source']\n for (var i = 0; i < props.length; i++) {\n var prop = props[i]\n if (r1[prop] !== r2[prop]) {\n return false\n }\n }\n return true\n }\n return false\n }\n // Returns true if the query is valid.\n function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) {\n if (!rawQuery) {\n return\n }\n var state = getSearchState(cm)\n var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase)\n if (!query) {\n return\n }\n highlightSearchMatches(cm, query)\n if (regexEqual(query, state.getQuery())) {\n return query\n }\n state.setQuery(query)\n return query\n }\n function searchOverlay(query) {\n if (query.source.charAt(0) == '^') {\n var matchSol = true\n }\n return {\n token: function (stream) {\n if (matchSol && !stream.sol()) {\n stream.skipToEnd()\n return\n }\n var match = stream.match(query, false)\n if (match) {\n if (match[0].length == 0) {\n // Matched empty string, skip to next.\n stream.next()\n return 'searching'\n }\n if (!stream.sol()) {\n // Backtrack 1 to match \\b\n stream.backUp(1)\n if (!query.exec(stream.next() + match[0])) {\n stream.next()\n return null\n }\n }\n stream.match(query)\n return 'searching'\n }\n while (!stream.eol()) {\n stream.next()\n if (stream.match(query, false)) break\n }\n },\n query: query\n }\n }\n function highlightSearchMatches(cm, query) {\n var searchState = getSearchState(cm)\n var overlay = searchState.getOverlay()\n if (!overlay || query != overlay.query) {\n if (overlay) {\n cm.removeOverlay(overlay)\n }\n overlay = searchOverlay(query)\n cm.addOverlay(overlay)\n if (cm.showMatchesOnScrollbar) {\n if (searchState.getScrollbarAnnotate()) {\n searchState.getScrollbarAnnotate().clear()\n }\n searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query))\n }\n searchState.setOverlay(overlay)\n }\n }\n function findNext(cm, prev, query, repeat) {\n if (repeat === undefined) {\n repeat = 1\n }\n return cm.operation(function () {\n var pos = cm.getCursor()\n var cursor = cm.getSearchCursor(query, pos)\n for (var i = 0; i < repeat; i++) {\n var found = cursor.find(prev)\n if (i == 0 && found && cursorEqual(cursor.from(), pos)) {\n found = cursor.find(prev)\n }\n if (!found) {\n // SearchCursor may have returned null because it hit EOF, wrap\n // around and try again.\n cursor = cm.getSearchCursor(\n query,\n prev ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0)\n )\n if (!cursor.find(prev)) {\n return\n }\n }\n }\n return cursor.from()\n })\n }\n function clearSearchHighlight(cm) {\n var state = getSearchState(cm)\n cm.removeOverlay(getSearchState(cm).getOverlay())\n state.setOverlay(null)\n if (state.getScrollbarAnnotate()) {\n state.getScrollbarAnnotate().clear()\n state.setScrollbarAnnotate(null)\n }\n }\n /**\n * Check if pos is in the specified range, INCLUSIVE.\n * Range can be specified with 1 or 2 arguments.\n * If the first range argument is an array, treat it as an array of line\n * numbers. Match pos against any of the lines.\n * If the first range argument is a number,\n * if there is only 1 range argument, check if pos has the same line\n * number\n * if there are 2 range arguments, then check if pos is in between the two\n * range arguments.\n */\n function isInRange(pos, start, end) {\n if (typeof pos !== 'number') {\n // Assume it is a cursor position. Get the line number.\n pos = pos.line\n }\n if (start instanceof Array) {\n return inArray(pos, start)\n } else {\n if (end) {\n return pos >= start && pos <= end\n } else {\n return pos == start\n }\n }\n }\n function getUserVisibleLines(cm) {\n var scrollInfo = cm.getScrollInfo()\n var occludeToleranceTop = 6\n var occludeToleranceBottom = 10\n var from = cm.coordsChar(\n { left: 0, top: occludeToleranceTop + scrollInfo.top },\n 'local'\n )\n var bottomY =\n scrollInfo.clientHeight - occludeToleranceBottom + scrollInfo.top\n var to = cm.coordsChar({ left: 0, top: bottomY }, 'local')\n return { top: from.line, bottom: to.line }\n }\n\n function getMarkPos(cm, vim, markName) {\n if (markName == \"'\") {\n var history = cm.doc.history.done\n var event = history[history.length - 2]\n return event && event.ranges && event.ranges[0].head\n }\n\n var mark = vim.marks[markName]\n return mark && mark.find()\n }\n\n var ExCommandDispatcher = function () {\n this.buildCommandMap_()\n }\n ExCommandDispatcher.prototype = {\n processCommand: function (cm, input, opt_params) {\n var that = this\n cm.operation(function () {\n cm.curOp.isVimOp = true\n that._processCommand(cm, input, opt_params)\n })\n },\n _processCommand: function (cm, input, opt_params) {\n var vim = cm.state.vim\n var commandHistoryRegister =\n vimGlobalState.registerController.getRegister(':')\n var previousCommand = commandHistoryRegister.toString()\n if (vim.visualMode) {\n exitVisualMode(cm)\n }\n var inputStream = new CodeMirror.StringStream(input)\n // update \": with the latest command whether valid or invalid\n commandHistoryRegister.setText(input)\n var params = opt_params || {}\n params.input = input\n try {\n this.parseInput_(cm, inputStream, params)\n } catch (e) {\n showConfirm(cm, e)\n throw e\n }\n var command\n var commandName\n if (!params.commandName) {\n // If only a line range is defined, move to the line.\n if (params.line !== undefined) {\n commandName = 'move'\n }\n } else {\n command = this.matchCommand_(params.commandName)\n if (command) {\n commandName = command.name\n if (command.excludeFromCommandHistory) {\n commandHistoryRegister.setText(previousCommand)\n }\n this.parseCommandArgs_(inputStream, params, command)\n if (command.type == 'exToKey') {\n // Handle Ex to Key mapping.\n for (var i = 0; i < command.toKeys.length; i++) {\n CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping')\n }\n return\n } else if (command.type == 'exToEx') {\n // Handle Ex to Ex mapping.\n this.processCommand(cm, command.toInput)\n return\n }\n }\n }\n if (!commandName) {\n showConfirm(cm, 'Not an editor command \":' + input + '\"')\n return\n }\n try {\n exCommands[commandName](cm, params)\n // Possibly asynchronous commands (e.g. substitute, which might have a\n // user confirmation), are responsible for calling the callback when\n // done. All others have it taken care of for them here.\n if ((!command || !command.possiblyAsync) && params.callback) {\n params.callback()\n }\n } catch (e) {\n showConfirm(cm, e)\n throw e\n }\n },\n parseInput_: function (cm, inputStream, result) {\n inputStream.eatWhile(':')\n // Parse range.\n if (inputStream.eat('%')) {\n result.line = cm.firstLine()\n result.lineEnd = cm.lastLine()\n } else {\n result.line = this.parseLineSpec_(cm, inputStream)\n if (result.line !== undefined && inputStream.eat(',')) {\n result.lineEnd = this.parseLineSpec_(cm, inputStream)\n }\n }\n\n // Parse command name.\n var commandMatch = inputStream.match(/^(\\w+)/)\n if (commandMatch) {\n result.commandName = commandMatch[1]\n } else {\n result.commandName = inputStream.match(/.*/)[0]\n }\n\n return result\n },\n parseLineSpec_: function (cm, inputStream) {\n var numberMatch = inputStream.match(/^(\\d+)/)\n if (numberMatch) {\n // Absolute line number plus offset (N+M or N-M) is probably a typo,\n // not something the user actually wanted. (NB: vim does allow this.)\n return parseInt(numberMatch[1], 10) - 1\n }\n switch (inputStream.next()) {\n case '.':\n return this.parseLineSpecOffset_(inputStream, cm.getCursor().line)\n case '$':\n return this.parseLineSpecOffset_(inputStream, cm.lastLine())\n case \"'\":\n var markName = inputStream.next()\n var markPos = getMarkPos(cm, cm.state.vim, markName)\n if (!markPos) throw new Error('Mark not set')\n return this.parseLineSpecOffset_(inputStream, markPos.line)\n case '-':\n case '+':\n inputStream.backUp(1)\n // Offset is relative to current line if not otherwise specified.\n return this.parseLineSpecOffset_(inputStream, cm.getCursor().line)\n default:\n inputStream.backUp(1)\n return undefined\n }\n },\n parseLineSpecOffset_: function (inputStream, line) {\n var offsetMatch = inputStream.match(/^([+-])?(\\d+)/)\n if (offsetMatch) {\n var offset = parseInt(offsetMatch[2], 10)\n if (offsetMatch[1] == '-') {\n line -= offset\n } else {\n line += offset\n }\n }\n return line\n },\n parseCommandArgs_: function (inputStream, params, command) {\n if (inputStream.eol()) {\n return\n }\n params.argString = inputStream.match(/.*/)[0]\n // Parse command-line arguments\n var delim = command.argDelimiter || /\\s+/\n var args = trim(params.argString).split(delim)\n if (args.length && args[0]) {\n params.args = args\n }\n },\n matchCommand_: function (commandName) {\n // Return the command in the command map that matches the shortest\n // prefix of the passed in command name. The match is guaranteed to be\n // unambiguous if the defaultExCommandMap's shortNames are set up\n // correctly. (see @code{defaultExCommandMap}).\n for (var i = commandName.length; i > 0; i--) {\n var prefix = commandName.substring(0, i)\n if (this.commandMap_[prefix]) {\n var command = this.commandMap_[prefix]\n if (command.name.indexOf(commandName) === 0) {\n return command\n }\n }\n }\n return null\n },\n buildCommandMap_: function () {\n this.commandMap_ = {}\n for (var i = 0; i < defaultExCommandMap.length; i++) {\n var command = defaultExCommandMap[i]\n var key = command.shortName || command.name\n this.commandMap_[key] = command\n }\n },\n map: function (lhs, rhs, ctx) {\n if (lhs != ':' && lhs.charAt(0) == ':') {\n if (ctx) {\n throw Error('Mode not supported for ex mappings')\n }\n var commandName = lhs.substring(1)\n if (rhs != ':' && rhs.charAt(0) == ':') {\n // Ex to Ex mapping\n this.commandMap_[commandName] = {\n name: commandName,\n type: 'exToEx',\n toInput: rhs.substring(1),\n user: true\n }\n } else {\n // Ex to key mapping\n this.commandMap_[commandName] = {\n name: commandName,\n type: 'exToKey',\n toKeys: rhs,\n user: true\n }\n }\n } else {\n if (rhs != ':' && rhs.charAt(0) == ':') {\n // Key to Ex mapping.\n var mapping = {\n keys: lhs,\n type: 'keyToEx',\n exArgs: { input: rhs.substring(1) }\n }\n if (ctx) {\n mapping.context = ctx\n }\n defaultKeymap.unshift(mapping)\n } else {\n // Key to key mapping\n var mapping = {\n keys: lhs,\n type: 'keyToKey',\n toKeys: rhs\n }\n if (ctx) {\n mapping.context = ctx\n }\n defaultKeymap.unshift(mapping)\n }\n }\n },\n unmap: function (lhs, ctx) {\n if (lhs != ':' && lhs.charAt(0) == ':') {\n // Ex to Ex or Ex to key mapping\n if (ctx) {\n throw Error('Mode not supported for ex mappings')\n }\n var commandName = lhs.substring(1)\n if (\n this.commandMap_[commandName] &&\n this.commandMap_[commandName].user\n ) {\n delete this.commandMap_[commandName]\n return\n }\n } else {\n // Key to Ex or key to key mapping\n var keys = lhs\n for (var i = 0; i < defaultKeymap.length; i++) {\n if (\n keys == defaultKeymap[i].keys &&\n defaultKeymap[i].context === ctx\n ) {\n defaultKeymap.splice(i, 1)\n return\n }\n }\n }\n throw Error('No such mapping.')\n }\n }\n\n var exCommands = {\n colorscheme: function (cm, params) {\n if (!params.args || params.args.length < 1) {\n showConfirm(cm, cm.getOption('theme'))\n return\n }\n cm.setOption('theme', params.args[0])\n },\n map: function (cm, params, ctx) {\n var mapArgs = params.args\n if (!mapArgs || mapArgs.length < 2) {\n if (cm) {\n showConfirm(cm, 'Invalid mapping: ' + params.input)\n }\n return\n }\n exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx)\n },\n imap: function (cm, params) {\n this.map(cm, params, 'insert')\n },\n nmap: function (cm, params) {\n this.map(cm, params, 'normal')\n },\n vmap: function (cm, params) {\n this.map(cm, params, 'visual')\n },\n unmap: function (cm, params, ctx) {\n var mapArgs = params.args\n if (!mapArgs || mapArgs.length < 1) {\n if (cm) {\n showConfirm(cm, 'No such mapping: ' + params.input)\n }\n return\n }\n exCommandDispatcher.unmap(mapArgs[0], ctx)\n },\n move: function (cm, params) {\n commandDispatcher.processCommand(cm, cm.state.vim, {\n type: 'motion',\n motion: 'moveToLineOrEdgeOfDocument',\n motionArgs: { forward: false, explicitRepeat: true, linewise: true },\n repeatOverride: params.line + 1\n })\n },\n set: function (cm, params) {\n var setArgs = params.args\n // Options passed through to the setOption/getOption calls. May be passed in by the\n // local/global versions of the set command\n var setCfg = params.setCfg || {}\n if (!setArgs || setArgs.length < 1) {\n if (cm) {\n showConfirm(cm, 'Invalid mapping: ' + params.input)\n }\n return\n }\n var expr = setArgs[0].split('=')\n var optionName = expr[0]\n var value = expr[1]\n var forceGet = false\n\n if (optionName.charAt(optionName.length - 1) == '?') {\n // If post-fixed with ?, then the set is actually a get.\n if (value) {\n throw Error('Trailing characters: ' + params.argString)\n }\n optionName = optionName.substring(0, optionName.length - 1)\n forceGet = true\n }\n if (value === undefined && optionName.substring(0, 2) == 'no') {\n // To set boolean options to false, the option name is prefixed with\n // 'no'.\n optionName = optionName.substring(2)\n value = false\n }\n\n var optionIsBoolean =\n options[optionName] && options[optionName].type == 'boolean'\n if (optionIsBoolean && value == undefined) {\n // Calling set with a boolean option sets it to true.\n value = true\n }\n // If no value is provided, then we assume this is a get.\n if ((!optionIsBoolean && value === undefined) || forceGet) {\n var oldValue = getOption(optionName, cm, setCfg)\n if (oldValue instanceof Error) {\n showConfirm(cm, oldValue.message)\n } else if (oldValue === true || oldValue === false) {\n showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName)\n } else {\n showConfirm(cm, ' ' + optionName + '=' + oldValue)\n }\n } else {\n var setOptionReturn = setOption(optionName, value, cm, setCfg)\n if (setOptionReturn instanceof Error) {\n showConfirm(cm, setOptionReturn.message)\n }\n }\n },\n setlocal: function (cm, params) {\n // setCfg is passed through to setOption\n params.setCfg = { scope: 'local' }\n this.set(cm, params)\n },\n setglobal: function (cm, params) {\n // setCfg is passed through to setOption\n params.setCfg = { scope: 'global' }\n this.set(cm, params)\n },\n registers: function (cm, params) {\n var regArgs = params.args\n var registers = vimGlobalState.registerController.registers\n var regInfo = '----------Registers----------

'\n if (!regArgs) {\n for (var registerName in registers) {\n var text = registers[registerName].toString()\n if (text.length) {\n regInfo += '\"' + registerName + ' ' + text + '
'\n }\n }\n } else {\n var registerName\n regArgs = regArgs.join('')\n for (var i = 0; i < regArgs.length; i++) {\n registerName = regArgs.charAt(i)\n if (\n !vimGlobalState.registerController.isValidRegister(registerName)\n ) {\n continue\n }\n var register = registers[registerName] || new Register()\n regInfo +=\n '\"' + registerName + ' ' + register.toString() + '
'\n }\n }\n showConfirm(cm, regInfo)\n },\n sort: function (cm, params) {\n var reverse, ignoreCase, unique, number, pattern\n function parseArgs() {\n if (params.argString) {\n var args = new CodeMirror.StringStream(params.argString)\n if (args.eat('!')) {\n reverse = true\n }\n if (args.eol()) {\n return\n }\n if (!args.eatSpace()) {\n return 'Invalid arguments'\n }\n var opts = args.match(/([dinuox]+)?\\s*(\\/.+\\/)?\\s*/)\n if (!opts && !args.eol()) {\n return 'Invalid arguments'\n }\n if (opts[1]) {\n ignoreCase = opts[1].indexOf('i') != -1\n unique = opts[1].indexOf('u') != -1\n var decimal =\n opts[1].indexOf('d') != -1 || (opts[1].indexOf('n') != -1 && 1)\n var hex = opts[1].indexOf('x') != -1 && 1\n var octal = opts[1].indexOf('o') != -1 && 1\n if (decimal + hex + octal > 1) {\n return 'Invalid arguments'\n }\n number =\n (decimal && 'decimal') || (hex && 'hex') || (octal && 'octal')\n }\n if (opts[2]) {\n pattern = new RegExp(\n opts[2].substr(1, opts[2].length - 2),\n ignoreCase ? 'i' : ''\n )\n }\n }\n }\n var err = parseArgs()\n if (err) {\n showConfirm(cm, err + ': ' + params.argString)\n return\n }\n var lineStart = params.line || cm.firstLine()\n var lineEnd = params.lineEnd || params.line || cm.lastLine()\n if (lineStart == lineEnd) {\n return\n }\n var curStart = Pos(lineStart, 0)\n var curEnd = Pos(lineEnd, lineLength(cm, lineEnd))\n var text = cm.getRange(curStart, curEnd).split('\\n')\n var numberRegex =\n pattern || number == 'decimal'\n ? /(-?)([\\d]+)/\n : number == 'hex'\n ? /(-?)(?:0x)?([0-9a-f]+)/i\n : number == 'octal'\n ? /([0-7]+)/\n : null\n var radix =\n number == 'decimal'\n ? 10\n : number == 'hex'\n ? 16\n : number == 'octal'\n ? 8\n : null\n var numPart = [],\n textPart = []\n if (number || pattern) {\n for (var i = 0; i < text.length; i++) {\n var matchPart = pattern ? text[i].match(pattern) : null\n if (matchPart && matchPart[0] != '') {\n numPart.push(matchPart)\n } else if (!pattern && numberRegex.exec(text[i])) {\n numPart.push(text[i])\n } else {\n textPart.push(text[i])\n }\n }\n } else {\n textPart = text\n }\n function compareFn(a, b) {\n if (reverse) {\n var tmp\n tmp = a\n a = b\n b = tmp\n }\n if (ignoreCase) {\n a = a.toLowerCase()\n b = b.toLowerCase()\n }\n var anum = number && numberRegex.exec(a)\n var bnum = number && numberRegex.exec(b)\n if (!anum) {\n return a < b ? -1 : 1\n }\n anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix)\n bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix)\n return anum - bnum\n }\n function comparePatternFn(a, b) {\n if (reverse) {\n var tmp\n tmp = a\n a = b\n b = tmp\n }\n if (ignoreCase) {\n a[0] = a[0].toLowerCase()\n b[0] = b[0].toLowerCase()\n }\n return a[0] < b[0] ? -1 : 1\n }\n numPart.sort(pattern ? comparePatternFn : compareFn)\n if (pattern) {\n for (var i = 0; i < numPart.length; i++) {\n numPart[i] = numPart[i].input\n }\n } else if (!number) {\n textPart.sort(compareFn)\n }\n text = !reverse ? textPart.concat(numPart) : numPart.concat(textPart)\n if (unique) {\n // Remove duplicate lines\n var textOld = text\n var lastLine\n text = []\n for (var i = 0; i < textOld.length; i++) {\n if (textOld[i] != lastLine) {\n text.push(textOld[i])\n }\n lastLine = textOld[i]\n }\n }\n cm.replaceRange(text.join('\\n'), curStart, curEnd)\n },\n global: function (cm, params) {\n // a global command is of the form\n // :[range]g/pattern/[cmd]\n // argString holds the string /pattern/[cmd]\n var argString = params.argString\n if (!argString) {\n showConfirm(cm, 'Regular Expression missing from global')\n return\n }\n // range is specified here\n var lineStart = params.line !== undefined ? params.line : cm.firstLine()\n var lineEnd = params.lineEnd || params.line || cm.lastLine()\n // get the tokens from argString\n var tokens = splitBySlash(argString)\n var regexPart = argString,\n cmd\n if (tokens.length) {\n regexPart = tokens[0]\n cmd = tokens.slice(1, tokens.length).join('/')\n }\n if (regexPart) {\n // If regex part is empty, then use the previous query. Otherwise\n // use the regex part as the new query.\n try {\n updateSearchQuery(\n cm,\n regexPart,\n true /** ignoreCase */,\n true /** smartCase */\n )\n } catch (e) {\n showConfirm(cm, 'Invalid regex: ' + regexPart)\n return\n }\n }\n // now that we have the regexPart, search for regex matches in the\n // specified range of lines\n var query = getSearchState(cm).getQuery()\n var matchedLines = [],\n content = ''\n for (var i = lineStart; i <= lineEnd; i++) {\n var matched = query.test(cm.getLine(i))\n if (matched) {\n matchedLines.push(i + 1)\n content += cm.getLine(i) + '
'\n }\n }\n // if there is no [cmd], just display the list of matched lines\n if (!cmd) {\n showConfirm(cm, content)\n return\n }\n var index = 0\n var nextCommand = function () {\n if (index < matchedLines.length) {\n var command = matchedLines[index] + cmd\n exCommandDispatcher.processCommand(cm, command, {\n callback: nextCommand\n })\n }\n index++\n }\n nextCommand()\n },\n substitute: function (cm, params) {\n if (!cm.getSearchCursor) {\n throw new Error(\n 'Search feature not available. Requires searchcursor.js or ' +\n 'any other getSearchCursor implementation.'\n )\n }\n var argString = params.argString\n var tokens = argString ? splitBySlash(argString) : []\n var regexPart,\n replacePart = '',\n trailing,\n flagsPart,\n count\n var confirm = false // Whether to confirm each replace.\n var global = false // True to replace all instances on a line, false to replace only 1.\n if (tokens.length) {\n regexPart = tokens[0]\n replacePart = tokens[1]\n if (regexPart && regexPart[regexPart.length - 1] === '$') {\n regexPart = regexPart.slice(0, regexPart.length - 1) + '\\\\n'\n replacePart = replacePart ? replacePart + '\\n' : '\\n'\n }\n if (replacePart !== undefined) {\n if (getOption('pcre')) {\n replacePart = unescapeRegexReplace(replacePart)\n } else {\n replacePart = translateRegexReplace(replacePart)\n }\n vimGlobalState.lastSubstituteReplacePart = replacePart\n }\n trailing = tokens[2] ? tokens[2].split(' ') : []\n } else {\n // either the argString is empty or its of the form ' hello/world'\n // actually splitBySlash returns a list of tokens\n // only if the string starts with a '/'\n if (argString && argString.length) {\n showConfirm(\n cm,\n 'Substitutions should be of the form ' + ':s/pattern/replace/'\n )\n return\n }\n }\n // After the 3rd slash, we can have flags followed by a space followed\n // by count.\n if (trailing) {\n flagsPart = trailing[0]\n count = parseInt(trailing[1])\n if (flagsPart) {\n if (flagsPart.indexOf('c') != -1) {\n confirm = true\n flagsPart.replace('c', '')\n }\n if (flagsPart.indexOf('g') != -1) {\n global = true\n flagsPart.replace('g', '')\n }\n regexPart = regexPart + '/' + flagsPart\n }\n }\n if (regexPart) {\n // If regex part is empty, then use the previous query. Otherwise use\n // the regex part as the new query.\n try {\n updateSearchQuery(\n cm,\n regexPart,\n true /** ignoreCase */,\n true /** smartCase */\n )\n } catch (e) {\n showConfirm(cm, 'Invalid regex: ' + regexPart)\n return\n }\n }\n replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart\n if (replacePart === undefined) {\n showConfirm(cm, 'No previous substitute regular expression')\n return\n }\n var state = getSearchState(cm)\n var query = state.getQuery()\n var lineStart =\n params.line !== undefined ? params.line : cm.getCursor().line\n var lineEnd = params.lineEnd || lineStart\n if (lineStart == cm.firstLine() && lineEnd == cm.lastLine()) {\n lineEnd = Infinity\n }\n if (count) {\n lineStart = lineEnd\n lineEnd = lineStart + count - 1\n }\n var startPos = clipCursorToContent(cm, Pos(lineStart, 0))\n var cursor = cm.getSearchCursor(query, startPos)\n doReplace(\n cm,\n confirm,\n global,\n lineStart,\n lineEnd,\n cursor,\n query,\n replacePart,\n params.callback\n )\n },\n redo: CodeMirror.commands.redo,\n undo: CodeMirror.commands.undo,\n write: function (cm) {\n if (CodeMirror.commands.save) {\n // If a save command is defined, call it.\n CodeMirror.commands.save(cm)\n } else if (cm.save) {\n // Saves to text area if no save command is defined and cm.save() is available.\n cm.save()\n }\n },\n nohlsearch: function (cm) {\n clearSearchHighlight(cm)\n },\n yank: function (cm) {\n var cur = copyCursor(cm.getCursor())\n var line = cur.line\n var lineText = cm.getLine(line)\n vimGlobalState.registerController.pushText(\n '0',\n 'yank',\n lineText,\n true,\n true\n )\n },\n delmarks: function (cm, params) {\n if (!params.argString || !trim(params.argString)) {\n showConfirm(cm, 'Argument required')\n return\n }\n\n var state = cm.state.vim\n var stream = new CodeMirror.StringStream(trim(params.argString))\n while (!stream.eol()) {\n stream.eatSpace()\n\n // Record the streams position at the beginning of the loop for use\n // in error messages.\n var count = stream.pos\n\n if (!stream.match(/[a-zA-Z]/, false)) {\n showConfirm(\n cm,\n 'Invalid argument: ' + params.argString.substring(count)\n )\n return\n }\n\n var sym = stream.next()\n // Check if this symbol is part of a range\n if (stream.match('-', true)) {\n // This symbol is part of a range.\n\n // The range must terminate at an alphabetic character.\n if (!stream.match(/[a-zA-Z]/, false)) {\n showConfirm(\n cm,\n 'Invalid argument: ' + params.argString.substring(count)\n )\n return\n }\n\n var startMark = sym\n var finishMark = stream.next()\n // The range must terminate at an alphabetic character which\n // shares the same case as the start of the range.\n if (\n (isLowerCase(startMark) && isLowerCase(finishMark)) ||\n (isUpperCase(startMark) && isUpperCase(finishMark))\n ) {\n var start = startMark.charCodeAt(0)\n var finish = finishMark.charCodeAt(0)\n if (start >= finish) {\n showConfirm(\n cm,\n 'Invalid argument: ' + params.argString.substring(count)\n )\n return\n }\n\n // Because marks are always ASCII values, and we have\n // determined that they are the same case, we can use\n // their char codes to iterate through the defined range.\n for (var j = 0; j <= finish - start; j++) {\n var mark = String.fromCharCode(start + j)\n delete state.marks[mark]\n }\n } else {\n showConfirm(cm, 'Invalid argument: ' + startMark + '-')\n return\n }\n } else {\n // This symbol is a valid mark, and is not part of a range.\n delete state.marks[sym]\n }\n }\n }\n }\n\n var exCommandDispatcher = new ExCommandDispatcher()\n\n /**\n * @param {CodeMirror} cm CodeMirror instance we are in.\n * @param {boolean} confirm Whether to confirm each replace.\n * @param {Cursor} lineStart Line to start replacing from.\n * @param {Cursor} lineEnd Line to stop replacing at.\n * @param {RegExp} query Query for performing matches with.\n * @param {string} replaceWith Text to replace matches with. May contain $1,\n * $2, etc for replacing captured groups using Javascript replace.\n * @param {function()} callback A callback for when the replace is done.\n */\n function doReplace(\n cm,\n confirm,\n global,\n lineStart,\n lineEnd,\n searchCursor,\n query,\n replaceWith,\n callback\n ) {\n // Set up all the functions.\n cm.state.vim.exMode = true\n var done = false\n var lastPos = searchCursor.from()\n function replaceAll() {\n cm.operation(function () {\n while (!done) {\n replace()\n next()\n }\n stop()\n })\n }\n function replace() {\n var text = cm.getRange(searchCursor.from(), searchCursor.to())\n var newText = text.replace(query, replaceWith)\n searchCursor.replace(newText)\n }\n function next() {\n // The below only loops to skip over multiple occurrences on the same\n // line when 'global' is not true.\n while (\n searchCursor.findNext() &&\n isInRange(searchCursor.from(), lineStart, lineEnd)\n ) {\n if (!global && lastPos && searchCursor.from().line == lastPos.line) {\n continue\n }\n cm.scrollIntoView(searchCursor.from(), 30)\n cm.setSelection(searchCursor.from(), searchCursor.to())\n lastPos = searchCursor.from()\n done = false\n return\n }\n done = true\n }\n function stop(close) {\n if (close) {\n close()\n }\n cm.focus()\n if (lastPos) {\n cm.setCursor(lastPos)\n var vim = cm.state.vim\n vim.exMode = false\n vim.lastHPos = vim.lastHSPos = lastPos.ch\n }\n if (callback) {\n callback()\n }\n }\n function onPromptKeyDown(e, _value, close) {\n // Swallow all keys.\n CodeMirror.e_stop(e)\n var keyName = CodeMirror.keyName(e)\n switch (keyName) {\n case 'Y':\n replace()\n next()\n break\n case 'N':\n next()\n break\n case 'A':\n // replaceAll contains a call to close of its own. We don't want it\n // to fire too early or multiple times.\n var savedCallback = callback\n callback = undefined\n cm.operation(replaceAll)\n callback = savedCallback\n break\n case 'L':\n replace()\n // fall through and exit.\n case 'Q':\n case 'Esc':\n case 'Ctrl-C':\n case 'Ctrl-[':\n stop(close)\n break\n }\n if (done) {\n stop(close)\n }\n return true\n }\n\n // Actually do replace.\n next()\n if (done) {\n showConfirm(cm, 'No matches for ' + query.source)\n return\n }\n if (!confirm) {\n replaceAll()\n if (callback) {\n callback()\n }\n return\n }\n showPrompt(cm, {\n prefix: 'replace with ' + replaceWith + ' (y/n/a/q/l)',\n onKeyDown: onPromptKeyDown\n })\n }\n\n CodeMirror.keyMap.vim = {\n attach: attachVimMap,\n detach: detachVimMap\n // call: cmKey\n }\n\n function exitInsertMode(cm) {\n var vim = cm.state.vim\n var macroModeState = vimGlobalState.macroModeState\n var insertModeChangeRegister =\n vimGlobalState.registerController.getRegister('.')\n var isPlaying = macroModeState.isPlaying\n var lastChange = macroModeState.lastInsertModeChanges\n // In case of visual block, the insertModeChanges are not saved as a\n // single word, so we convert them to a single word\n // so as to update the \". register as expected in real vim.\n var text = []\n if (!isPlaying) {\n var selLength = lastChange.inVisualBlock\n ? vim.lastSelection.visualBlock.height\n : 1\n var changes = lastChange.changes\n var text = []\n var i = 0\n // In case of multiple selections in blockwise visual,\n // the inserted text, for example: 'foo', is stored as\n // 'f', 'f', InsertModeKey 'o', 'o', 'o', 'o'. (if you have a block with 2 lines).\n // We push the contents of the changes array as per the following:\n // 1. In case of InsertModeKey, just increment by 1.\n // 2. In case of a character, jump by selLength (2 in the example).\n while (i < changes.length) {\n // This loop will convert 'ffoooo' to 'foo'.\n text.push(changes[i])\n if (changes[i] instanceof InsertModeKey) {\n i++\n } else {\n i += selLength\n }\n }\n lastChange.changes = text\n cm.off('change', onChange)\n CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown)\n }\n if (!isPlaying && vim.insertModeRepeat > 1) {\n // Perform insert mode repeat for commands like 3,a and 3,o.\n repeatLastEdit(\n cm,\n vim,\n vim.insertModeRepeat - 1,\n true /** repeatForInsert */\n )\n vim.lastEditInputState.repeatOverride = vim.insertModeRepeat\n }\n delete vim.insertModeRepeat\n vim.insertMode = false\n cm.setCursor(cm.getCursor().line, cm.getCursor().ch - 1)\n cm.setOption('keyMap', 'vim')\n cm.setOption('disableInput', true)\n cm.toggleOverwrite(false) // exit replace mode if we were in it.\n // update the \". register before exiting insert mode\n insertModeChangeRegister.setText(lastChange.changes.join(''))\n CodeMirror.signal(cm, 'vim-mode-change', { mode: 'normal' })\n if (macroModeState.isRecording) {\n logInsertModeChange(macroModeState)\n }\n }\n\n function _mapCommand(command) {\n defaultKeymap.unshift(command)\n }\n\n function mapCommand(keys, type, name, args, extra) {\n var command = { keys: keys, type: type }\n command[type] = name\n command[type + 'Args'] = args\n for (var key in extra) {\n command[key] = extra[key]\n }\n _mapCommand(command)\n }\n\n // The timeout in milliseconds for the two-character ESC keymap should be\n // adjusted according to your typing speed to prevent false positives.\n defineOption('insertModeEscKeysTimeout', 200, 'number')\n\n CodeMirror.keyMap['vim-insert'] = {\n // TODO: override navigation keys so that Esc will cancel automatic\n // indentation from o, O, i_\n // fallthrough: ['default'],\n fallthrough: [],\n attach: attachVimMap,\n detach: detachVimMap\n // call: cmKey\n }\n\n CodeMirror.keyMap['vim-replace'] = {\n Backspace: 'goCharLeft',\n fallthrough: ['vim-insert'],\n attach: attachVimMap,\n detach: detachVimMap\n // call: cmKey\n }\n\n function executeMacroRegister(cm, vim, macroModeState, registerName) {\n var register = vimGlobalState.registerController.getRegister(registerName)\n if (registerName == ':') {\n // Read-only register containing last Ex command.\n if (register.keyBuffer[0]) {\n exCommandDispatcher.processCommand(cm, register.keyBuffer[0])\n }\n macroModeState.isPlaying = false\n return\n }\n var keyBuffer = register.keyBuffer\n var imc = 0\n macroModeState.isPlaying = true\n macroModeState.replaySearchQueries = register.searchQueries.slice(0)\n for (var i = 0; i < keyBuffer.length; i++) {\n var text = keyBuffer[i]\n var match, key\n while (text) {\n // Pull off one command key, which is either a single character\n // or a special sequence wrapped in '<' and '>', e.g. ''.\n match = /<\\w+-.+?>|<\\w+>|./.exec(text)\n key = match[0]\n text = text.substring(match.index + key.length)\n CodeMirror.Vim.handleKey(cm, key, 'macro')\n if (vim.insertMode) {\n var changes = register.insertModeChanges[imc++].changes\n vimGlobalState.macroModeState.lastInsertModeChanges.changes =\n changes\n repeatInsertModeChanges(cm, changes, 1)\n exitInsertMode(cm)\n }\n }\n }\n macroModeState.isPlaying = false\n }\n\n function logKey(macroModeState, key) {\n if (macroModeState.isPlaying) {\n return\n }\n var registerName = macroModeState.latestRegister\n var register = vimGlobalState.registerController.getRegister(registerName)\n if (register) {\n register.pushText(key)\n }\n }\n\n function logInsertModeChange(macroModeState) {\n if (macroModeState.isPlaying) {\n return\n }\n var registerName = macroModeState.latestRegister\n var register = vimGlobalState.registerController.getRegister(registerName)\n if (register && register.pushInsertModeChanges) {\n register.pushInsertModeChanges(macroModeState.lastInsertModeChanges)\n }\n }\n\n function logSearchQuery(macroModeState, query) {\n if (macroModeState.isPlaying) {\n return\n }\n var registerName = macroModeState.latestRegister\n var register = vimGlobalState.registerController.getRegister(registerName)\n if (register && register.pushSearchQuery) {\n register.pushSearchQuery(query)\n }\n }\n\n /**\n * Listens for changes made in insert mode.\n * Should only be active in insert mode.\n */\n function onChange(cm, changeObj) {\n var macroModeState = vimGlobalState.macroModeState\n var lastChange = macroModeState.lastInsertModeChanges\n if (!macroModeState.isPlaying) {\n while (changeObj) {\n lastChange.expectCursorActivityForChange = true\n if (\n changeObj.origin == '+input' ||\n changeObj.origin == 'paste' ||\n changeObj.origin === undefined /* only in testing */\n ) {\n var text = changeObj.text.join('\\n')\n if (lastChange.maybeReset) {\n lastChange.changes = []\n lastChange.maybeReset = false\n }\n if (cm.state.overwrite && !/\\n/.test(text)) {\n lastChange.changes.push([text])\n } else {\n lastChange.changes.push(text)\n }\n }\n // Change objects may be chained with next.\n changeObj = changeObj.next\n }\n }\n }\n\n /**\n * Listens for any kind of cursor activity on CodeMirror.\n */\n function onCursorActivity(cm) {\n var vim = cm.state.vim\n if (vim.insertMode) {\n // Tracking cursor activity in insert mode (for macro support).\n var macroModeState = vimGlobalState.macroModeState\n if (macroModeState.isPlaying) {\n return\n }\n var lastChange = macroModeState.lastInsertModeChanges\n if (lastChange.expectCursorActivityForChange) {\n lastChange.expectCursorActivityForChange = false\n } else {\n // Cursor moved outside the context of an edit. Reset the change.\n lastChange.maybeReset = true\n }\n } else if (!cm.curOp.isVimOp) {\n handleExternalSelection(cm, vim)\n }\n if (vim.visualMode) {\n updateFakeCursor(cm)\n }\n }\n function updateFakeCursor(cm) {\n var vim = cm.state.vim\n var from = clipCursorToContent(cm, copyCursor(vim.sel.head))\n var to = offsetCursor(from, 0, 1)\n if (vim.fakeCursor) {\n vim.fakeCursor.clear()\n }\n vim.fakeCursor = cm.markText(from, to, {\n className: 'cm-animate-fat-cursor'\n })\n }\n function handleExternalSelection(cm, vim) {\n var anchor = cm.getCursor('anchor')\n var head = cm.getCursor('head')\n // Enter or exit visual mode to match mouse selection.\n if (vim.visualMode && !cm.somethingSelected()) {\n exitVisualMode(cm, false)\n } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) {\n vim.visualMode = true\n vim.visualLine = false\n CodeMirror.signal(cm, 'vim-mode-change', { mode: 'visual' })\n }\n if (vim.visualMode) {\n // Bind CodeMirror selection model to vim selection model.\n // Mouse selections are considered visual characterwise.\n var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0\n var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0\n head = offsetCursor(head, 0, headOffset)\n anchor = offsetCursor(anchor, 0, anchorOffset)\n vim.sel = {\n anchor: anchor,\n head: head\n }\n updateMark(cm, vim, '<', cursorMin(head, anchor))\n updateMark(cm, vim, '>', cursorMax(head, anchor))\n } else if (!vim.insertMode) {\n // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse.\n vim.lastHPos = cm.getCursor().ch\n }\n }\n\n /** Wrapper for special keys pressed in insert mode */\n function InsertModeKey(keyName) {\n this.keyName = keyName\n }\n\n /**\n * Handles raw key down events from the text area.\n * - Should only be active in insert mode.\n * - For recording deletes in insert mode.\n */\n function onKeyEventTargetKeyDown(e) {\n var macroModeState = vimGlobalState.macroModeState\n var lastChange = macroModeState.lastInsertModeChanges\n var keyName = CodeMirror.keyName(e)\n if (!keyName) {\n return\n }\n function onKeyFound() {\n if (lastChange.maybeReset) {\n lastChange.changes = []\n lastChange.maybeReset = false\n }\n lastChange.changes.push(new InsertModeKey(keyName))\n return true\n }\n if (\n keyName.indexOf('Delete') != -1 ||\n keyName.indexOf('Backspace') != -1\n ) {\n CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound)\n }\n }\n\n /**\n * Repeats the last edit, which includes exactly 1 command and at most 1\n * insert. Operator and motion commands are read from lastEditInputState,\n * while action commands are read from lastEditActionCommand.\n *\n * If repeatForInsert is true, then the function was called by\n * exitInsertMode to repeat the insert mode changes the user just made. The\n * corresponding enterInsertMode call was made with a count.\n */\n function repeatLastEdit(cm, vim, repeat, repeatForInsert) {\n var macroModeState = vimGlobalState.macroModeState\n macroModeState.isPlaying = true\n var isAction = !!vim.lastEditActionCommand\n var cachedInputState = vim.inputState\n function repeatCommand() {\n if (isAction) {\n commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand)\n } else {\n commandDispatcher.evalInput(cm, vim)\n }\n }\n function repeatInsert(repeat) {\n if (macroModeState.lastInsertModeChanges.changes.length > 0) {\n // For some reason, repeat cw in desktop VIM does not repeat\n // insert mode changes. Will conform to that behavior.\n repeat = !vim.lastEditActionCommand ? 1 : repeat\n var changeObject = macroModeState.lastInsertModeChanges\n repeatInsertModeChanges(cm, changeObject.changes, repeat)\n }\n }\n vim.inputState = vim.lastEditInputState\n if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) {\n // o and O repeat have to be interlaced with insert repeats so that the\n // insertions appear on separate lines instead of the last line.\n for (var i = 0; i < repeat; i++) {\n repeatCommand()\n repeatInsert(1)\n }\n } else {\n if (!repeatForInsert) {\n // Hack to get the cursor to end up at the right place. If I is\n // repeated in insert mode repeat, cursor will be 1 insert\n // change set left of where it should be.\n repeatCommand()\n }\n repeatInsert(repeat)\n }\n vim.inputState = cachedInputState\n if (vim.insertMode && !repeatForInsert) {\n // Don't exit insert mode twice. If repeatForInsert is set, then we\n // were called by an exitInsertMode call lower on the stack.\n exitInsertMode(cm)\n }\n macroModeState.isPlaying = false\n }\n\n function repeatInsertModeChanges(cm, changes, repeat) {\n function keyHandler(binding) {\n if (typeof binding === 'string') {\n CodeMirror.commands[binding](cm)\n } else {\n binding(cm)\n }\n return true\n }\n var head = cm.getCursor('head')\n var inVisualBlock =\n vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock\n if (inVisualBlock) {\n // Set up block selection again for repeating the changes.\n var vim = cm.state.vim\n var lastSel = vim.lastSelection\n var offset = getOffset(lastSel.anchor, lastSel.head)\n selectForInsert(cm, head, offset.line + 1)\n repeat = cm.listSelections().length\n cm.setCursor(head)\n }\n for (var i = 0; i < repeat; i++) {\n if (inVisualBlock) {\n cm.setCursor(offsetCursor(head, i, 0))\n }\n for (var j = 0; j < changes.length; j++) {\n var change = changes[j]\n if (change instanceof InsertModeKey) {\n CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler)\n } else if (typeof change === 'string') {\n var cur = cm.getCursor()\n cm.replaceRange(change, cur, cur)\n } else {\n var start = cm.getCursor()\n var end = offsetCursor(start, 0, change[0].length)\n cm.replaceRange(change[0], start, end)\n }\n }\n }\n if (inVisualBlock) {\n cm.setCursor(offsetCursor(head, 0, 1))\n }\n }\n\n resetVimGlobalState()\n\n vimApi.commandDispatcher = commandDispatcher\n vimApi.exCommandDispatcher = exCommandDispatcher\n return vimApi\n }\n\n // Initialize Vim and make it available as an API.\n return (CodeMirror.Vim = Vim())\n}\n"],"mappings":"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"} \ No newline at end of file diff --git a/lib/vim.js b/lib/vim.js deleted file mode 100644 index d3e558b..0000000 --- a/lib/vim.js +++ /dev/null @@ -1,1312 +0,0 @@ -"use strict"; - -var _inkdrop = require("inkdrop"); -var _keymap = _interopRequireDefault(require("./keymap")); -var _eventKit = require("event-kit"); -var _codemirror = _interopRequireDefault(require("codemirror")); -var _electron = require("electron"); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } -function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } -function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } -class Plugin { - constructor() { - _defineProperty(this, "config", { - seamlessJumpToTitle: { - title: 'Seamlessly jump to note title', - type: 'boolean', - description: 'Focus jumps from the editor to the note title bar by `vim:move-up` command', - default: false - } - }); - _defineProperty(this, "handleEditorLoad", editor => { - this.activateMode(editor); - }); - _defineProperty(this, "handleVimModeChange", (event, _opt) => { - _inkdrop.logger.debug('vim mode changed:', event); - const { - mode - } = event; - const cm = this.getCodeMirror(); - cm.getWrapperElement().classList.remove('insert-mode'); - cm.getWrapperElement().classList.remove('visual-mode'); - cm.getWrapperElement().classList.remove('normal-mode'); - cm.getWrapperElement().classList.remove('replace-mode'); - switch (mode) { - case 'normal': - cm.getWrapperElement().classList.add('normal-mode'); - break; - case 'visual': - cm.getWrapperElement().classList.add('visual-mode'); - break; - case 'replace': - cm.getWrapperElement().classList.add('replace-mode'); - break; - case 'insert': - cm.getWrapperElement().classList.add('insert-mode'); - break; - } - }); - _defineProperty(this, "handleEditorTextInput", event => { - // only process if the event is fired via EventTarget.dispatchEvent() - if (this.isInsertMode() && !event.isTrusted) { - _inkdrop.logger.debug('handle text input:', event); - const text = event.data; - const cm = this.getCodeMirror(); - cm.replaceSelection(text); - } - }); - _defineProperty(this, "handleEditorKeyDown", event => { - const keyName = this.normalizeKeyName(event.key); - const cm = this.getCodeMirror(); - const vim = this.vim.maybeInitVimState(cm); - const isNumeric = !event.ctrlKey && !event.altKey && !event.metaKey && !event.shiftKey && keyName.match(/^\d$/); - const target = cm.getInputField(); - const currentKeyStroke = [...inkdrop.keymaps.queuedKeystrokes.filter(k => !k.startsWith('^')), keyName]; - const { - partialMatchCandidates, - exactMatchCandidates - } = inkdrop.keymaps.findMatchCandidates(currentKeyStroke); - const partialMatches = inkdrop.keymaps.findPartialMatches(partialMatchCandidates, target); - const exactMatches = inkdrop.keymaps.findExactMatches(exactMatchCandidates, target); - _inkdrop.logger.debug('handleEditorKeyDown: currentKeyStroke:', currentKeyStroke); - _inkdrop.logger.debug('handleEditorKeyDown: exactMatches:', exactMatches); - _inkdrop.logger.debug('handleEditorKeyDown: partialMatches:', partialMatches); - if (this.isBufferingKey()) { - _inkdrop.logger.debug('handleEditorKeyDown: handle key buffering:', keyName, event); - const b = cm.getInputField().webkitMatchesSelector('.CodeMirror.vim-mode:not(.insert-mode) textarea'); - _inkdrop.logger.debug('handleEditorKeyDown: keybinding check:', exactMatches, b); - if (keyName !== 'Ctrl' && keyName !== 'Alt' && keyName !== 'Shift' && keyName !== 'Meta') { - const { - inputState - } = vim; - const hasOperatorOrMotion = inputState.motion || inputState.operator; - if ((event.key.length === 1 || keyName === 'space') && (!isNumeric || !hasOperatorOrMotion)) { - inputState.selectedCharacter = event.key; - inputState.keyBuffer = ''; - if (exactMatches.length === 0 && partialMatches.length === 0) { - const { - pendingCommand - } = this; - this.stopBufferingKey(); - if (typeof pendingCommand === 'function') { - if (pendingCommand(event)) { - event.stopPropagation(); - event.preventDefault(); - } - } - } - } else if (isNumeric) { - vim.inputState.pushRepeatDigit(keyName); - } - } - } else if (!this.isInsertMode()) { - if (isNumeric) { - if (exactMatches.length === 0) { - vim.inputState.pushRepeatDigit(keyName); - } - } else { - // push key buffer to the repeat digit - const keys = vim.inputState.keyBuffer; - vim.inputState.keyBuffer = ''; - const keysMatcher = /^(\d*)(.*)$/.exec(keys); - if (keysMatcher[1] && keysMatcher[1] !== '0') { - vim.inputState.pushRepeatDigit(keysMatcher[1]); - } - } - } - }); - _defineProperty(this, "handleFocusEditor", _event => { - this.yankClipboard(); - }); - } - activate() { - this.vim = (0, _keymap.default)(_codemirror.default); - if (inkdrop.isEditorActive()) { - this.activateMode(inkdrop.getActiveEditor()); - } - inkdrop.onEditorLoad(this.handleEditorLoad); - } - deactivate() { - if (this.disposables) { - this.disposables.dispose(); - } - if (inkdrop.isEditorActive()) { - this.deactivateMode(inkdrop.getActiveEditor()); - } - } - activateMode(editor) { - const { - cm - } = editor; - this.originalKeyMap = cm.getOption('keyMap'); - cm.setOption('keyMap', 'vim'); - cm.on('vim-mode-change', this.handleVimModeChange); - cm.on('focus', this.handleFocusEditor); - const el = cm.getWrapperElement(); - el.classList.add('vim-mode', 'normal-mode'); - this.registerCommands(); - this.registerExCommands(); - } - deactivateMode(editor) { - const { - cm - } = editor; - if (cm && this.originalKeyMap) { - cm.setOption('keyMap', this.originalKeyMap); - cm.off('vim-mode-change', this.handleVimModeChange); - const el = cm.getWrapperElement(); - el.classList.remove('vim-mode'); - } - } - normalizeKeyName(key) { - switch (key) { - case 'Enter': - return 'enter'; - case ' ': - return 'space'; - case 'ArrowRight': - return 'right'; - case 'ArrowLeft': - return 'left'; - case 'ArrowUp': - return 'up'; - case 'ArrowDown': - return 'down'; - default: - if (key.match(/^[A-Z]$/)) { - return `shift-${key}`; - } - return key; - } - } - startBufferingKey(command, customBufferingModeClass) { - const wrapper = this.getCodeMirror().getWrapperElement(); - _inkdrop.logger.debug('Start key buffering'); - wrapper.classList.add('key-buffering'); - if (customBufferingModeClass) { - wrapper.classList.add('key-buffering-' + customBufferingModeClass); - } - this.pendingCommand = command; - } - stopBufferingKey() { - _inkdrop.logger.debug('Stop key buffering'); - const wrapper = this.getCodeMirror().getWrapperElement(); - const classes = Array.prototype.slice.apply(wrapper.classList); - for (const i of classes) { - if (i.startsWith('key-buffering')) { - wrapper.classList.remove(i); - } - } - this.pendingCommand = undefined; - } - isBufferingKey() { - const wrapper = this.getCodeMirror().getWrapperElement(); - return wrapper.classList.contains('key-buffering'); - } - bufferKey(key) { - const cm = this.getCodeMirror(); - const vim = this.vim.maybeInitVimState(cm); - const vimKey = this.vim.cmKeyToVimKey("'" + key + "'"); - vim.inputState.keyBuffer = vim.inputState.keyBuffer + vimKey; - _inkdrop.logger.debug('keyBuffer:', vim.inputState.keyBuffer, vim.inputState); - } - isInsertMode() { - const wrapper = this.getCodeMirror().getWrapperElement(); - return wrapper.classList.contains('insert-mode'); - } - registerCommands() { - const disposables = new _eventKit.CompositeDisposable(); - const editor = inkdrop.getActiveEditor(); - const { - cm - } = editor; - const wrapper = cm.getWrapperElement(); - const doKeyToKey = async command => { - _inkdrop.logger.debug('doKeyToKey:', command); - let keys = command.toKeys; - while (keys) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - const match = /<\w+-.+?>|<\w+>|./.exec(keys); - let key = match[0]; - _inkdrop.logger.debug('key:', key); - keys = keys.substring(match.index + key.length); - if (this.isBufferingKey()) { - this.handleEditorKeyDown(new KeyboardEvent('keydown', { - key - })); - } else { - if (key.match(/^[A-Z]$/)) { - key = 'shift-' + key; - } - const { - exactMatchCandidates - } = inkdrop.keymaps.findMatchCandidates([key]); - _inkdrop.logger.debug('exactMatchCandidates:', exactMatchCandidates); - const bindings = inkdrop.keymaps.findExactMatches(exactMatchCandidates, document.activeElement); - const b = bindings[0]; - if (b) { - inkdrop.commands.dispatch(document.activeElement, b.command); - } else { - _inkdrop.logger.debug('command not found for key:', key); - } - } - } - }; - - // bind key to command - const h = command => { - return e => { - _inkdrop.logger.debug('command:', command, 'state:', Object.assign({}, cm.state.vim.inputState)); - e.stopPropagation(); - const vim = this.vim.maybeInitVimState(cm); - return cm.operation(() => { - cm.curOp.isVimOp = true; - try { - if (command.type === 'keyToKey') { - doKeyToKey(command); - } else { - this.vim.commandDispatcher.processCommand(cm, vim, command); - } - } catch (e) { - // clear VIM state in case it's in a bad state. - cm.state.vim = undefined; - this.vim.maybeInitVimState(cm); - if (!_codemirror.default.Vim.suppressErrorLogging) { - console.error(e); - } - throw e; - } - return true; - }); - }; - }; - // bind keystroke to command - const b = command => { - return e => { - _inkdrop.logger.debug('buffer command:', command, 'state:', Object.assign({}, cm.state.vim.inputState), e.originalEvent); - this.startBufferingKey(h(command), 'command'); - this.bufferKey(e.originalEvent.key); - }; - }; - // bind keystroke to operator - const p = command => { - return e => { - _inkdrop.logger.debug('operator command:', command, 'state:', Object.assign({}, cm.state.vim.inputState), e.originalEvent, e); - const vim = this.vim.maybeInitVimState(cm); - if (!vim.inputState.operator && !this.isBufferingKey() && !vim.visualMode) { - this.startBufferingKey(e => { - const el = cm.getInputField(); - const keyName = this.normalizeKeyName(e.key); - const keyBinding = inkdrop.keymaps.findKeyBindings({ - keystrokes: keyName, - target: el - }); - if (keyBinding.length > 0) { - inkdrop.commands.dispatch(el, keyBinding[0].command); - return true; - } else { - return false; - } - }, 'operator'); - if (e.originalEvent) { - this.bufferKey(e.originalEvent.key); - } else { - _inkdrop.logger.debug('buffer key:', command.keys); - this.bufferKey(command.keys); - } - } - return h(command)(e); - }; - }; - const handlers = { - 'vim:native!': () => {}, - 'vim:reset-normal-mode': e => { - _codemirror.default.Vim.clearInputState(cm); - this.stopBufferingKey(); - e.stopPropagation(); - }, - 'vim:exit-visual-mode': e => { - _inkdrop.logger.debug('exit-visual-mode'); - _codemirror.default.Vim.clearInputState(cm); - _codemirror.default.Vim.exitVisualMode(cm); - this.stopBufferingKey(); - e.stopPropagation(); - }, - 'vim:exit-insert-mode': e => { - _inkdrop.logger.debug('exit-insert-mode'); - _codemirror.default.Vim.clearInputState(cm); - _codemirror.default.Vim.exitInsertMode(cm); - this.stopBufferingKey(); - e.stopPropagation(); - }, - 'vim:move-left': h({ - keys: 'h', - type: 'motion', - motion: 'moveByCharacters', - motionArgs: { - forward: false - } - }), - 'vim:move-right': h({ - keys: 'l', - type: 'motion', - motion: 'moveByCharacters', - motionArgs: { - forward: true - } - }), - 'vim:move-up': (command => { - return e => { - const seamlessJumpToTitleEnabled = inkdrop.config.get('vim.seamlessJumpToTitle'); - const cur = cm.getCursor(); - if (cur.line === 0 && cur.ch === 0 && seamlessJumpToTitleEnabled) { - e.stopPropagation(); - inkdrop.commands.dispatch(document.body, 'editor:title:focus'); - } else { - command(e); - } - }; - })(h({ - keys: 'k', - type: 'motion', - motion: 'moveByLines', - motionArgs: { - forward: false, - linewise: true - } - })), - 'vim:move-down': h({ - keys: 'j', - type: 'motion', - motion: 'moveByLines', - motionArgs: { - forward: true, - linewise: true - } - }), - 'vim:move-up-by-display-lines': h({ - keys: 'gk', - type: 'motion', - motion: 'moveByDisplayLines', - motionArgs: { - forward: false - } - }), - 'vim:move-down-by-display-lines': h({ - keys: 'gj', - type: 'motion', - motion: 'moveByDisplayLines', - motionArgs: { - forward: true - } - }), - 'vim:move-to-next-word': h({ - keys: 'w', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: true, - wordEnd: false - } - }), - 'vim:move-to-next-whole-word': h({ - keys: 'W', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: true, - wordEnd: false, - bigWord: true - } - }), - 'vim:move-to-end-of-word': h({ - keys: 'e', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: true, - wordEnd: true, - inclusive: true - } - }), - 'vim:move-to-previous-end-of-word': h({ - keys: 'ge', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: false, - wordEnd: true, - inclusive: true - } - }), - 'vim:move-to-end-of-whole-word': h({ - keys: 'E', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: true, - wordEnd: true, - bigWord: true, - inclusive: true - } - }), - 'vim:move-to-previous-end-of-whole-word': h({ - keys: 'gE', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: false, - wordEnd: true, - bigWord: true, - inclusive: true - } - }), - 'vim:move-to-previous-word': h({ - keys: 'b', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: false, - wordEnd: false - } - }), - 'vim:move-to-previous-whole-word': h({ - keys: 'B', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: false, - wordEnd: false, - bigWord: true - } - }), - 'vim:move-to-next-paragraph': h({ - keys: '}', - type: 'motion', - motion: 'moveByParagraph', - motionArgs: { - forward: true, - toJumplist: true - } - }), - 'vim:move-to-previous-paragraph': h({ - keys: '{', - type: 'motion', - motion: 'moveByParagraph', - motionArgs: { - forward: false, - toJumplist: true - } - }), - 'vim:move-to-beginning-of-line-with-zero': (() => { - const handler = h({ - keys: '0', - type: 'motion', - motion: 'moveToStartOfLine' - }); - return e => { - const vim = this.vim.maybeInitVimState(cm); - if (vim.inputState.getRepeat() > 0) { - vim.inputState.pushRepeatDigit('0'); - } else { - return handler(e); - } - }; - })(), - 'vim:move-to-beginning-of-line': h({ - keys: '0', - type: 'motion', - motion: 'moveToStartOfLine' - }), - 'vim:move-to-first-character-of-line': h({ - keys: '^', - type: 'motion', - motion: 'moveToFirstNonWhiteSpaceCharacter' - }), - 'vim:move-to-first-character-of-line-and-down': h({ - keys: '_', - type: 'motion', - motion: 'moveByLines', - motionArgs: { - forward: true, - toFirstChar: true, - repeatOffset: -1 - } - }), - 'vim:move-to-last-character-of-line': h({ - keys: '$', - type: 'motion', - motion: 'moveToEol', - motionArgs: { - inclusive: true - } - }), - 'vim:move-to-last-nonblank-character-of-line-and-down': () => { - '???'; - }, - 'vim:move-to-first-character-of-line-up': h({ - keys: '-', - type: 'motion', - motion: 'moveByLines', - motionArgs: { - forward: false, - toFirstChar: true - } - }), - 'vim:move-to-first-character-of-line-down': h({ - keys: '+', - type: 'motion', - motion: 'moveByLines', - motionArgs: { - forward: true, - toFirstChar: true - } - }), - 'vim:move-to-start-of-file': h({ - keys: 'gg', - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { - forward: false, - explicitRepeat: true, - linewise: true, - toJumplist: true - } - }), - 'vim:scroll-half-screen-up': h({ - keys: '', - type: 'motion', - motion: 'moveByScroll', - motionArgs: { - forward: false, - explicitRepeat: true - } - }), - 'vim:scroll-full-screen-up': h({ - keys: '', - type: 'motion', - motion: 'moveByPage', - motionArgs: { - forward: false - } - }), - 'vim:scroll-half-screen-down': h({ - keys: '', - type: 'motion', - motion: 'moveByScroll', - motionArgs: { - forward: true, - explicitRepeat: true - } - }), - 'vim:scroll-full-screen-down': h({ - keys: '', - type: 'motion', - motion: 'moveByPage', - motionArgs: { - forward: true - } - }), - 'vim:scroll-down': h({ - keys: '', - type: 'action', - action: 'scroll', - actionArgs: { - forward: true, - linewise: true - } - }), - 'vim:scroll-up': h({ - keys: '', - type: 'action', - action: 'scroll', - actionArgs: { - forward: false, - linewise: true - } - }), - 'vim:scroll-cursor-to-top': h({ - keys: 'z', - type: 'action', - action: 'scrollToCursor', - actionArgs: { - position: 'top' - }, - motion: 'moveToFirstNonWhiteSpaceCharacter' - }), - 'vim:scroll-cursor-to-top-leave': h({ - keys: 'zt', - type: 'action', - action: 'scrollToCursor', - actionArgs: { - position: 'top' - } - }), - 'vim:scroll-cursor-to-middle': h({ - keys: 'z.', - type: 'action', - action: 'scrollToCursor', - actionArgs: { - position: 'center' - }, - motion: 'moveToFirstNonWhiteSpaceCharacter' - }), - 'vim:scroll-cursor-to-middle-leave': h({ - keys: 'zz', - type: 'action', - action: 'scrollToCursor', - actionArgs: { - position: 'center' - } - }), - 'vim:scroll-cursor-to-bottom': h({ - keys: 'z-', - type: 'action', - action: 'scrollToCursor', - actionArgs: { - position: 'bottom' - } - }), - 'vim:scroll-cursor-to-bottom-leave': h({ - keys: 'zb', - type: 'action', - action: 'scrollToCursor', - actionArgs: { - position: 'bottom' - }, - motion: 'moveToFirstNonWhiteSpaceCharacter' - }), - 'vim:move-to-line': h({ - keys: 'G', - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { - forward: true, - explicitRepeat: true, - linewise: true, - toJumplist: true - } - }), - 'vim:move-to-top-of-screen': h({ - keys: 'H', - type: 'motion', - motion: 'moveToTopLine', - motionArgs: { - linewise: true, - toJumplist: true - } - }), - 'vim:move-to-bottom-of-screen': h({ - keys: 'L', - type: 'motion', - motion: 'moveToBottomLine', - motionArgs: { - linewise: true, - toJumplist: true - } - }), - 'vim:move-to-middle-of-screen': h({ - keys: 'M', - type: 'motion', - motion: 'moveToMiddleLine', - motionArgs: { - linewise: true, - toJumplist: true - } - }), - 'vim:delete': p({ - keys: 'd', - type: 'operator', - operator: 'delete' - }), - 'vim:delete-to-last-character-of-line': h({ - keys: 'D', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveToEol', - motionArgs: { - inclusive: true - }, - context: 'normal' - }), - 'vim:change': p({ - keys: 'c', - type: 'operator', - operator: 'change' - }), - 'vim:change-to-last-character-of-line': h({ - keys: 'C', - type: 'operatorMotion', - operator: 'change', - motion: 'moveToEol', - motionArgs: { - inclusive: true - }, - context: 'normal' - }), - 'vim:substitute-line': h({ - keys: 'S', - type: 'keyToKey', - toKeys: 'cc', - context: 'normal' - }), - 'vim:substitute-line-visual': h({ - keys: 'S', - type: 'keyToKey', - toKeys: 'VdO', - context: 'visual' - }), - 'vim:replace': b({ - keys: 'r', - type: 'action', - action: 'replace', - isEdit: true - }), - 'vim:insert-at-beginning-of-line': h({ - keys: 'I', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - insertAt: 'firstNonBlank' - }, - context: 'normal' - }), - 'vim:text-object-manipulation-inner': b({ - keys: 'i', - type: 'motion', - motion: 'textObjectManipulation', - motionArgs: { - textObjectInner: true - } - }), - 'vim:text-object-manipulation': b({ - keys: 'a', - type: 'motion', - motion: 'textObjectManipulation' - }), - 'vim:indent': p({ - keys: '>', - type: 'operator', - operator: 'indent', - operatorArgs: { - indentRight: true - } - }), - 'vim:outdent': p({ - keys: '<', - type: 'operator', - operator: 'indent', - operatorArgs: { - indentRight: false - } - }), - 'vim:auto-indent': () => { - 'not supported'; - }, - 'vim:reselect-last-selection': h({ - keys: 'gv', - type: 'action', - action: 'reselectLastSelection' - }), - 'vim:join': h({ - keys: 'J', - type: 'action', - action: 'joinLines', - isEdit: true - }), - 'vim:yank': p({ - keys: 'y', - type: 'operator', - operator: 'yank' - }), - 'vim:yank-line': h({ - keys: 'Y', - type: 'operatorMotion', - operator: 'yank', - motion: 'expandToLine', - motionArgs: { - linewise: true - }, - context: 'normal' - }), - 'vim:put-before': h({ - keys: 'P', - type: 'action', - action: 'paste', - isEdit: true, - actionArgs: { - after: false, - isEdit: true - } - }), - 'vim:put-after': h({ - keys: 'p', - type: 'action', - action: 'paste', - isEdit: true, - actionArgs: { - after: true, - isEdit: true - } - }), - 'vim:toggle-case': h({ - keys: 'g~', - type: 'operator', - operator: 'changeCase' - }), - 'vim:upper-case': h({ - keys: 'gU', - type: 'operator', - operator: 'changeCase', - operatorArgs: { - toLower: false - }, - isEdit: true - }), - 'vim:lower-case': h({ - keys: 'gu', - type: 'operator', - operator: 'changeCase', - operatorArgs: { - toLower: true - }, - isEdit: true - }), - 'vim:toggle-case-now': h({ - keys: '~', - type: 'operatorMotion', - operator: 'changeCase', - motion: 'moveByCharacters', - motionArgs: { - forward: true - }, - operatorArgs: { - shouldMoveCursor: true - }, - context: 'normal' - }), - 'vim:mark': b({ - keys: 'm', - type: 'action', - action: 'setMark' - }), - 'vim:move-to-mark-literal': b({ - keys: '`', - type: 'motion', - motion: 'goToMark', - motionArgs: { - toJumplist: true - } - }), - 'vim:move-to-mark': b({ - keys: "'", - type: 'motion', - motion: 'goToMark', - motionArgs: { - toJumplist: true, - linewise: true - } - }), - 'vim:find': b({ - keys: 'f', - type: 'motion', - motion: 'moveToCharacter', - motionArgs: { - forward: true, - inclusive: true - } - }), - 'vim:find-backwards': b({ - keys: 'F', - type: 'motion', - motion: 'moveToCharacter', - motionArgs: { - forward: false - } - }), - 'vim:till': b({ - keys: 't', - type: 'motion', - motion: 'moveTillCharacter', - motionArgs: { - forward: true, - inclusive: true - } - }), - 'vim:till-backwards': b({ - keys: 'T', - type: 'motion', - motion: 'moveTillCharacter', - motionArgs: { - forward: false - } - }), - 'vim:repeat-find': h({ - keys: ';', - type: 'motion', - motion: 'repeatLastCharacterSearch', - motionArgs: { - forward: true - } - }), - 'vim:repeat-find-reverse': h({ - keys: ',', - type: 'motion', - motion: 'repeatLastCharacterSearch', - motionArgs: { - forward: false - } - }), - 'vim:search': h({ - keys: '/', - type: 'search', - searchArgs: { - forward: true, - querySrc: 'prompt', - toJumplist: true - } - }), - 'vim:reverse-search': h({ - keys: '?', - type: 'search', - searchArgs: { - forward: false, - querySrc: 'prompt', - toJumplist: true - } - }), - 'vim:search-current-word': h({ - keys: '*', - type: 'search', - searchArgs: { - forward: true, - querySrc: 'wordUnderCursor', - wholeWordOnly: true, - toJumplist: true - } - }), - 'vim:reverse-search-current-word': h({ - keys: '#', - type: 'search', - searchArgs: { - forward: false, - querySrc: 'wordUnderCursor', - wholeWordOnly: true, - toJumplist: true - } - }), - 'vim:repeat-search': h({ - keys: 'n', - type: 'motion', - motion: 'findNext', - motionArgs: { - forward: true, - toJumplist: true - } - }), - 'vim:repeat-search-backwards': h({ - keys: 'N', - type: 'motion', - motion: 'findNext', - motionArgs: { - forward: false, - toJumplist: true - } - }), - 'vim:bracket-matching-motion': h({ - keys: '%', - type: 'motion', - motion: 'moveToMatchedSymbol', - motionArgs: { - inclusive: true, - toJumplist: true - } - }), - 'vim:ex-command': h({ - keys: ':', - type: 'ex' - }), - // normal mode - 'vim:activate-insert-mode': h({ - keys: 'i', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - insertAt: 'inplace' - }, - context: 'normal' - }), - 'vim:activate-replace-mode': h({ - keys: 'R', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - replace: true - } - }), - 'vim:activate-characterwise-visual-mode': h({ - keys: 'v', - type: 'action', - action: 'toggleVisualMode' - }), - 'vim:activate-linewise-visual-mode': h({ - keys: 'V', - type: 'action', - action: 'toggleVisualMode', - actionArgs: { - linewise: true - } - }), - 'vim:activate-blockwise-visual-mode': h({ - keys: '', - type: 'action', - action: 'toggleVisualMode', - actionArgs: { - blockwise: true - } - }), - 'vim:undo': h({ - keys: 'u', - type: 'action', - action: 'undo', - context: 'normal' - }), - 'vim:insert-above-with-newline': h({ - keys: 'O', - type: 'action', - action: 'newLineAndEnterInsertMode', - isEdit: true, - interlaceInsertRepeat: true, - actionArgs: { - after: false - }, - context: 'normal' - }), - 'vim:insert-below-with-newline': h({ - keys: 'o', - type: 'action', - action: 'newLineAndEnterInsertMode', - isEdit: true, - interlaceInsertRepeat: true, - actionArgs: { - after: true - }, - context: 'normal' - }), - 'vim:insert-after': h({ - keys: 'a', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - insertAt: 'charAfter' - }, - context: 'normal' - }), - 'vim:insert-after-end-of-line': h({ - keys: 'A', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - insertAt: 'eol' - }, - context: 'normal' - }), - 'vim:delete-right': h({ - keys: 'x', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveByCharacters', - motionArgs: { - forward: true - }, - operatorMotionArgs: { - visualLine: false - } - }), - 'vim:delete-left': h({ - keys: 'X', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveByCharacters', - motionArgs: { - forward: false - }, - operatorMotionArgs: { - visualLine: true - } - }), - 'vim:substitute': h({ - keys: 's', - type: 'keyToKey', - toKeys: 'cl', - context: 'normal' - }), - 'vim:substitute-visual': h({ - keys: 's', - type: 'keyToKey', - toKeys: 'c', - context: 'visual' - }), - 'vim:repeat': h({ - keys: '.', - type: 'action', - action: 'repeatLastEdit' - }), - 'vim:increase': h({ - keys: '', - type: 'action', - action: 'incrementNumberToken', - isEdit: true, - actionArgs: { - increase: true, - backtrack: false - } - }), - 'vim:decrease': h({ - keys: '', - type: 'action', - action: 'incrementNumberToken', - isEdit: true, - actionArgs: { - increase: false, - backtrack: false - } - }), - 'vim:register-prefix': b({ - keys: '"', - type: 'action', - action: 'setRegister' - }), - // insert mode - 'vim:delete-to-beginning-of-word': h({ - keys: '', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveByWords', - motionArgs: { - forward: false, - wordEnd: false - }, - context: 'insert' - }), - // visual mode - 'vim:insert-at-start-of-target': h({ - keys: 'I', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - insertAt: 'startOfSelectedArea' - }, - context: 'visual' - }), - 'vim:insert-at-end-of-target': h({ - keys: 'A', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { - insertAt: 'endOfSelectedArea' - }, - context: 'visual' - }), - 'vim:reverse-selections': h({ - keys: 'o', - type: 'motion', - motion: 'moveToOtherHighlightedEnd', - context: 'visual' - }), - 'vim:reverse-selections-at-same-line': h({ - keys: 'O', - type: 'motion', - motion: 'moveToOtherHighlightedEnd', - motionArgs: { - sameLine: true - }, - context: 'visual' - }) - }; - disposables.add(inkdrop.commands.add(wrapper, handlers)); - disposables.add(inkdrop.commands.add(document.querySelector('.mde-preview'), { - 'vim:move-to-start-of-file': ({ - target - }) => { - target.scrollTop = 0; - }, - 'vim:scroll-up': ({ - target - }) => { - target.scrollTop -= 30; - }, - 'vim:scroll-down': ({ - target - }) => { - target.scrollTop += 30; - }, - 'vim:scroll-half-screen-up': ({ - target - }) => { - target.scrollTop -= target.clientHeight / 2; - }, - 'vim:scroll-half-screen-down': ({ - target - }) => { - target.scrollTop += target.clientHeight / 2; - }, - 'vim:scroll-full-screen-up': ({ - target - }) => { - target.scrollTop -= target.clientHeight; - }, - 'vim:scroll-full-screen-down': ({ - target - }) => { - target.scrollTop += target.clientHeight; - }, - 'vim:move-to-line': ({ - target - }) => { - target.scrollTop = target.scrollHeight; - } - })); - wrapper.addEventListener('textInput', this.handleEditorTextInput); - wrapper.addEventListener('keydown', this.handleEditorKeyDown); - disposables.add(new _eventKit.Disposable(() => wrapper.removeEventListener('keydown', this.handleEditorKeyDown))); - this.disposables = disposables; - } - registerExCommands() { - const el = this.getCodeMirror().getWrapperElement(); - this.vim.defineEx('write', 'w', () => { - inkdrop.commands.dispatch(el, 'core:save-note'); - }); - this.vim.defineEx('next', 'n', () => { - inkdrop.commands.dispatch(el, 'core:open-next-note'); - }); - this.vim.defineEx('prev', '', () => { - inkdrop.commands.dispatch(el, 'core:open-prev-note'); - }); - this.vim.defineEx('preview', 'p', () => { - inkdrop.commands.dispatch(el, 'view:toggle-preview'); - }); - this.vim.defineEx('side-by-side', 'side', () => { - inkdrop.commands.dispatch(el, 'view:toggle-side-by-side'); - }); - } - getCodeMirror() { - return inkdrop.getActiveEditor().cm; - } - yankClipboard() { - const state = this.vim.getVimGlobalState(); - const text = _electron.clipboard.readText(); - const linewise = text.indexOf('\n') >= 0; - state.registerController.pushText('0', 'yank', text, linewise, true); - } -} -module.exports = new Plugin(); \ No newline at end of file diff --git a/lib/vim.js.map b/lib/vim.js.map deleted file mode 100644 index 55cb7d4..0000000 --- a/lib/vim.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"vim.js","names":["Plugin","editor","activateMode","event","_opt","logger","debug","mode","cm","getCodeMirror","getWrapperElement","classList","remove","add","isInsertMode","isTrusted","text","data","replaceSelection","keyName","normalizeKeyName","key","vim","maybeInitVimState","isNumeric","ctrlKey","altKey","metaKey","shiftKey","match","target","getInputField","currentKeyStroke","inkdrop","keymaps","queuedKeystrokes","filter","k","startsWith","partialMatchCandidates","exactMatchCandidates","findMatchCandidates","partialMatches","findPartialMatches","exactMatches","findExactMatches","isBufferingKey","b","webkitMatchesSelector","inputState","hasOperatorOrMotion","motion","operator","length","selectedCharacter","keyBuffer","pendingCommand","stopBufferingKey","stopPropagation","preventDefault","pushRepeatDigit","keys","keysMatcher","exec","_event","yankClipboard","activate","CodeMirror","isEditorActive","getActiveEditor","onEditorLoad","handleEditorLoad","deactivate","disposables","dispose","deactivateMode","originalKeyMap","getOption","setOption","on","handleVimModeChange","handleFocusEditor","el","registerCommands","registerExCommands","off","startBufferingKey","command","customBufferingModeClass","wrapper","classes","Array","prototype","slice","apply","i","undefined","contains","bufferKey","vimKey","cmKeyToVimKey","CompositeDisposable","doKeyToKey","toKeys","substring","index","handleEditorKeyDown","KeyboardEvent","bindings","document","activeElement","commands","dispatch","h","e","Object","assign","state","operation","curOp","isVimOp","type","commandDispatcher","processCommand","Vim","suppressErrorLogging","console","error","originalEvent","p","visualMode","keyBinding","findKeyBindings","keystrokes","handlers","clearInputState","exitVisualMode","exitInsertMode","motionArgs","forward","cur","getCursor","line","ch","body","linewise","wordEnd","bigWord","inclusive","toJumplist","handler","getRepeat","toFirstChar","repeatOffset","explicitRepeat","action","actionArgs","position","context","isEdit","insertAt","textObjectInner","operatorArgs","indentRight","after","toLower","shouldMoveCursor","searchArgs","querySrc","wholeWordOnly","replace","blockwise","interlaceInsertRepeat","operatorMotionArgs","visualLine","increase","backtrack","sameLine","querySelector","scrollTop","clientHeight","scrollHeight","addEventListener","handleEditorTextInput","Disposable","removeEventListener","defineEx","getVimGlobalState","clipboard","readText","indexOf","registerController","pushText","module","exports"],"sources":["../src/vim.js"],"sourcesContent":["import { logger } from 'inkdrop'\nimport vimKeymap from './keymap'\nimport { CompositeDisposable, Disposable } from 'event-kit'\nimport CodeMirror from 'codemirror'\nimport { clipboard } from 'electron'\n\nclass Plugin {\n activate() {\n this.vim = vimKeymap(CodeMirror)\n if (inkdrop.isEditorActive()) {\n this.activateMode(inkdrop.getActiveEditor())\n }\n inkdrop.onEditorLoad(this.handleEditorLoad)\n }\n\n deactivate() {\n if (this.disposables) {\n this.disposables.dispose()\n }\n if (inkdrop.isEditorActive()) {\n this.deactivateMode(inkdrop.getActiveEditor())\n }\n }\n\n activateMode(editor) {\n const { cm } = editor\n this.originalKeyMap = cm.getOption('keyMap')\n cm.setOption('keyMap', 'vim')\n cm.on('vim-mode-change', this.handleVimModeChange)\n cm.on('focus', this.handleFocusEditor)\n\n const el = cm.getWrapperElement()\n el.classList.add('vim-mode', 'normal-mode')\n\n this.registerCommands()\n this.registerExCommands()\n }\n\n deactivateMode(editor) {\n const { cm } = editor\n if (cm && this.originalKeyMap) {\n cm.setOption('keyMap', this.originalKeyMap)\n cm.off('vim-mode-change', this.handleVimModeChange)\n const el = cm.getWrapperElement()\n el.classList.remove('vim-mode')\n }\n }\n\n normalizeKeyName(key) {\n switch (key) {\n case 'Enter':\n return 'enter'\n case ' ':\n return 'space'\n case 'ArrowRight':\n return 'right'\n case 'ArrowLeft':\n return 'left'\n case 'ArrowUp':\n return 'up'\n case 'ArrowDown':\n return 'down'\n default:\n if (key.match(/^[A-Z]$/)) {\n return `shift-${key}`\n }\n return key\n }\n }\n\n startBufferingKey(command, customBufferingModeClass) {\n const wrapper = this.getCodeMirror().getWrapperElement()\n logger.debug('Start key buffering')\n wrapper.classList.add('key-buffering')\n if (customBufferingModeClass) {\n wrapper.classList.add('key-buffering-' + customBufferingModeClass)\n }\n this.pendingCommand = command\n }\n\n stopBufferingKey() {\n logger.debug('Stop key buffering')\n const wrapper = this.getCodeMirror().getWrapperElement()\n const classes = Array.prototype.slice.apply(wrapper.classList)\n for (const i of classes) {\n if (i.startsWith('key-buffering')) {\n wrapper.classList.remove(i)\n }\n }\n this.pendingCommand = undefined\n }\n\n isBufferingKey() {\n const wrapper = this.getCodeMirror().getWrapperElement()\n return wrapper.classList.contains('key-buffering')\n }\n\n bufferKey(key) {\n const cm = this.getCodeMirror()\n const vim = this.vim.maybeInitVimState(cm)\n const vimKey = this.vim.cmKeyToVimKey(\"'\" + key + \"'\")\n vim.inputState.keyBuffer = vim.inputState.keyBuffer + vimKey\n logger.debug('keyBuffer:', vim.inputState.keyBuffer, vim.inputState)\n }\n\n isInsertMode() {\n const wrapper = this.getCodeMirror().getWrapperElement()\n return wrapper.classList.contains('insert-mode')\n }\n\n registerCommands() {\n const disposables = new CompositeDisposable()\n const editor = inkdrop.getActiveEditor()\n const { cm } = editor\n const wrapper = cm.getWrapperElement()\n\n const doKeyToKey = async command => {\n logger.debug('doKeyToKey:', command)\n let keys = command.toKeys\n while (keys) {\n // Pull off one command key, which is either a single character\n // or a special sequence wrapped in '<' and '>', e.g. ''.\n const match = /<\\w+-.+?>|<\\w+>|./.exec(keys)\n let key = match[0]\n logger.debug('key:', key)\n keys = keys.substring(match.index + key.length)\n\n if (this.isBufferingKey()) {\n this.handleEditorKeyDown(new KeyboardEvent('keydown', { key }))\n } else {\n if (key.match(/^[A-Z]$/)) {\n key = 'shift-' + key\n }\n const { exactMatchCandidates } = inkdrop.keymaps.findMatchCandidates([\n key\n ])\n logger.debug('exactMatchCandidates:', exactMatchCandidates)\n const bindings = inkdrop.keymaps.findExactMatches(\n exactMatchCandidates,\n document.activeElement\n )\n const b = bindings[0]\n if (b) {\n inkdrop.commands.dispatch(document.activeElement, b.command)\n } else {\n logger.debug('command not found for key:', key)\n }\n }\n }\n }\n\n // bind key to command\n const h = command => {\n return e => {\n logger.debug(\n 'command:',\n command,\n 'state:',\n Object.assign({}, cm.state.vim.inputState)\n )\n e.stopPropagation()\n const vim = this.vim.maybeInitVimState(cm)\n return cm.operation(() => {\n cm.curOp.isVimOp = true\n try {\n if (command.type === 'keyToKey') {\n doKeyToKey(command)\n } else {\n this.vim.commandDispatcher.processCommand(cm, vim, command)\n }\n } catch (e) {\n // clear VIM state in case it's in a bad state.\n cm.state.vim = undefined\n this.vim.maybeInitVimState(cm)\n if (!CodeMirror.Vim.suppressErrorLogging) {\n console.error(e)\n }\n throw e\n }\n return true\n })\n }\n }\n // bind keystroke to command\n const b = command => {\n return e => {\n logger.debug(\n 'buffer command:',\n command,\n 'state:',\n Object.assign({}, cm.state.vim.inputState),\n e.originalEvent\n )\n this.startBufferingKey(h(command), 'command')\n this.bufferKey(e.originalEvent.key)\n }\n }\n // bind keystroke to operator\n const p = command => {\n return e => {\n logger.debug(\n 'operator command:',\n command,\n 'state:',\n Object.assign({}, cm.state.vim.inputState),\n e.originalEvent,\n e\n )\n const vim = this.vim.maybeInitVimState(cm)\n if (\n !vim.inputState.operator &&\n !this.isBufferingKey() &&\n !vim.visualMode\n ) {\n this.startBufferingKey(e => {\n const el = cm.getInputField()\n const keyName = this.normalizeKeyName(e.key)\n const keyBinding = inkdrop.keymaps.findKeyBindings({\n keystrokes: keyName,\n target: el\n })\n if (keyBinding.length > 0) {\n inkdrop.commands.dispatch(el, keyBinding[0].command)\n return true\n } else {\n return false\n }\n }, 'operator')\n if (e.originalEvent) {\n this.bufferKey(e.originalEvent.key)\n } else {\n logger.debug('buffer key:', command.keys)\n this.bufferKey(command.keys)\n }\n }\n return h(command)(e)\n }\n }\n const handlers = {\n 'vim:native!': () => {},\n 'vim:reset-normal-mode': e => {\n CodeMirror.Vim.clearInputState(cm)\n this.stopBufferingKey()\n e.stopPropagation()\n },\n 'vim:exit-visual-mode': e => {\n logger.debug('exit-visual-mode')\n CodeMirror.Vim.clearInputState(cm)\n CodeMirror.Vim.exitVisualMode(cm)\n this.stopBufferingKey()\n e.stopPropagation()\n },\n 'vim:exit-insert-mode': e => {\n logger.debug('exit-insert-mode')\n CodeMirror.Vim.clearInputState(cm)\n CodeMirror.Vim.exitInsertMode(cm)\n this.stopBufferingKey()\n e.stopPropagation()\n },\n 'vim:move-left': h({\n keys: 'h',\n type: 'motion',\n motion: 'moveByCharacters',\n motionArgs: { forward: false }\n }),\n 'vim:move-right': h({\n keys: 'l',\n type: 'motion',\n motion: 'moveByCharacters',\n motionArgs: { forward: true }\n }),\n 'vim:move-up': (command => {\n return e => {\n const cur = cm.getCursor()\n if (cur.line === 0 && cur.ch === 0) {\n e.stopPropagation()\n inkdrop.commands.dispatch(document.body, 'editor:title:focus')\n } else {\n command(e)\n }\n }\n })(\n h({\n keys: 'k',\n type: 'motion',\n motion: 'moveByLines',\n motionArgs: { forward: false, linewise: true }\n })\n ),\n 'vim:move-down': h({\n keys: 'j',\n type: 'motion',\n motion: 'moveByLines',\n motionArgs: { forward: true, linewise: true }\n }),\n 'vim:move-up-by-display-lines': h({\n keys: 'gk',\n type: 'motion',\n motion: 'moveByDisplayLines',\n motionArgs: { forward: false }\n }),\n 'vim:move-down-by-display-lines': h({\n keys: 'gj',\n type: 'motion',\n motion: 'moveByDisplayLines',\n motionArgs: { forward: true }\n }),\n\n 'vim:move-to-next-word': h({\n keys: 'w',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: { forward: true, wordEnd: false }\n }),\n 'vim:move-to-next-whole-word': h({\n keys: 'W',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: { forward: true, wordEnd: false, bigWord: true }\n }),\n 'vim:move-to-end-of-word': h({\n keys: 'e',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: { forward: true, wordEnd: true, inclusive: true }\n }),\n 'vim:move-to-previous-end-of-word': h({\n keys: 'ge',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: { forward: false, wordEnd: true, inclusive: true }\n }),\n 'vim:move-to-end-of-whole-word': h({\n keys: 'E',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: {\n forward: true,\n wordEnd: true,\n bigWord: true,\n inclusive: true\n }\n }),\n 'vim:move-to-previous-end-of-whole-word': h({\n keys: 'gE',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: {\n forward: false,\n wordEnd: true,\n bigWord: true,\n inclusive: true\n }\n }),\n 'vim:move-to-previous-word': h({\n keys: 'b',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: { forward: false, wordEnd: false }\n }),\n 'vim:move-to-previous-whole-word': h({\n keys: 'B',\n type: 'motion',\n motion: 'moveByWords',\n motionArgs: { forward: false, wordEnd: false, bigWord: true }\n }),\n 'vim:move-to-next-paragraph': h({\n keys: '}',\n type: 'motion',\n motion: 'moveByParagraph',\n motionArgs: { forward: true, toJumplist: true }\n }),\n 'vim:move-to-previous-paragraph': h({\n keys: '{',\n type: 'motion',\n motion: 'moveByParagraph',\n motionArgs: { forward: false, toJumplist: true }\n }),\n 'vim:move-to-beginning-of-line-with-zero': (() => {\n const handler = h({\n keys: '0',\n type: 'motion',\n motion: 'moveToStartOfLine'\n })\n return e => {\n const vim = this.vim.maybeInitVimState(cm)\n if (vim.inputState.getRepeat() > 0) {\n vim.inputState.pushRepeatDigit('0')\n } else {\n return handler(e)\n }\n }\n })(),\n 'vim:move-to-beginning-of-line': h({\n keys: '0',\n type: 'motion',\n motion: 'moveToStartOfLine'\n }),\n 'vim:move-to-first-character-of-line': h({\n keys: '^',\n type: 'motion',\n motion: 'moveToFirstNonWhiteSpaceCharacter'\n }),\n 'vim:move-to-first-character-of-line-and-down': h({\n keys: '_',\n type: 'motion',\n motion: 'moveByLines',\n motionArgs: { forward: true, toFirstChar: true, repeatOffset: -1 }\n }),\n 'vim:move-to-last-character-of-line': h({\n keys: '$',\n type: 'motion',\n motion: 'moveToEol',\n motionArgs: { inclusive: true }\n }),\n 'vim:move-to-last-nonblank-character-of-line-and-down': () => {\n '???'\n },\n 'vim:move-to-first-character-of-line-up': h({\n keys: '-',\n type: 'motion',\n motion: 'moveByLines',\n motionArgs: { forward: false, toFirstChar: true }\n }),\n 'vim:move-to-first-character-of-line-down': h({\n keys: '+',\n type: 'motion',\n motion: 'moveByLines',\n motionArgs: { forward: true, toFirstChar: true }\n }),\n\n 'vim:move-to-start-of-file': h({\n keys: 'gg',\n type: 'motion',\n motion: 'moveToLineOrEdgeOfDocument',\n motionArgs: {\n forward: false,\n explicitRepeat: true,\n linewise: true,\n toJumplist: true\n }\n }),\n 'vim:scroll-half-screen-up': h({\n keys: '',\n type: 'motion',\n motion: 'moveByScroll',\n motionArgs: { forward: false, explicitRepeat: true }\n }),\n 'vim:scroll-full-screen-up': h({\n keys: '',\n type: 'motion',\n motion: 'moveByPage',\n motionArgs: { forward: false }\n }),\n 'vim:scroll-half-screen-down': h({\n keys: '',\n type: 'motion',\n motion: 'moveByScroll',\n motionArgs: { forward: true, explicitRepeat: true }\n }),\n 'vim:scroll-full-screen-down': h({\n keys: '',\n type: 'motion',\n motion: 'moveByPage',\n motionArgs: { forward: true }\n }),\n 'vim:scroll-down': h({\n keys: '',\n type: 'action',\n action: 'scroll',\n actionArgs: { forward: true, linewise: true }\n }),\n 'vim:scroll-up': h({\n keys: '',\n type: 'action',\n action: 'scroll',\n actionArgs: { forward: false, linewise: true }\n }),\n 'vim:scroll-cursor-to-top': h({\n keys: 'z',\n type: 'action',\n action: 'scrollToCursor',\n actionArgs: { position: 'top' },\n motion: 'moveToFirstNonWhiteSpaceCharacter'\n }),\n 'vim:scroll-cursor-to-top-leave': h({\n keys: 'zt',\n type: 'action',\n action: 'scrollToCursor',\n actionArgs: { position: 'top' }\n }),\n 'vim:scroll-cursor-to-middle': h({\n keys: 'z.',\n type: 'action',\n action: 'scrollToCursor',\n actionArgs: { position: 'center' },\n motion: 'moveToFirstNonWhiteSpaceCharacter'\n }),\n 'vim:scroll-cursor-to-middle-leave': h({\n keys: 'zz',\n type: 'action',\n action: 'scrollToCursor',\n actionArgs: { position: 'center' }\n }),\n 'vim:scroll-cursor-to-bottom': h({\n keys: 'z-',\n type: 'action',\n action: 'scrollToCursor',\n actionArgs: { position: 'bottom' }\n }),\n 'vim:scroll-cursor-to-bottom-leave': h({\n keys: 'zb',\n type: 'action',\n action: 'scrollToCursor',\n actionArgs: { position: 'bottom' },\n motion: 'moveToFirstNonWhiteSpaceCharacter'\n }),\n 'vim:move-to-line': h({\n keys: 'G',\n type: 'motion',\n motion: 'moveToLineOrEdgeOfDocument',\n motionArgs: {\n forward: true,\n explicitRepeat: true,\n linewise: true,\n toJumplist: true\n }\n }),\n 'vim:move-to-top-of-screen': h({\n keys: 'H',\n type: 'motion',\n motion: 'moveToTopLine',\n motionArgs: { linewise: true, toJumplist: true }\n }),\n 'vim:move-to-bottom-of-screen': h({\n keys: 'L',\n type: 'motion',\n motion: 'moveToBottomLine',\n motionArgs: { linewise: true, toJumplist: true }\n }),\n 'vim:move-to-middle-of-screen': h({\n keys: 'M',\n type: 'motion',\n motion: 'moveToMiddleLine',\n motionArgs: { linewise: true, toJumplist: true }\n }),\n\n 'vim:delete': p({ keys: 'd', type: 'operator', operator: 'delete' }),\n 'vim:delete-to-last-character-of-line': h({\n keys: 'D',\n type: 'operatorMotion',\n operator: 'delete',\n motion: 'moveToEol',\n motionArgs: { inclusive: true },\n context: 'normal'\n }),\n 'vim:change': p({ keys: 'c', type: 'operator', operator: 'change' }),\n 'vim:change-to-last-character-of-line': h({\n keys: 'C',\n type: 'operatorMotion',\n operator: 'change',\n motion: 'moveToEol',\n motionArgs: { inclusive: true },\n context: 'normal'\n }),\n 'vim:substitute-line': h({\n keys: 'S',\n type: 'keyToKey',\n toKeys: 'cc',\n context: 'normal'\n }),\n 'vim:substitute-line-visual': h({\n keys: 'S',\n type: 'keyToKey',\n toKeys: 'VdO',\n context: 'visual'\n }),\n 'vim:replace': b({\n keys: 'r',\n type: 'action',\n action: 'replace',\n isEdit: true\n }),\n 'vim:insert-at-beginning-of-line': h({\n keys: 'I',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { insertAt: 'firstNonBlank' },\n context: 'normal'\n }),\n 'vim:text-object-manipulation-inner': b({\n keys: 'i',\n type: 'motion',\n motion: 'textObjectManipulation',\n motionArgs: { textObjectInner: true }\n }),\n 'vim:text-object-manipulation': b({\n keys: 'a',\n type: 'motion',\n motion: 'textObjectManipulation'\n }),\n 'vim:indent': p({\n keys: '>',\n type: 'operator',\n operator: 'indent',\n operatorArgs: { indentRight: true }\n }),\n 'vim:outdent': p({\n keys: '<',\n type: 'operator',\n operator: 'indent',\n operatorArgs: { indentRight: false }\n }),\n 'vim:auto-indent': () => {\n 'not supported'\n },\n 'vim:reselect-last-selection': h({\n keys: 'gv',\n type: 'action',\n action: 'reselectLastSelection'\n }),\n 'vim:join': h({\n keys: 'J',\n type: 'action',\n action: 'joinLines',\n isEdit: true\n }),\n\n 'vim:yank': p({ keys: 'y', type: 'operator', operator: 'yank' }),\n 'vim:yank-line': h({\n keys: 'Y',\n type: 'operatorMotion',\n operator: 'yank',\n motion: 'expandToLine',\n motionArgs: { linewise: true },\n context: 'normal'\n }),\n 'vim:put-before': h({\n keys: 'P',\n type: 'action',\n action: 'paste',\n isEdit: true,\n actionArgs: { after: false, isEdit: true }\n }),\n 'vim:put-after': h({\n keys: 'p',\n type: 'action',\n action: 'paste',\n isEdit: true,\n actionArgs: { after: true, isEdit: true }\n }),\n\n 'vim:toggle-case': h({\n keys: 'g~',\n type: 'operator',\n operator: 'changeCase'\n }),\n 'vim:upper-case': h({\n keys: 'gU',\n type: 'operator',\n operator: 'changeCase',\n operatorArgs: { toLower: false },\n isEdit: true\n }),\n 'vim:lower-case': h({\n keys: 'gu',\n type: 'operator',\n operator: 'changeCase',\n operatorArgs: { toLower: true },\n isEdit: true\n }),\n 'vim:toggle-case-now': h({\n keys: '~',\n type: 'operatorMotion',\n operator: 'changeCase',\n motion: 'moveByCharacters',\n motionArgs: { forward: true },\n operatorArgs: { shouldMoveCursor: true },\n context: 'normal'\n }),\n\n 'vim:mark': b({\n keys: 'm',\n type: 'action',\n action: 'setMark'\n }),\n 'vim:move-to-mark-literal': b({\n keys: '`',\n type: 'motion',\n motion: 'goToMark',\n motionArgs: { toJumplist: true }\n }),\n 'vim:move-to-mark': b({\n keys: \"'\",\n type: 'motion',\n motion: 'goToMark',\n motionArgs: { toJumplist: true, linewise: true }\n }),\n\n 'vim:find': b({\n keys: 'f',\n type: 'motion',\n motion: 'moveToCharacter',\n motionArgs: { forward: true, inclusive: true }\n }),\n 'vim:find-backwards': b({\n keys: 'F',\n type: 'motion',\n motion: 'moveToCharacter',\n motionArgs: { forward: false }\n }),\n 'vim:till': b({\n keys: 't',\n type: 'motion',\n motion: 'moveTillCharacter',\n motionArgs: { forward: true, inclusive: true }\n }),\n 'vim:till-backwards': b({\n keys: 'T',\n type: 'motion',\n motion: 'moveTillCharacter',\n motionArgs: { forward: false }\n }),\n 'vim:repeat-find': h({\n keys: ';',\n type: 'motion',\n motion: 'repeatLastCharacterSearch',\n motionArgs: { forward: true }\n }),\n 'vim:repeat-find-reverse': h({\n keys: ',',\n type: 'motion',\n motion: 'repeatLastCharacterSearch',\n motionArgs: { forward: false }\n }),\n\n 'vim:search': h({\n keys: '/',\n type: 'search',\n searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }\n }),\n 'vim:reverse-search': h({\n keys: '?',\n type: 'search',\n searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }\n }),\n 'vim:search-current-word': h({\n keys: '*',\n type: 'search',\n searchArgs: {\n forward: true,\n querySrc: 'wordUnderCursor',\n wholeWordOnly: true,\n toJumplist: true\n }\n }),\n 'vim:reverse-search-current-word': h({\n keys: '#',\n type: 'search',\n searchArgs: {\n forward: false,\n querySrc: 'wordUnderCursor',\n wholeWordOnly: true,\n toJumplist: true\n }\n }),\n 'vim:repeat-search': h({\n keys: 'n',\n type: 'motion',\n motion: 'findNext',\n motionArgs: { forward: true, toJumplist: true }\n }),\n 'vim:repeat-search-backwards': h({\n keys: 'N',\n type: 'motion',\n motion: 'findNext',\n motionArgs: { forward: false, toJumplist: true }\n }),\n\n 'vim:bracket-matching-motion': h({\n keys: '%',\n type: 'motion',\n motion: 'moveToMatchedSymbol',\n motionArgs: { inclusive: true, toJumplist: true }\n }),\n\n 'vim:ex-command': h({ keys: ':', type: 'ex' }),\n\n // normal mode\n 'vim:activate-insert-mode': h({\n keys: 'i',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { insertAt: 'inplace' },\n context: 'normal'\n }),\n 'vim:activate-replace-mode': h({\n keys: 'R',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { replace: true }\n }),\n 'vim:activate-characterwise-visual-mode': h({\n keys: 'v',\n type: 'action',\n action: 'toggleVisualMode'\n }),\n 'vim:activate-linewise-visual-mode': h({\n keys: 'V',\n type: 'action',\n action: 'toggleVisualMode',\n actionArgs: { linewise: true }\n }),\n 'vim:activate-blockwise-visual-mode': h({\n keys: '',\n type: 'action',\n action: 'toggleVisualMode',\n actionArgs: { blockwise: true }\n }),\n\n 'vim:undo': h({\n keys: 'u',\n type: 'action',\n action: 'undo',\n context: 'normal'\n }),\n\n 'vim:insert-above-with-newline': h({\n keys: 'O',\n type: 'action',\n action: 'newLineAndEnterInsertMode',\n isEdit: true,\n interlaceInsertRepeat: true,\n actionArgs: { after: false },\n context: 'normal'\n }),\n 'vim:insert-below-with-newline': h({\n keys: 'o',\n type: 'action',\n action: 'newLineAndEnterInsertMode',\n isEdit: true,\n interlaceInsertRepeat: true,\n actionArgs: { after: true },\n context: 'normal'\n }),\n 'vim:insert-after': h({\n keys: 'a',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { insertAt: 'charAfter' },\n context: 'normal'\n }),\n 'vim:insert-after-end-of-line': h({\n keys: 'A',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { insertAt: 'eol' },\n context: 'normal'\n }),\n 'vim:delete-right': h({\n keys: 'x',\n type: 'operatorMotion',\n operator: 'delete',\n motion: 'moveByCharacters',\n motionArgs: { forward: true },\n operatorMotionArgs: { visualLine: false }\n }),\n 'vim:delete-left': h({\n keys: 'X',\n type: 'operatorMotion',\n operator: 'delete',\n motion: 'moveByCharacters',\n motionArgs: { forward: false },\n operatorMotionArgs: { visualLine: true }\n }),\n 'vim:substitute': h({\n keys: 's',\n type: 'keyToKey',\n toKeys: 'cl',\n context: 'normal'\n }),\n 'vim:substitute-visual': h({\n keys: 's',\n type: 'keyToKey',\n toKeys: 'c',\n context: 'visual'\n }),\n 'vim:repeat': h({\n keys: '.',\n type: 'action',\n action: 'repeatLastEdit'\n }),\n\n 'vim:increase': h({\n keys: '',\n type: 'action',\n action: 'incrementNumberToken',\n isEdit: true,\n actionArgs: { increase: true, backtrack: false }\n }),\n 'vim:decrease': h({\n keys: '',\n type: 'action',\n action: 'incrementNumberToken',\n isEdit: true,\n actionArgs: { increase: false, backtrack: false }\n }),\n\n 'vim:register-prefix': b({\n keys: '\"',\n type: 'action',\n action: 'setRegister'\n }),\n\n // insert mode\n 'vim:delete-to-beginning-of-word': h({\n keys: '',\n type: 'operatorMotion',\n operator: 'delete',\n motion: 'moveByWords',\n motionArgs: { forward: false, wordEnd: false },\n context: 'insert'\n }),\n\n // visual mode\n 'vim:insert-at-start-of-target': h({\n keys: 'I',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { insertAt: 'startOfSelectedArea' },\n context: 'visual'\n }),\n 'vim:insert-at-end-of-target': h({\n keys: 'A',\n type: 'action',\n action: 'enterInsertMode',\n isEdit: true,\n actionArgs: { insertAt: 'endOfSelectedArea' },\n context: 'visual'\n }),\n 'vim:reverse-selections': h({\n keys: 'o',\n type: 'motion',\n motion: 'moveToOtherHighlightedEnd',\n context: 'visual'\n }),\n 'vim:reverse-selections-at-same-line': h({\n keys: 'O',\n type: 'motion',\n motion: 'moveToOtherHighlightedEnd',\n motionArgs: { sameLine: true },\n context: 'visual'\n })\n }\n disposables.add(inkdrop.commands.add(wrapper, handlers))\n disposables.add(\n inkdrop.commands.add(document.querySelector('.mde-preview'), {\n 'vim:move-to-start-of-file': ({ target }) => {\n target.scrollTop = 0\n },\n 'vim:scroll-up': ({ target }) => {\n target.scrollTop -= 30\n },\n 'vim:scroll-down': ({ target }) => {\n target.scrollTop += 30\n },\n 'vim:scroll-half-screen-up': ({ target }) => {\n target.scrollTop -= target.clientHeight / 2\n },\n 'vim:scroll-half-screen-down': ({ target }) => {\n target.scrollTop += target.clientHeight / 2\n },\n 'vim:scroll-full-screen-up': ({ target }) => {\n target.scrollTop -= target.clientHeight\n },\n 'vim:scroll-full-screen-down': ({ target }) => {\n target.scrollTop += target.clientHeight\n },\n 'vim:move-to-line': ({ target }) => {\n target.scrollTop = target.scrollHeight\n }\n })\n )\n wrapper.addEventListener('textInput', this.handleEditorTextInput)\n wrapper.addEventListener('keydown', this.handleEditorKeyDown)\n disposables.add(\n new Disposable(() =>\n wrapper.removeEventListener('keydown', this.handleEditorKeyDown)\n )\n )\n\n this.disposables = disposables\n }\n\n registerExCommands() {\n const el = this.getCodeMirror().getWrapperElement()\n this.vim.defineEx('write', 'w', () => {\n inkdrop.commands.dispatch(el, 'core:save-note')\n })\n this.vim.defineEx('next', 'n', () => {\n inkdrop.commands.dispatch(el, 'core:open-next-note')\n })\n this.vim.defineEx('prev', '', () => {\n inkdrop.commands.dispatch(el, 'core:open-prev-note')\n })\n this.vim.defineEx('preview', 'p', () => {\n inkdrop.commands.dispatch(el, 'view:toggle-preview')\n })\n this.vim.defineEx('side-by-side', 'side', () => {\n inkdrop.commands.dispatch(el, 'view:toggle-side-by-side')\n })\n }\n\n getCodeMirror() {\n return inkdrop.getActiveEditor().cm\n }\n\n yankClipboard() {\n const state = this.vim.getVimGlobalState()\n const text = clipboard.readText()\n const linewise = text.indexOf('\\n') >= 0\n state.registerController.pushText('0', 'yank', text, linewise, true)\n }\n\n handleEditorLoad = editor => {\n this.activateMode(editor)\n }\n\n handleVimModeChange = (event, _opt) => {\n logger.debug('vim mode changed:', event)\n const { mode } = event\n const cm = this.getCodeMirror()\n cm.getWrapperElement().classList.remove('insert-mode')\n cm.getWrapperElement().classList.remove('visual-mode')\n cm.getWrapperElement().classList.remove('normal-mode')\n cm.getWrapperElement().classList.remove('replace-mode')\n switch (mode) {\n case 'normal':\n cm.getWrapperElement().classList.add('normal-mode')\n break\n case 'visual':\n cm.getWrapperElement().classList.add('visual-mode')\n break\n case 'replace':\n cm.getWrapperElement().classList.add('replace-mode')\n break\n case 'insert':\n cm.getWrapperElement().classList.add('insert-mode')\n break\n }\n }\n\n handleEditorTextInput = event => {\n // only process if the event is fired via EventTarget.dispatchEvent()\n if (this.isInsertMode() && !event.isTrusted) {\n logger.debug('handle text input:', event)\n const text = event.data\n const cm = this.getCodeMirror()\n cm.replaceSelection(text)\n }\n }\n\n handleEditorKeyDown = event => {\n const keyName = this.normalizeKeyName(event.key)\n const cm = this.getCodeMirror()\n const vim = this.vim.maybeInitVimState(cm)\n const isNumeric =\n !event.ctrlKey &&\n !event.altKey &&\n !event.metaKey &&\n !event.shiftKey &&\n keyName.match(/^\\d$/)\n\n const target = cm.getInputField()\n const currentKeyStroke = [\n ...inkdrop.keymaps.queuedKeystrokes.filter(k => !k.startsWith('^')),\n keyName\n ]\n const { partialMatchCandidates, exactMatchCandidates } =\n inkdrop.keymaps.findMatchCandidates(currentKeyStroke)\n const partialMatches = inkdrop.keymaps.findPartialMatches(\n partialMatchCandidates,\n target\n )\n const exactMatches = inkdrop.keymaps.findExactMatches(\n exactMatchCandidates,\n target\n )\n logger.debug('handleEditorKeyDown: currentKeyStroke:', currentKeyStroke)\n logger.debug('handleEditorKeyDown: exactMatches:', exactMatches)\n logger.debug('handleEditorKeyDown: partialMatches:', partialMatches)\n\n if (this.isBufferingKey()) {\n logger.debug('handleEditorKeyDown: handle key buffering:', keyName, event)\n const b = cm\n .getInputField()\n .webkitMatchesSelector(\n '.CodeMirror.vim-mode:not(.insert-mode) textarea'\n )\n logger.debug('handleEditorKeyDown: keybinding check:', exactMatches, b)\n\n if (\n keyName !== 'Ctrl' &&\n keyName !== 'Alt' &&\n keyName !== 'Shift' &&\n keyName !== 'Meta'\n ) {\n const { inputState } = vim\n const hasOperatorOrMotion = inputState.motion || inputState.operator\n if (\n (event.key.length === 1 || keyName === 'space') &&\n (!isNumeric || !hasOperatorOrMotion)\n ) {\n inputState.selectedCharacter = event.key\n inputState.keyBuffer = ''\n\n if (exactMatches.length === 0 && partialMatches.length === 0) {\n const { pendingCommand } = this\n this.stopBufferingKey()\n\n if (typeof pendingCommand === 'function') {\n if (pendingCommand(event)) {\n event.stopPropagation()\n event.preventDefault()\n }\n }\n }\n } else if (isNumeric) {\n vim.inputState.pushRepeatDigit(keyName)\n }\n }\n } else if (!this.isInsertMode()) {\n if (isNumeric) {\n if (exactMatches.length === 0) {\n vim.inputState.pushRepeatDigit(keyName)\n }\n } else {\n // push key buffer to the repeat digit\n const keys = vim.inputState.keyBuffer\n vim.inputState.keyBuffer = ''\n const keysMatcher = /^(\\d*)(.*)$/.exec(keys)\n if (keysMatcher[1] && keysMatcher[1] !== '0') {\n vim.inputState.pushRepeatDigit(keysMatcher[1])\n }\n }\n }\n }\n\n handleFocusEditor = _event => {\n this.yankClipboard()\n }\n}\n\nmodule.exports = new Plugin()\n"],"mappings":"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"} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 2aab914..32f7171 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,1825 +1,264 @@ { "name": "vim", - "version": "2.2.2", + "version": "3.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vim", - "version": "2.2.0", - "license": "MIT", - "devDependencies": { - "@babel/cli": "^7.16.0", - "@babel/core": "^7.16.0", - "@babel/eslint-parser": "^7.16.3", - "@babel/plugin-proposal-class-properties": "^7.16.0", - "@babel/preset-env": "^7.16.4", - "@babel/preset-react": "^7.16.0", - "eslint": "^8.3.0", - "eslint-config-prettier": "^8.3.0", - "prettier": "^2.5.0" - }, - "engines": { - "inkdrop": "^5.x" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/cli": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.20.7.tgz", - "integrity": "sha512-WylgcELHB66WwQqItxNILsMlaTd8/SO6SgTTjMp4uCI7P4QyH1r3nqgFmO3BfM4AtfniHgFMH3EpYFj/zynBkQ==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.8", - "commander": "^4.0.1", - "convert-source-map": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.2.0", - "make-dir": "^2.1.0", - "slash": "^2.0.0" - }, - "bin": { - "babel": "bin/babel.js", - "babel-external-helpers": "bin/babel-external-helpers.js" - }, - "engines": { - "node": ">=6.9.0" - }, - "optionalDependencies": { - "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", - "chokidar": "^3.4.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.20.10", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz", - "integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", - "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helpers": "^7.20.7", - "@babel/parser": "^7.20.7", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.12", - "@babel/types": "^7.20.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/eslint-parser": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz", - "integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==", - "dev": true, - "dependencies": { - "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || >=14.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.11.0", - "eslint": "^7.5.0 || ^8.0.0" - } - }, - "node_modules/@babel/generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz", - "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", - "dev": true, - "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.12.tgz", - "integrity": "sha512-9OunRkbT0JQcednL0UFvbfXpAsUXiGjUk0a7sN8fUXX7Mue79cUSMjHGDRRi/Vz9vYlpIhLV5fMD5dKoMhhsNQ==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-member-expression-to-functions": "^7.20.7", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/helper-split-export-declaration": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz", - "integrity": "sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.2.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", - "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", - "dev": true, - "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.20.7.tgz", - "integrity": "sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", - "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.10", - "@babel/types": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", - "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", - "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.20.7", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", - "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", - "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", - "dev": true, - "dependencies": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz", - "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==", - "dev": true, - "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", - "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", - "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz", - "integrity": "sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-proposal-optional-chaining": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", - "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.20.7.tgz", - "integrity": "sha512-AveGOoi9DAjUYYuUAG//Ig69GlazLnoyzMw68VCDux+c1tsnnH/OkYcpz/5xzMkEFC6UxjR5Gw1c+iY2wOGVeQ==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", - "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.20.7.tgz", - "integrity": "sha512-T+A7b1kfjtRM51ssoOfS1+wbyCVqorfyZhT99TvxxLMirPShD8CzKMRepMlCBGM5RpHMbn8s+5MMHnPstJH6mQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz", - "integrity": "sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.20.5", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz", - "integrity": "sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", - "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", - "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", - "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.11.tgz", - "integrity": "sha512-tA4N427a7fjf1P0/2I4ScsHGc5jcHPbb30xMbaTke2gxDuWpUfXDuX1FEymJwKk4tuGUvGcejAR6HdZVqmmPyw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.7.tgz", - "integrity": "sha512-LWYbsiXTPKl+oBlXUGlwNlJZetXD5Am+CyBdqhPsDVjM9Jc8jwBJFrKhHf900Kfk2eZG1y9MAG3UNajol7A4VQ==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", - "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/template": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz", - "integrity": "sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", - "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", - "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", - "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", - "dev": true, - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", - "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", - "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", - "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", - "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", - "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.20.11.tgz", - "integrity": "sha512-S8e1f7WQ7cimJQ51JkAaDrEtohVEitXjgCGAS2N8S31Y42E+kWwfSz83LYz57QdBm7q9diARVqanIaH2oVgQnw==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-simple-access": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", - "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", - "dev": true, - "dependencies": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-identifier": "^7.19.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", - "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", - "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.20.5", - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", - "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", - "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz", - "integrity": "sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", - "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", - "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.20.7.tgz", - "integrity": "sha512-Tfq7qqD+tRj3EoDhY00nn2uP2hsRxgYGi5mLQ5TimKav0a9Lrpd4deE+fcLXU8zFYRjlKPHZhpCvfEA6qnBxqQ==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-jsx": "^7.18.6", - "@babel/types": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", - "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", - "dev": true, + "version": "3.0.0", + "license": "MIT", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "@replit/codemirror-vim": "^6.3.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", - "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "devDependencies": { + "eslint": "^9.28.0", + "eslint-config-prettier": "^10.1.5", + "prettier": "^3.5.3" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "inkdrop": "^5.x" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", - "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", - "dev": true, + "node_modules/@codemirror/commands": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.1.tgz", + "integrity": "sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==", + "license": "MIT", + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "regenerator-transform": "^0.15.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.4.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", - "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", - "dev": true, + "node_modules/@codemirror/language": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.0.tgz", + "integrity": "sha512-A7+f++LodNNc1wGgoRDTt78cOwWm9KVezApgjOMp1W4hM0898nsqBXwF+sbePE7ZRcjN7Sa1Z5m2oN27XkmEjQ==", + "license": "MIT", + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.1.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" } }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", - "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", - "dev": true, + "node_modules/@codemirror/search": { + "version": "6.5.11", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.11.tgz", + "integrity": "sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==", + "license": "MIT", + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", - "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", - "dev": true, + "node_modules/@codemirror/state": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", + "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==", + "license": "MIT", + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@marijn/find-cluster-break": "^1.0.0" } }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", - "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", - "dev": true, + "node_modules/@codemirror/view": { + "version": "6.37.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.37.0.tgz", + "integrity": "sha512-ghHIeRGfWB8h9Tc3sMdr7D5zp4sZvlCzG36Xjdh2ymmfAwvSaCJAAsL3HLyLEnHcE953+5Uox1bx5OS+YCW/7Q==", + "license": "MIT", + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@codemirror/state": "^6.5.0", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", - "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", - "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", - "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", - "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "node_modules/@eslint/config-array": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", + "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/preset-env": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", - "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", + "node_modules/@eslint/config-helpers": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", + "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", "dev": true, - "dependencies": { - "@babel/compat-data": "^7.20.1", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-async-generator-functions": "^7.20.1", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.20.2", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.20.0", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.20.2", - "@babel/plugin-transform-classes": "^7.20.2", - "@babel/plugin-transform-computed-properties": "^7.18.9", - "@babel/plugin-transform-destructuring": "^7.20.2", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.9", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.8", - "@babel/plugin-transform-function-name": "^7.18.9", - "@babel/plugin-transform-literals": "^7.18.9", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.19.6", - "@babel/plugin-transform-modules-commonjs": "^7.19.6", - "@babel/plugin-transform-modules-systemjs": "^7.19.6", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.20.1", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.19.0", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.9", - "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.20.2", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "core-js-compat": "^3.25.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "node_modules/@eslint/core": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", + "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" + "@types/json-schema": "^7.0.15" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/preset-react": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz", - "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==", + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-transform-react-display-name": "^7.18.6", - "@babel/plugin-transform-react-jsx": "^7.18.6", - "@babel/plugin-transform-react-jsx-development": "^7.18.6", - "@babel/plugin-transform-react-pure-annotations": "^7.18.6" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/runtime": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", - "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", + "node_modules/@eslint/js": { + "version": "9.28.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", + "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, - "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/traverse": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz", - "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==", + "node_modules/@eslint/plugin-kit": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", + "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "debug": "^4.1.0", - "globals": "^11.1.0" + "@eslint/core": "^0.14.0", + "levn": "^0.4.1" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/types": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": ">=18.18.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", - "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18.18.0" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": ">=18.18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@humanwhocodes/module-importer": { @@ -1835,115 +274,87 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=6.0.0" + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "node_modules/@lezer/common": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz", + "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==", + "license": "MIT", + "peer": true }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, + "node_modules/@lezer/highlight": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", + "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", + "license": "MIT", + "peer": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@lezer/common": "^1.0.0" } }, - "node_modules/@nicolo-ribaudo/chokidar-2": { - "version": "2.1.8-no-fsevents.3", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", - "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", - "dev": true, - "optional": true - }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { - "version": "5.1.1-v1", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", - "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "dev": true, + "node_modules/@lezer/lr": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", + "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", + "license": "MIT", + "peer": true, "dependencies": { - "eslint-scope": "5.1.1" + "@lezer/common": "^1.0.0" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "license": "MIT", + "peer": true + }, + "node_modules/@replit/codemirror-vim": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@replit/codemirror-vim/-/codemirror-vim-6.3.0.tgz", + "integrity": "sha512-aTx931ULAMuJx6xLf7KQDOL7CxD+Sa05FktTDrtLaSy53uj01ll3Zf17JdKsriER248oS55GBzg0CfCTjEneAQ==", + "license": "MIT", + "peerDependencies": { + "@codemirror/commands": "6.x.x", + "@codemirror/language": "6.x.x", + "@codemirror/search": "6.x.x", + "@codemirror/state": "6.x.x", + "@codemirror/view": "6.x.x" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@types/estree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "dev": true, - "engines": { - "node": ">= 8" - } + "license": "MIT" }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } + "license": "MIT" }, "node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1956,6 +367,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -1965,6 +377,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1976,274 +389,61 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "optional": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", - "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-define-polyfill-provider": "^0.3.3", - "semver": "^6.1.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", - "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3", - "core-js-compat": "^3.25.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", - "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "license": "Python-2.0" }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "optional": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001442", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001442.tgz", - "integrity": "sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ] - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "optional": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } + "license": "MIT" }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 6" + "node": ">=6" } }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "node_modules/core-js-compat": { - "version": "3.27.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.27.1.tgz", - "integrity": "sha512-Dg91JFeCDA17FKnneN7oCMz4BkQ4TcffkgHP4OWwp9yx3pi7ubqMDXXSacfNak1PQqjc95skyt+YBLHQJnkJwA==", "dev": true, - "dependencies": { - "browserslist": "^4.21.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } + "license": "MIT" + }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT", + "peer": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2254,12 +454,13 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -2274,150 +475,114 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } + "license": "MIT" }, "node_modules/eslint": { - "version": "8.31.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.31.0.tgz", - "integrity": "sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==", + "version": "9.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz", + "integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint/eslintrc": "^1.4.1", - "@humanwhocodes/config-array": "^0.11.8", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.20.0", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.14.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.28.0", + "@eslint/plugin-kit": "^0.3.1", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", + "eslint-scope": "^8.3.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-prettier": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz", - "integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==", + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", + "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", "dev": true, + "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, "peerDependencies": { "eslint": ">=7.0.0" } }, "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" + "estraverse": "^5.2.0" }, "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/ansi-styles": { @@ -2481,37 +646,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -2524,21 +658,6 @@ "node": ">=10.13.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2561,36 +680,29 @@ } }, "node_modules/espree": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", - "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -2598,20 +710,12 @@ "node": ">=0.10" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -2619,20 +723,12 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -2642,6 +738,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -2650,52 +747,34 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } + "license": "MIT" }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, - "optional": true, + "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=16.0.0" } }, "node_modules/find-up": { @@ -2715,148 +794,55 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "optional": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } + "license": "ISC" }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" - } - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" + "node": ">=18" }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -2877,47 +863,6 @@ "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "optional": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2939,76 +884,39 @@ "node": ">=0.10.0" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/js-sdsl": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", - "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==", "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "license": "ISC" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" + "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -3016,16 +924,14 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" } }, "node_modules/levn": { @@ -3033,6 +939,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -3056,54 +963,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3112,10 +983,11 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -3123,43 +995,19 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/node-releases": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", - "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -3200,6 +1048,7 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -3216,301 +1065,68 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.2.tgz", - "integrity": "sha512-BtRV9BcncDyI2tsuS19zzhzoxD8Dh8LiCx7j7tHzrkz8GFXAexeWFdi22mjE1d16dftH2qNaytVxqiRTGlMfpw==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, + "license": "MIT", "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/punycode": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.2.0.tgz", - "integrity": "sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "optional": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", - "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/regexpu-core": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.2.tgz", - "integrity": "sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsgen": "^0.7.1", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsgen": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz", - "integrity": "sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==", - "dev": true - }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -3523,27 +1139,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, + "license": "MIT", "engines": { "node": ">=8" } @@ -3553,6 +1149,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -3560,63 +1157,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "optional": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } + "node_modules/style-mod": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", + "license": "MIT", + "peer": true }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -3624,98 +1177,29 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist-lint": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT", + "peer": true + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -3727,26 +1211,15 @@ } }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 64ca2e7..6c1d4e3 100644 --- a/package.json +++ b/package.json @@ -1,27 +1,23 @@ { "name": "vim", - "main": "./lib/vim", - "version": "2.2.2", + "main": "./src/vim", + "version": "3.0.0", "description": "vim keybindings", "keywords": [], "repository": "https://github.com/inkdropapp/inkdrop-vim", "license": "MIT", "scripts": { - "build": "babel src/ -d lib/", - "dev": "babel src/ -s -d lib/ --watch" + "lint": "eslint ." }, "engines": { "inkdrop": "^5.x" }, "devDependencies": { - "@babel/cli": "^7.16.0", - "@babel/core": "^7.16.0", - "@babel/eslint-parser": "^7.16.3", - "@babel/plugin-proposal-class-properties": "^7.16.0", - "@babel/preset-env": "^7.16.4", - "@babel/preset-react": "^7.16.0", - "eslint": "^8.3.0", - "eslint-config-prettier": "^8.3.0", - "prettier": "^2.5.0" + "eslint": "^9.28.0", + "eslint-config-prettier": "^10.1.5", + "prettier": "^3.5.3" + }, + "dependencies": { + "@replit/codemirror-vim": "^6.3.0" } } diff --git a/prettier.config.js b/prettier.config.mjs similarity index 76% rename from prettier.config.js rename to prettier.config.mjs index 9f75780..55b2039 100644 --- a/prettier.config.js +++ b/prettier.config.mjs @@ -1,4 +1,4 @@ -const options = { +export default { arrowParens: 'avoid', singleQuote: true, bracketSpacing: true, @@ -7,5 +7,3 @@ const options = { tabWidth: 2, trailingComma: 'none' } - -module.exports = options diff --git a/src/clipboard.js b/src/clipboard.js new file mode 100644 index 0000000..1ea5cb5 --- /dev/null +++ b/src/clipboard.js @@ -0,0 +1,49 @@ +const { vim, Vim } = require('@replit/codemirror-vim') +const { clipboard } = require('electron') +const { EditorView } = require('@codemirror/view') + +Vim.defineOperator('yank', (cm, args, ranges, oldAnchor) => { + const vim = cm.state.vim + const text = cm.getSelection() + const endPos = vim.visualMode + ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor) + : oldAnchor + Vim.getRegisterController().pushText( + args.registerName, + 'yank', + text, + args.linewise, + vim.visualBlock + ) + clipboard.writeText(text) + + return endPos +}) + +const registerClipboardText = () => { + const text = clipboard.readText() + if (text) { + const isLinewise = text.indexOf('\n') >= 0 + Vim.getRegisterController().pushText( + '', + 'yank', + text, + isLinewise, + vim.visualBlock + ) + } +} +const registerClipboardTextOnFocus = () => { + return EditorView.updateListener.of(update => { + if (update.focusChanged) { + if (update.view.hasFocus) { + registerClipboardText() + } + } + }) +} + +module.exports = { + registerClipboardText, + registerClipboardTextOnFocus +} diff --git a/src/keymap.js b/src/keymap.js deleted file mode 100644 index e09f970..0000000 --- a/src/keymap.js +++ /dev/null @@ -1,6446 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Supported keybindings: - * Too many to list. Refer to defaultKeyMap below. - * - * Supported Ex commands: - * Refer to defaultExCommandMap below. - * - * Registers: unnamed, -, a-z, A-Z, 0-9 - * (Does not respect the special case for number registers when delete - * operator is made with these commands: %, (, ), , /, ?, n, N, {, } ) - * TODO: Implement the remaining registers. - * - * Marks: a-z, A-Z, and 0-9 - * TODO: Implement the remaining special marks. They have more complex - * behavior. - * - * Events: - * 'vim-mode-change' - raised on the editor anytime the current mode changes, - * Event object: {mode: "visual", subMode: "linewise"} - * - * Code structure: - * 1. Default keymap - * 2. Variable declarations and short basic helpers - * 3. Instance (External API) implementation - * 4. Internal state tracking objects (input state, counter) implementation - * and instantiation - * 5. Key handler (the main command dispatcher) implementation - * 6. Motion, operator, and action implementations - * 7. Helper functions for the key handler, motions, operators, and actions - * 8. Set up Vim to work as a keymap for CodeMirror. - * 9. Ex command implementations. - */ -const { logger } = require('inkdrop') -const { clipboard } = require('electron') - -module.exports = function (CodeMirror) { - var defaultKeymap = [] - var _defaultKeymap = [ - // Key to key mapping. This goes first to make it possible to override - // existing mappings. - { keys: '', type: 'keyToKey', toKeys: 'h' }, - { keys: '', type: 'keyToKey', toKeys: 'l' }, - { keys: '', type: 'keyToKey', toKeys: 'k' }, - { keys: '', type: 'keyToKey', toKeys: 'j' }, - { keys: '', type: 'keyToKey', toKeys: 'l' }, - { keys: '', type: 'keyToKey', toKeys: 'h', context: 'normal' }, - // - { keys: '', type: 'keyToKey', toKeys: 'W' }, - { keys: '', type: 'keyToKey', toKeys: 'B', context: 'normal' }, - { keys: '', type: 'keyToKey', toKeys: 'w' }, - { keys: '', type: 'keyToKey', toKeys: 'b', context: 'normal' }, - { keys: '', type: 'keyToKey', toKeys: 'j' }, - { keys: '', type: 'keyToKey', toKeys: 'k' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, - { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, - { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' }, - { keys: 's', type: 'keyToKey', toKeys: 'c', context: 'visual' }, - { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' }, - { keys: 'S', type: 'keyToKey', toKeys: 'VdO', context: 'visual' }, - { keys: '', type: 'keyToKey', toKeys: '0' }, - { keys: '', type: 'keyToKey', toKeys: '$' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' }, - { - keys: '', - type: 'action', - action: 'toggleOverwrite', - context: 'insert' - }, - // Motions - { - keys: 'H', - type: 'motion', - motion: 'moveToTopLine', - motionArgs: { linewise: true, toJumplist: true } - }, - { - keys: 'M', - type: 'motion', - motion: 'moveToMiddleLine', - motionArgs: { linewise: true, toJumplist: true } - }, - { - keys: 'L', - type: 'motion', - motion: 'moveToBottomLine', - motionArgs: { linewise: true, toJumplist: true } - }, - { - keys: 'h', - type: 'motion', - motion: 'moveByCharacters', - motionArgs: { forward: false } - }, - { - keys: 'l', - type: 'motion', - motion: 'moveByCharacters', - motionArgs: { forward: true } - }, - { - keys: 'j', - type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: true, linewise: true } - }, - { - keys: 'k', - type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: false, linewise: true } - }, - { - keys: 'gj', - type: 'motion', - motion: 'moveByDisplayLines', - motionArgs: { forward: true } - }, - { - keys: 'gk', - type: 'motion', - motion: 'moveByDisplayLines', - motionArgs: { forward: false } - }, - { - keys: 'w', - type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: false } - }, - { - keys: 'W', - type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: false, bigWord: true } - }, - { - keys: 'e', - type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: true, inclusive: true } - }, - { - keys: 'E', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: true, - wordEnd: true, - bigWord: true, - inclusive: true - } - }, - { - keys: 'b', - type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: false } - }, - { - keys: 'B', - type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: false, bigWord: true } - }, - { - keys: 'ge', - type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: true, inclusive: true } - }, - { - keys: 'gE', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: false, - wordEnd: true, - bigWord: true, - inclusive: true - } - }, - { - keys: '{', - type: 'motion', - motion: 'moveByParagraph', - motionArgs: { forward: false, toJumplist: true } - }, - { - keys: '}', - type: 'motion', - motion: 'moveByParagraph', - motionArgs: { forward: true, toJumplist: true } - }, - { - keys: '', - type: 'motion', - motion: 'moveByPage', - motionArgs: { forward: true } - }, - { - keys: '', - type: 'motion', - motion: 'moveByPage', - motionArgs: { forward: false } - }, - { - keys: '', - type: 'motion', - motion: 'moveByScroll', - motionArgs: { forward: true, explicitRepeat: true } - }, - { - keys: '', - type: 'motion', - motion: 'moveByScroll', - motionArgs: { forward: false, explicitRepeat: true } - }, - { - keys: 'gg', - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { - forward: false, - explicitRepeat: true, - linewise: true, - toJumplist: true - } - }, - { - keys: 'G', - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { - forward: true, - explicitRepeat: true, - linewise: true, - toJumplist: true - } - }, - { keys: '0', type: 'motion', motion: 'moveToStartOfLine' }, - { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { - keys: '+', - type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: true, toFirstChar: true } - }, - { - keys: '-', - type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: false, toFirstChar: true } - }, - { - keys: '_', - type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: true, toFirstChar: true, repeatOffset: -1 } - }, - { - keys: '$', - type: 'motion', - motion: 'moveToEol', - motionArgs: { inclusive: true } - }, - { - keys: '%', - type: 'motion', - motion: 'moveToMatchedSymbol', - motionArgs: { inclusive: true, toJumplist: true } - }, - { - keys: 'f', - type: 'motion', - motion: 'moveToCharacter', - motionArgs: { forward: true, inclusive: true } - }, - { - keys: 'F', - type: 'motion', - motion: 'moveToCharacter', - motionArgs: { forward: false } - }, - { - keys: 't', - type: 'motion', - motion: 'moveTillCharacter', - motionArgs: { forward: true, inclusive: true } - }, - { - keys: 'T', - type: 'motion', - motion: 'moveTillCharacter', - motionArgs: { forward: false } - }, - { - keys: ';', - type: 'motion', - motion: 'repeatLastCharacterSearch', - motionArgs: { forward: true } - }, - { - keys: ',', - type: 'motion', - motion: 'repeatLastCharacterSearch', - motionArgs: { forward: false } - }, - { - keys: "'", - type: 'motion', - motion: 'goToMark', - motionArgs: { toJumplist: true, linewise: true } - }, - { - keys: '`', - type: 'motion', - motion: 'goToMark', - motionArgs: { toJumplist: true } - }, - { - keys: ']`', - type: 'motion', - motion: 'jumpToMark', - motionArgs: { forward: true } - }, - { - keys: '[`', - type: 'motion', - motion: 'jumpToMark', - motionArgs: { forward: false } - }, - { - keys: "]'", - type: 'motion', - motion: 'jumpToMark', - motionArgs: { forward: true, linewise: true } - }, - { - keys: "['", - type: 'motion', - motion: 'jumpToMark', - motionArgs: { forward: false, linewise: true } - }, - // the next two aren't motions but must come before more general motion declarations - { - keys: ']p', - type: 'action', - action: 'paste', - isEdit: true, - actionArgs: { after: true, isEdit: true, matchIndent: true } - }, - { - keys: '[p', - type: 'action', - action: 'paste', - isEdit: true, - actionArgs: { after: false, isEdit: true, matchIndent: true } - }, - { - keys: ']', - type: 'motion', - motion: 'moveToSymbol', - motionArgs: { forward: true, toJumplist: true } - }, - { - keys: '[', - type: 'motion', - motion: 'moveToSymbol', - motionArgs: { forward: false, toJumplist: true } - }, - { keys: '|', type: 'motion', motion: 'moveToColumn' }, - { - keys: 'o', - type: 'motion', - motion: 'moveToOtherHighlightedEnd', - context: 'visual' - }, - { - keys: 'O', - type: 'motion', - motion: 'moveToOtherHighlightedEnd', - motionArgs: { sameLine: true }, - context: 'visual' - }, - // Operators - { keys: 'd', type: 'operator', operator: 'delete' }, - { keys: 'y', type: 'operator', operator: 'yank' }, - { keys: 'c', type: 'operator', operator: 'change' }, - { - keys: '>', - type: 'operator', - operator: 'indent', - operatorArgs: { indentRight: true } - }, - { - keys: '<', - type: 'operator', - operator: 'indent', - operatorArgs: { indentRight: false } - }, - { keys: 'g~', type: 'operator', operator: 'changeCase' }, - { - keys: 'gu', - type: 'operator', - operator: 'changeCase', - operatorArgs: { toLower: true }, - isEdit: true - }, - { - keys: 'gU', - type: 'operator', - operator: 'changeCase', - operatorArgs: { toLower: false }, - isEdit: true - }, - { - keys: 'n', - type: 'motion', - motion: 'findNext', - motionArgs: { forward: true, toJumplist: true } - }, - { - keys: 'N', - type: 'motion', - motion: 'findNext', - motionArgs: { forward: false, toJumplist: true } - }, - // Operator-Motion dual commands - { - keys: 'x', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveByCharacters', - motionArgs: { forward: true }, - operatorMotionArgs: { visualLine: false } - }, - { - keys: 'X', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveByCharacters', - motionArgs: { forward: false }, - operatorMotionArgs: { visualLine: true } - }, - { - keys: 'D', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveToEol', - motionArgs: { inclusive: true }, - context: 'normal' - }, - { - keys: 'D', - type: 'operator', - operator: 'delete', - operatorArgs: { linewise: true }, - context: 'visual' - }, - { - keys: 'Y', - type: 'operatorMotion', - operator: 'yank', - motion: 'expandToLine', - motionArgs: { linewise: true }, - context: 'normal' - }, - { - keys: 'Y', - type: 'operator', - operator: 'yank', - operatorArgs: { linewise: true }, - context: 'visual' - }, - { - keys: 'C', - type: 'operatorMotion', - operator: 'change', - motion: 'moveToEol', - motionArgs: { inclusive: true }, - context: 'normal' - }, - { - keys: 'C', - type: 'operator', - operator: 'change', - operatorArgs: { linewise: true }, - context: 'visual' - }, - { - keys: '~', - type: 'operatorMotion', - operator: 'changeCase', - motion: 'moveByCharacters', - motionArgs: { forward: true }, - operatorArgs: { shouldMoveCursor: true }, - context: 'normal' - }, - { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual' }, - { - keys: '', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: false }, - context: 'insert' - }, - // Actions - { - keys: '', - type: 'action', - action: 'jumpListWalk', - actionArgs: { forward: true } - }, - { - keys: '', - type: 'action', - action: 'jumpListWalk', - actionArgs: { forward: false } - }, - { - keys: '', - type: 'action', - action: 'scroll', - actionArgs: { forward: true, linewise: true } - }, - { - keys: '', - type: 'action', - action: 'scroll', - actionArgs: { forward: false, linewise: true } - }, - { - keys: 'a', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { insertAt: 'charAfter' }, - context: 'normal' - }, - { - keys: 'A', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { insertAt: 'eol' }, - context: 'normal' - }, - { - keys: 'A', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { insertAt: 'endOfSelectedArea' }, - context: 'visual' - }, - { - keys: 'i', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { insertAt: 'inplace' }, - context: 'normal' - }, - { - keys: 'I', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { insertAt: 'firstNonBlank' }, - context: 'normal' - }, - { - keys: 'I', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { insertAt: 'startOfSelectedArea' }, - context: 'visual' - }, - { - keys: 'o', - type: 'action', - action: 'newLineAndEnterInsertMode', - isEdit: true, - interlaceInsertRepeat: true, - actionArgs: { after: true }, - context: 'normal' - }, - { - keys: 'O', - type: 'action', - action: 'newLineAndEnterInsertMode', - isEdit: true, - interlaceInsertRepeat: true, - actionArgs: { after: false }, - context: 'normal' - }, - { keys: 'v', type: 'action', action: 'toggleVisualMode' }, - { - keys: 'V', - type: 'action', - action: 'toggleVisualMode', - actionArgs: { linewise: true } - }, - { - keys: '', - type: 'action', - action: 'toggleVisualMode', - actionArgs: { blockwise: true } - }, - { - keys: '', - type: 'action', - action: 'toggleVisualMode', - actionArgs: { blockwise: true } - }, - { keys: 'gv', type: 'action', action: 'reselectLastSelection' }, - { keys: 'J', type: 'action', action: 'joinLines', isEdit: true }, - { - keys: 'p', - type: 'action', - action: 'paste', - isEdit: true, - actionArgs: { after: true, isEdit: true } - }, - { - keys: 'P', - type: 'action', - action: 'paste', - isEdit: true, - actionArgs: { after: false, isEdit: true } - }, - { keys: 'r', type: 'action', action: 'replace', isEdit: true }, - { keys: '@', type: 'action', action: 'replayMacro' }, - { keys: 'q', type: 'action', action: 'enterMacroRecordMode' }, - // Handle Replace-mode as a special case of insert mode. - { - keys: 'R', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { replace: true } - }, - { keys: 'u', type: 'action', action: 'undo', context: 'normal' }, - { - keys: 'u', - type: 'operator', - operator: 'changeCase', - operatorArgs: { toLower: true }, - context: 'visual', - isEdit: true - }, - { - keys: 'U', - type: 'operator', - operator: 'changeCase', - operatorArgs: { toLower: false }, - context: 'visual', - isEdit: true - }, - { keys: '', type: 'action', action: 'redo' }, - { keys: 'm', type: 'action', action: 'setMark' }, - { keys: '"', type: 'action', action: 'setRegister' }, - { - keys: 'zz', - type: 'action', - action: 'scrollToCursor', - actionArgs: { position: 'center' } - }, - { - keys: 'z.', - type: 'action', - action: 'scrollToCursor', - actionArgs: { position: 'center' }, - motion: 'moveToFirstNonWhiteSpaceCharacter' - }, - { - keys: 'zt', - type: 'action', - action: 'scrollToCursor', - actionArgs: { position: 'top' } - }, - { - keys: 'z', - type: 'action', - action: 'scrollToCursor', - actionArgs: { position: 'top' }, - motion: 'moveToFirstNonWhiteSpaceCharacter' - }, - { - keys: 'z-', - type: 'action', - action: 'scrollToCursor', - actionArgs: { position: 'bottom' } - }, - { - keys: 'zb', - type: 'action', - action: 'scrollToCursor', - actionArgs: { position: 'bottom' }, - motion: 'moveToFirstNonWhiteSpaceCharacter' - }, - { keys: '.', type: 'action', action: 'repeatLastEdit' }, - { - keys: '', - type: 'action', - action: 'incrementNumberToken', - isEdit: true, - actionArgs: { increase: true, backtrack: false } - }, - { - keys: '', - type: 'action', - action: 'incrementNumberToken', - isEdit: true, - actionArgs: { increase: false, backtrack: false } - }, - { - keys: '', - type: 'action', - action: 'indent', - actionArgs: { indentRight: true }, - context: 'insert' - }, - { - keys: '', - type: 'action', - action: 'indent', - actionArgs: { indentRight: false }, - context: 'insert' - }, - // Text object motions - { keys: 'a', type: 'motion', motion: 'textObjectManipulation' }, - { - keys: 'i', - type: 'motion', - motion: 'textObjectManipulation', - motionArgs: { textObjectInner: true } - }, - // Search - { - keys: '/', - type: 'search', - searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true } - }, - { - keys: '?', - type: 'search', - searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true } - }, - { - keys: '*', - type: 'search', - searchArgs: { - forward: true, - querySrc: 'wordUnderCursor', - wholeWordOnly: true, - toJumplist: true - } - }, - { - keys: '#', - type: 'search', - searchArgs: { - forward: false, - querySrc: 'wordUnderCursor', - wholeWordOnly: true, - toJumplist: true - } - }, - { - keys: 'g*', - type: 'search', - searchArgs: { - forward: true, - querySrc: 'wordUnderCursor', - toJumplist: true - } - }, - { - keys: 'g#', - type: 'search', - searchArgs: { - forward: false, - querySrc: 'wordUnderCursor', - toJumplist: true - } - }, - // Ex command - { keys: ':', type: 'ex' } - ] - - /** - * Ex commands - * Care must be taken when adding to the default Ex command map. For any - * pair of commands that have a shared prefix, at least one of their - * shortNames must not match the prefix of the other command. - */ - var defaultExCommandMap = [ - { name: 'colorscheme', shortName: 'colo' }, - { name: 'map' }, - { name: 'imap', shortName: 'im' }, - { name: 'nmap', shortName: 'nm' }, - { name: 'vmap', shortName: 'vm' }, - { name: 'unmap' }, - { name: 'write', shortName: 'w' }, - { name: 'undo', shortName: 'u' }, - { name: 'redo', shortName: 'red' }, - { name: 'set', shortName: 'se' }, - { name: 'set', shortName: 'se' }, - { name: 'setlocal', shortName: 'setl' }, - { name: 'setglobal', shortName: 'setg' }, - { name: 'sort', shortName: 'sor' }, - { name: 'substitute', shortName: 's', possiblyAsync: true }, - { name: 'nohlsearch', shortName: 'noh' }, - { name: 'yank', shortName: 'y' }, - { name: 'delmarks', shortName: 'delm' }, - { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true }, - { name: 'global', shortName: 'g' } - ] - - var Pos = CodeMirror.Pos - - var Vim = function () { - function enterVimMode(cm) { - cm.setOption('disableInput', true) - cm.setOption('showCursorWhenSelecting', false) - CodeMirror.signal(cm, 'vim-mode-change', { mode: 'normal' }) - cm.on('cursorActivity', onCursorActivity) - maybeInitVimState(cm) - CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)) - } - - function leaveVimMode(cm) { - cm.setOption('disableInput', false) - cm.off('cursorActivity', onCursorActivity) - CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)) - cm.state.vim = null - } - - function detachVimMap(cm, next) { - if (this == CodeMirror.keyMap.vim) { - CodeMirror.rmClass(cm.getWrapperElement(), 'cm-fat-cursor') - } - - if (!next || next.attach != attachVimMap) { - leaveVimMode(cm) - } - } - function attachVimMap(cm, prev) { - if (this == CodeMirror.keyMap.vim) { - CodeMirror.addClass(cm.getWrapperElement(), 'cm-fat-cursor') - } - - if (!prev || prev.attach != attachVimMap) { - enterVimMode(cm) - } - } - - // Deprecated, simply setting the keymap works again. - CodeMirror.defineOption('vimMode', false, function (cm, val, prev) { - if (val && cm.getOption('keyMap') != 'vim') { - cm.setOption('keyMap', 'vim') - } else if ( - !val && - prev != CodeMirror.Init && - /^vim/.test(cm.getOption('keyMap')) - ) { - cm.setOption('keyMap', 'default') - } - }) - - function cmKey(key, cm) { - if (!cm) { - return undefined - } - if (this[key]) { - return this[key] - } - var vimKey = cmKeyToVimKey(key) - if (!vimKey) { - return false - } - var cmd = CodeMirror.Vim.findKey(cm, vimKey) - if (typeof cmd === 'function') { - CodeMirror.signal(cm, 'vim-keypress', vimKey) - } - return cmd - } - - var modifiers = { Shift: 'S', Ctrl: 'C', Alt: 'A', Cmd: 'D', Mod: 'A' } - var specialKeys = { - Enter: 'CR', - Backspace: 'BS', - Delete: 'Del', - Insert: 'Ins' - } - function cmKeyToVimKey(key) { - if (key.charAt(0) == "'") { - // Keypress character binding of format "'a'" - return key.charAt(1) - } - var pieces = key.split(/-(?!$)/) - var lastPiece = pieces[pieces.length - 1] - if (pieces.length == 1 && pieces[0].length == 1) { - // No-modifier bindings use literal character bindings above. Skip. - return false - } else if ( - pieces.length == 2 && - pieces[0] == 'Shift' && - lastPiece.length == 1 - ) { - // Ignore Shift+char bindings as they should be handled by literal character. - return false - } - var hasCharacter = false - for (var i = 0; i < pieces.length; i++) { - var piece = pieces[i] - if (piece in modifiers) { - pieces[i] = modifiers[piece] - } else { - hasCharacter = true - } - if (piece in specialKeys) { - pieces[i] = specialKeys[piece] - } - } - if (!hasCharacter) { - // Vim does not support modifier only keys. - return false - } - // TODO: Current bindings expect the character to be lower case, but - // it looks like vim key notation uses upper case. - if (isUpperCase(lastPiece)) { - pieces[pieces.length - 1] = lastPiece.toLowerCase() - } - return '<' + pieces.join('-') + '>' - } - - function getOnPasteFn(cm) { - var vim = cm.state.vim - if (!vim.onPasteFn) { - vim.onPasteFn = function () { - if (!vim.insertMode) { - cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)) - actions.enterInsertMode(cm, {}, vim) - } - } - } - return vim.onPasteFn - } - - var numberRegex = /[\d]/ - var wordCharTest = [ - CodeMirror.isWordChar, - function (ch) { - return ch && !CodeMirror.isWordChar(ch) && !/\s/.test(ch) - } - ], - bigWordCharTest = [ - function (ch) { - return /\S/.test(ch) - } - ] - function makeKeyRange(start, size) { - var keys = [] - for (var i = start; i < start + size; i++) { - keys.push(String.fromCharCode(i)) - } - return keys - } - var upperCaseAlphabet = makeKeyRange(65, 26) - var lowerCaseAlphabet = makeKeyRange(97, 26) - var numbers = makeKeyRange(48, 10) - var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, [ - '<', - '>' - ]) - var validRegisters = [].concat( - upperCaseAlphabet, - lowerCaseAlphabet, - numbers, - ['-', '"', '.', ':', '/'] - ) - - function isLine(cm, line) { - return line >= cm.firstLine() && line <= cm.lastLine() - } - function isLowerCase(k) { - return /^[a-z]$/.test(k) - } - function isMatchableSymbol(k) { - return '()[]{}'.indexOf(k) != -1 - } - function isNumber(k) { - return numberRegex.test(k) - } - function isUpperCase(k) { - return /^[A-Z]$/.test(k) - } - function isWhiteSpaceString(k) { - return /^\s*$/.test(k) - } - function inArray(val, arr) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] == val) { - return true - } - } - return false - } - - var options = {} - function defineOption(name, defaultValue, type, aliases, callback) { - if (defaultValue === undefined && !callback) { - throw Error('defaultValue is required unless callback is provided') - } - if (!type) { - type = 'string' - } - options[name] = { - type: type, - defaultValue: defaultValue, - callback: callback - } - if (aliases) { - for (var i = 0; i < aliases.length; i++) { - options[aliases[i]] = options[name] - } - } - if (defaultValue) { - setOption(name, defaultValue) - } - } - - function setOption(name, value, cm, cfg) { - var option = options[name] - cfg = cfg || {} - var scope = cfg.scope - if (!option) { - return new Error('Unknown option: ' + name) - } - if (option.type == 'boolean') { - if (value && value !== true) { - return new Error('Invalid argument: ' + name + '=' + value) - } else if (value !== false) { - // Boolean options are set to true if value is not defined. - value = true - } - } - if (option.callback) { - if (scope !== 'local') { - option.callback(value, undefined) - } - if (scope !== 'global' && cm) { - option.callback(value, cm) - } - } else { - if (scope !== 'local') { - option.value = option.type == 'boolean' ? !!value : value - } - if (scope !== 'global' && cm) { - cm.state.vim.options[name] = { value: value } - } - } - } - - function getOption(name, cm, cfg) { - var option = options[name] - cfg = cfg || {} - var scope = cfg.scope - if (!option) { - return new Error('Unknown option: ' + name) - } - if (option.callback) { - var local = cm && option.callback(undefined, cm) - if (scope !== 'global' && local !== undefined) { - return local - } - if (scope !== 'local') { - return option.callback() - } - } else { - var local = scope !== 'global' && cm && cm.state.vim.options[name] - return (local || (scope !== 'local' && option) || {}).value - } - } - - defineOption('filetype', undefined, 'string', ['ft'], function (name, cm) { - // Option is local. Do nothing for global. - if (cm === undefined) { - return - } - // The 'filetype' option proxies to the CodeMirror 'mode' option. - if (name === undefined) { - var mode = cm.getOption('mode') - return mode == 'null' ? '' : mode - } else { - var mode = name == '' ? 'null' : name - cm.setOption('mode', mode) - } - }) - - var createCircularJumpList = function () { - var size = 100 - var pointer = -1 - var head = 0 - var tail = 0 - var buffer = new Array(size) - function add(cm, oldCur, newCur) { - var current = pointer % size - var curMark = buffer[current] - function useNextSlot(cursor) { - var next = ++pointer % size - var trashMark = buffer[next] - if (trashMark) { - trashMark.clear() - } - buffer[next] = cm.setBookmark(cursor) - } - if (curMark) { - var markPos = curMark.find() - // avoid recording redundant cursor position - if (markPos && !cursorEqual(markPos, oldCur)) { - useNextSlot(oldCur) - } - } else { - useNextSlot(oldCur) - } - useNextSlot(newCur) - head = pointer - tail = pointer - size + 1 - if (tail < 0) { - tail = 0 - } - } - function move(cm, offset) { - pointer += offset - if (pointer > head) { - pointer = head - } else if (pointer < tail) { - pointer = tail - } - var mark = buffer[(size + pointer) % size] - // skip marks that are temporarily removed from text buffer - if (mark && !mark.find()) { - var inc = offset > 0 ? 1 : -1 - var newCur - var oldCur = cm.getCursor() - do { - pointer += inc - mark = buffer[(size + pointer) % size] - // skip marks that are the same as current position - if ( - mark && - (newCur = mark.find()) && - !cursorEqual(oldCur, newCur) - ) { - break - } - } while (pointer < head && pointer > tail) - } - return mark - } - return { - cachedCursor: undefined, // used for # and * jumps - add: add, - move: move - } - } - - // Returns an object to track the changes associated insert mode. It - // clones the object that is passed in, or creates an empty object one if - // none is provided. - var createInsertModeChanges = function (c) { - if (c) { - // Copy construction - return { - changes: c.changes, - expectCursorActivityForChange: c.expectCursorActivityForChange - } - } - return { - // Change list - changes: [], - // Set to true on change, false on cursorActivity. - expectCursorActivityForChange: false - } - } - - function MacroModeState() { - this.latestRegister = undefined - this.isPlaying = false - this.isRecording = false - this.replaySearchQueries = [] - this.onRecordingDone = undefined - this.lastInsertModeChanges = createInsertModeChanges() - } - MacroModeState.prototype = { - exitMacroRecordMode: function () { - var macroModeState = vimGlobalState.macroModeState - if (macroModeState.onRecordingDone) { - macroModeState.onRecordingDone() // close dialog - } - macroModeState.onRecordingDone = undefined - macroModeState.isRecording = false - }, - enterMacroRecordMode: function (cm, registerName) { - var register = - vimGlobalState.registerController.getRegister(registerName) - if (register) { - register.clear() - this.latestRegister = registerName - if (cm.openDialog) { - this.onRecordingDone = cm.openDialog( - '(recording)[' + registerName + ']', - null, - { bottom: true } - ) - } - this.isRecording = true - } - } - } - - function maybeInitVimState(cm) { - if (!cm.state.vim) { - // Store instance state in the CodeMirror object. - cm.state.vim = { - inputState: new InputState(), - // Vim's input state that triggered the last edit, used to repeat - // motions and operators with '.'. - lastEditInputState: undefined, - // Vim's action command before the last edit, used to repeat actions - // with '.' and insert mode repeat. - lastEditActionCommand: undefined, - // When using jk for navigation, if you move from a longer line to a - // shorter line, the cursor may clip to the end of the shorter line. - // If j is pressed again and cursor goes to the next line, the - // cursor should go back to its horizontal position on the longer - // line if it can. This is to keep track of the horizontal position. - lastHPos: -1, - // Doing the same with screen-position for gj/gk - lastHSPos: -1, - // The last motion command run. Cleared if a non-motion command gets - // executed in between. - lastMotion: null, - marks: {}, - // Mark for rendering fake cursor for visual mode. - fakeCursor: null, - insertMode: false, - // Repeat count for changes made in insert mode, triggered by key - // sequences like 3,i. Only exists when insertMode is true. - insertModeRepeat: undefined, - visualMode: false, - // If we are in visual line mode. No effect if visualMode is false. - visualLine: false, - visualBlock: false, - lastSelection: null, - lastPastedText: null, - sel: {}, - // Buffer-local/window-local values of vim options. - options: {} - } - } - return cm.state.vim - } - var vimGlobalState - function resetVimGlobalState() { - vimGlobalState = { - // The current search query. - searchQuery: null, - // Whether we are searching backwards. - searchIsReversed: false, - // Replace part of the last substituted pattern - lastSubstituteReplacePart: undefined, - jumpList: createCircularJumpList(), - macroModeState: new MacroModeState(), - // Recording latest f, t, F or T motion command. - lastCharacterSearch: { - increment: 0, - forward: true, - selectedCharacter: '' - }, - registerController: new RegisterController({}), - // search history buffer - searchHistoryController: new HistoryController(), - // ex Command history buffer - exCommandHistoryController: new HistoryController() - } - for (var optionName in options) { - var option = options[optionName] - option.value = option.defaultValue - } - } - - var lastInsertModeKeyTimer - var vimApi = { - buildKeyMap: function () { - // TODO: Convert keymap into dictionary format for fast lookup. - }, - // Testing hook, though it might be useful to expose the register - // controller anyways. - getRegisterController: function () { - return vimGlobalState.registerController - }, - resetVimGlobalState: resetVimGlobalState, - getVimGlobalState: function () { - return vimGlobalState - }, - maybeInitVimState: maybeInitVimState, - - suppressErrorLogging: false, - - InsertModeKey: InsertModeKey, - map: function (lhs, rhs, ctx) { - // Add user defined key bindings. - exCommandDispatcher.map(lhs, rhs, ctx) - }, - unmap: function (lhs, ctx) { - exCommandDispatcher.unmap(lhs, ctx) - }, - // TODO: Expose setOption and getOption as instance methods. Need to decide how to namespace - // them, or somehow make them work with the existing CodeMirror setOption/getOption API. - setOption: setOption, - getOption: getOption, - defineOption: defineOption, - defineEx: function (name, prefix, func) { - if (!prefix) { - prefix = name - } else if (name.indexOf(prefix) !== 0) { - throw new Error( - '(Vim.defineEx) "' + - prefix + - '" is not a prefix of "' + - name + - '", command not registered' - ) - } - exCommands[name] = func - exCommandDispatcher.commandMap_[prefix] = { - name: name, - shortName: prefix, - type: 'api' - } - }, - handleKey: function (cm, key, origin) { - var command = this.findKey(cm, key, origin) - if (typeof command === 'function') { - return command() - } - }, - /** - * This is the outermost function called by CodeMirror, after keys have - * been mapped to their Vim equivalents. - * - * Finds a command based on the key (and cached keys if there is a - * multi-key sequence). Returns `undefined` if no key is matched, a noop - * function if a partial match is found (multi-key), and a function to - * execute the bound command if a a key is matched. The function always - * returns true. - */ - findKey: function (cm, key, origin) { - var vim = maybeInitVimState(cm) - function handleMacroRecording() { - var macroModeState = vimGlobalState.macroModeState - if (macroModeState.isRecording) { - if (key == 'q') { - macroModeState.exitMacroRecordMode() - clearInputState(cm) - return true - } - if (origin != 'mapping') { - logKey(macroModeState, key) - } - } - } - function handleEsc() { - if (key == '') { - // Clear input state and get back to normal mode. - clearInputState(cm) - if (vim.visualMode) { - exitVisualMode(cm) - } else if (vim.insertMode) { - exitInsertMode(cm) - } - return true - } - } - function doKeyToKey(keys) { - // TODO: prevent infinite recursion. - var match - while (keys) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - match = /<\w+-.+?>|<\w+>|./.exec(keys) - key = match[0] - keys = keys.substring(match.index + key.length) - CodeMirror.Vim.handleKey(cm, key, 'mapping') - } - } - - function handleKeyInsertMode() { - if (handleEsc()) { - return true - } - - var keys = (vim.inputState.keyBuffer = vim.inputState.keyBuffer + key) - logger.debug('keyBuffer:', keys) - var keysAreChars = key.length == 1 - var match = commandDispatcher.matchCommand( - keys, - defaultKeymap, - vim.inputState, - 'insert' - ) - // Need to check all key substrings in insert mode. - while (keys.length > 1 && match.type !== 'full') { - var keys = (vim.inputState.keyBuffer = keys.slice(1)) - var thisMatch = commandDispatcher.matchCommand( - keys, - defaultKeymap, - vim.inputState, - 'insert' - ) - if (thisMatch.type !== 'none') { - match = thisMatch - } - } - if (match.type === 'none') { - clearInputState(cm) - return false - } else if (match.type === 'partial') { - if (lastInsertModeKeyTimer) { - window.clearTimeout(lastInsertModeKeyTimer) - } - lastInsertModeKeyTimer = window.setTimeout(() => { - if (vim.insertMode && vim.inputState.keyBuffer) { - clearInputState(cm) - } - }, getOption('insertModeEscKeysTimeout')) - return !keysAreChars - } - - if (lastInsertModeKeyTimer) { - window.clearTimeout(lastInsertModeKeyTimer) - } - if (keysAreChars) { - var selections = cm.listSelections() - for (var i = 0; i < selections.length; i++) { - var here = selections[i].head - cm.replaceRange( - '', - offsetCursor(here, 0, -(keys.length - 1)), - here, - '+input' - ) - } - vimGlobalState.macroModeState.lastInsertModeChanges.changes.pop() - } - clearInputState(cm) - return match.command - } - - function handleKeyNonInsertMode() { - if (handleMacroRecording() || handleEsc()) { - return true - } - - var keys = (vim.inputState.keyBuffer = vim.inputState.keyBuffer + key) - if (/^[1-9]\d*$/.test(keys)) { - return true - } - - var keysMatcher = /^(\d*)(.*)$/.exec(keys) - if (!keysMatcher) { - clearInputState(cm) - return false - } - var context = vim.visualMode ? 'visual' : 'normal' - var match = commandDispatcher.matchCommand( - keysMatcher[2] || keysMatcher[1], - defaultKeymap, - vim.inputState, - context - ) - if (match.type === 'none') { - clearInputState(cm) - return false - } else if (match.type === 'partial') { - return true - } - - vim.inputState.keyBuffer = '' - keysMatcher = /^(\d*)(.*)$/.exec(keys) - if (keysMatcher[1] && keysMatcher[1] !== '0') { - vim.inputState.pushRepeatDigit(keysMatcher[1]) - } - return match.command - } - - var command - if (vim.insertMode) { - command = handleKeyInsertMode() - } else { - command = handleKeyNonInsertMode() - } - - logger.debug( - 'keyBuffer::::', - command, - vim.inputState.keyBuffer, - vim.inputState.operator, - vim.inputState.operatorArgs - ) - - if (command === false) { - return undefined - } else if (command === true) { - // TODO: Look into using CodeMirror's multi-key handling. - // Return no-op since we are caching the key. Counts as handled, but - // don't want act on it just yet. - return function () { - return true - } - } else { - return function () { - return cm.operation(function () { - cm.curOp.isVimOp = true - try { - if (command.type === 'keyToKey') { - doKeyToKey(command.toKeys) - } else { - commandDispatcher.processCommand(cm, vim, command) - } - } catch (e) { - // clear VIM state in case it's in a bad state. - cm.state.vim = undefined - maybeInitVimState(cm) - if (!CodeMirror.Vim.suppressErrorLogging) { - console['log'](e) - } - throw e - } - return true - }) - } - } - }, - handleEx: function (cm, input) { - exCommandDispatcher.processCommand(cm, input) - }, - - defineMotion: defineMotion, - defineAction: defineAction, - defineOperator: defineOperator, - mapCommand: mapCommand, - _mapCommand: _mapCommand, - - defineRegister: defineRegister, - - exitVisualMode: exitVisualMode, - exitInsertMode: exitInsertMode, - clearInputState: clearInputState, - - cmKeyToVimKey: cmKeyToVimKey - } - - // Represents the current input state. - function InputState() { - this.prefixRepeat = [] - this.motionRepeat = [] - - this.operator = null - this.operatorArgs = null - this.motion = null - this.motionArgs = null - this.keyBuffer = [] // For matching multi-key commands. - this.registerName = null // Defaults to the unnamed register. - } - InputState.prototype.pushRepeatDigit = function (n) { - if (!this.operator) { - this.prefixRepeat = this.prefixRepeat.concat(n) - } else { - this.motionRepeat = this.motionRepeat.concat(n) - } - } - InputState.prototype.getRepeat = function () { - var repeat = 0 - if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) { - repeat = 1 - if (this.prefixRepeat.length > 0) { - repeat *= parseInt(this.prefixRepeat.join(''), 10) - } - if (this.motionRepeat.length > 0) { - repeat *= parseInt(this.motionRepeat.join(''), 10) - } - } - return repeat - } - - function clearInputState(cm, reason) { - cm.state.vim.inputState = new InputState() - CodeMirror.signal(cm, 'vim-command-done', reason) - } - - /* - * Register stores information about copy and paste registers. Besides - * text, a register must store whether it is linewise (i.e., when it is - * pasted, should it insert itself into a new line, or should the text be - * inserted at the cursor position.) - */ - function Register(text, linewise, blockwise) { - this.clear() - this.keyBuffer = [text || ''] - this.insertModeChanges = [] - this.searchQueries = [] - this.linewise = !!linewise - this.blockwise = !!blockwise - } - Register.prototype = { - setText: function (text, linewise, blockwise) { - this.keyBuffer = [text || ''] - this.linewise = !!linewise - this.blockwise = !!blockwise - }, - pushText: function (text, linewise) { - // if this register has ever been set to linewise, use linewise. - if (linewise) { - if (!this.linewise) { - this.keyBuffer.push('\n') - } - this.linewise = true - } - this.keyBuffer.push(text) - }, - pushInsertModeChanges: function (changes) { - this.insertModeChanges.push(createInsertModeChanges(changes)) - }, - pushSearchQuery: function (query) { - this.searchQueries.push(query) - }, - clear: function () { - this.keyBuffer = [] - this.insertModeChanges = [] - this.searchQueries = [] - this.linewise = false - }, - toString: function () { - return this.keyBuffer.join('') - } - } - - /** - * Defines an external register. - * - * The name should be a single character that will be used to reference the register. - * The register should support setText, pushText, clear, and toString(). See Register - * for a reference implementation. - */ - function defineRegister(name, register) { - var registers = vimGlobalState.registerController.registers - if (!name || name.length != 1) { - throw Error('Register name must be 1 character') - } - if (registers[name]) { - throw Error('Register already defined ' + name) - } - registers[name] = register - validRegisters.push(name) - } - - /* - * vim registers allow you to keep many independent copy and paste buffers. - * See http://usevim.com/2012/04/13/registers/ for an introduction. - * - * RegisterController keeps the state of all the registers. An initial - * state may be passed in. The unnamed register '"' will always be - * overridden. - */ - function RegisterController(registers) { - this.registers = registers - this.unnamedRegister = registers['"'] = new Register() - registers['.'] = new Register() - registers[':'] = new Register() - registers['/'] = new Register() - } - RegisterController.prototype = { - pushText: function (registerName, operator, text, linewise, blockwise) { - if (linewise && text.charAt(text.length - 1) !== '\n') { - text += '\n' - } - // Lowercase and uppercase registers refer to the same register. - // Uppercase just means append. - var register = this.isValidRegister(registerName) - ? this.getRegister(registerName) - : null - // if no register/an invalid register was specified, things go to the - // default registers - if (!register) { - switch (operator) { - case 'yank': - // The 0 register contains the text from the most recent yank. - const reg = new Register(text, linewise, blockwise) - logger.debug('yanked:', reg) - this.registers['0'] = reg - clipboard.writeText(reg.keyBuffer[0]) - break - case 'delete': - case 'change': - clipboard.writeText(text) - if (text.indexOf('\n') == -1) { - // Delete less than 1 line. Update the small delete register. - this.registers['-'] = new Register(text, linewise) - } else { - // Shift down the contents of the numbered registers and put the - // deleted text into register 1. - this.shiftNumericRegisters_() - this.registers['1'] = new Register(text, linewise) - } - break - } - // Make sure the unnamed register is set to what just happened - this.unnamedRegister.setText(text, linewise, blockwise) - return - } - - // If we've gotten to this point, we've actually specified a register - var append = isUpperCase(registerName) - if (append) { - register.pushText(text, linewise) - } else { - register.setText(text, linewise, blockwise) - } - // The unnamed register always has the same value as the last used - // register. - this.unnamedRegister.setText(register.toString(), linewise) - }, - // Gets the register named @name. If one of @name doesn't already exist, - // create it. If @name is invalid, return the unnamedRegister. - getRegister: function (name) { - if (!this.isValidRegister(name)) { - return this.unnamedRegister - } - name = name.toLowerCase() - if (!this.registers[name]) { - this.registers[name] = new Register() - } - return this.registers[name] - }, - isValidRegister: function (name) { - return name && inArray(name, validRegisters) - }, - shiftNumericRegisters_: function () { - for (var i = 9; i >= 2; i--) { - this.registers[i] = this.getRegister('' + (i - 1)) - } - } - } - function HistoryController() { - this.historyBuffer = [] - this.iterator = 0 - this.initialPrefix = null - } - HistoryController.prototype = { - // the input argument here acts a user entered prefix for a small time - // until we start autocompletion in which case it is the autocompleted. - nextMatch: function (input, up) { - var historyBuffer = this.historyBuffer - var dir = up ? -1 : 1 - if (this.initialPrefix === null) this.initialPrefix = input - for ( - var i = this.iterator + dir; - up ? i >= 0 : i < historyBuffer.length; - i += dir - ) { - var element = historyBuffer[i] - for (var j = 0; j <= element.length; j++) { - if (this.initialPrefix == element.substring(0, j)) { - this.iterator = i - return element - } - } - } - // should return the user input in case we reach the end of buffer. - if (i >= historyBuffer.length) { - this.iterator = historyBuffer.length - return this.initialPrefix - } - // return the last autocompleted query or exCommand as it is. - if (i < 0) return input - }, - pushInput: function (input) { - var index = this.historyBuffer.indexOf(input) - if (index > -1) this.historyBuffer.splice(index, 1) - if (input.length) this.historyBuffer.push(input) - }, - reset: function () { - this.initialPrefix = null - this.iterator = this.historyBuffer.length - } - } - var commandDispatcher = { - matchCommand: function (keys, keyMap, inputState, context) { - var matches = commandMatches(keys, keyMap, context, inputState) - if (!matches.full && !matches.partial) { - return { type: 'none' } - } else if (!matches.full && matches.partial) { - return { type: 'partial' } - } - - var bestMatch - for (var i = 0; i < matches.full.length; i++) { - var match = matches.full[i] - if (!bestMatch) { - bestMatch = match - } - } - if (bestMatch.keys.slice(-11) == '') { - var character = lastChar(keys) - if (!character) return { type: 'none' } - inputState.selectedCharacter = character - } - return { type: 'full', command: bestMatch } - }, - processCommand: function (cm, vim, command) { - vim.inputState.repeatOverride = command.repeatOverride - switch (command.type) { - case 'motion': - this.processMotion(cm, vim, command) - break - case 'operator': - this.processOperator(cm, vim, command) - break - case 'operatorMotion': - this.processOperatorMotion(cm, vim, command) - break - case 'action': - this.processAction(cm, vim, command) - break - case 'search': - this.processSearch(cm, vim, command) - break - case 'ex': - case 'keyToEx': - this.processEx(cm, vim, command) - break - default: - break - } - }, - processMotion: function (cm, vim, command) { - vim.inputState.motion = command.motion - vim.inputState.motionArgs = copyArgs(command.motionArgs) - this.evalInput(cm, vim) - }, - processOperator: function (cm, vim, command) { - var inputState = vim.inputState - if (inputState.operator) { - if (inputState.operator === command.operator) { - // Typing an operator twice like 'dd' makes the operator operate - // linewise - inputState.motion = 'expandToLine' - inputState.motionArgs = { linewise: true } - this.evalInput(cm, vim) - return - } else { - // 2 different operators in a row doesn't make sense. - clearInputState(cm) - } - } - inputState.operator = command.operator - inputState.operatorArgs = copyArgs(command.operatorArgs) - if (vim.visualMode) { - // Operating on a selection in visual mode. We don't need a motion. - this.evalInput(cm, vim) - } - }, - processOperatorMotion: function (cm, vim, command) { - var visualMode = vim.visualMode - var operatorMotionArgs = copyArgs(command.operatorMotionArgs) - if (operatorMotionArgs) { - // Operator motions may have special behavior in visual mode. - if (visualMode && operatorMotionArgs.visualLine) { - vim.visualLine = true - } - } - this.processOperator(cm, vim, command) - if (!visualMode) { - this.processMotion(cm, vim, command) - } - }, - processAction: function (cm, vim, command) { - var inputState = vim.inputState - var repeat = inputState.getRepeat() - var repeatIsExplicit = !!repeat - var actionArgs = copyArgs(command.actionArgs) || {} - if (inputState.selectedCharacter) { - actionArgs.selectedCharacter = inputState.selectedCharacter - } - // Actions may or may not have motions and operators. Do these first. - if (command.operator) { - this.processOperator(cm, vim, command) - } - if (command.motion) { - this.processMotion(cm, vim, command) - } - if (command.motion || command.operator) { - this.evalInput(cm, vim) - } - actionArgs.repeat = repeat || 1 - actionArgs.repeatIsExplicit = repeatIsExplicit - actionArgs.registerName = inputState.registerName - clearInputState(cm) - vim.lastMotion = null - if (command.isEdit) { - this.recordLastEdit(vim, inputState, command) - } - actions[command.action](cm, actionArgs, vim) - }, - processSearch: function (cm, vim, command) { - if (!cm.getSearchCursor) { - // Search depends on SearchCursor. - return - } - var forward = command.searchArgs.forward - var wholeWordOnly = command.searchArgs.wholeWordOnly - getSearchState(cm).setReversed(!forward) - var promptPrefix = forward ? '/' : '?' - var originalQuery = getSearchState(cm).getQuery() - var originalScrollPos = cm.getScrollInfo() - function handleQuery(query, ignoreCase, smartCase) { - vimGlobalState.searchHistoryController.pushInput(query) - vimGlobalState.searchHistoryController.reset() - try { - updateSearchQuery(cm, query, ignoreCase, smartCase) - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + query) - clearInputState(cm) - return - } - commandDispatcher.processMotion(cm, vim, { - type: 'motion', - motion: 'findNext', - motionArgs: { - forward: true, - toJumplist: command.searchArgs.toJumplist - } - }) - } - function onPromptClose(query) { - cm.scrollTo(originalScrollPos.left, originalScrollPos.top) - handleQuery(query, true /** ignoreCase */, true /** smartCase */) - var macroModeState = vimGlobalState.macroModeState - if (macroModeState.isRecording) { - logSearchQuery(macroModeState, query) - } - } - function onPromptKeyUp(e, query, close) { - var keyName = CodeMirror.keyName(e), - up, - offset - if (keyName == 'Up' || keyName == 'Down') { - up = keyName == 'Up' - offset = e.target ? e.target.selectionEnd : 0 - query = - vimGlobalState.searchHistoryController.nextMatch(query, up) || '' - close(query) - if (offset && e.target) - e.target.selectionEnd = e.target.selectionStart = Math.min( - offset, - e.target.value.length - ) - } else { - if ( - keyName != 'Left' && - keyName != 'Right' && - keyName != 'Ctrl' && - keyName != 'Alt' && - keyName != 'Shift' - ) { - vimGlobalState.searchHistoryController.reset() - } - } - var parsedQuery - try { - parsedQuery = updateSearchQuery( - cm, - query, - true /** ignoreCase */, - true /** smartCase */ - ) - } catch (e) { - // Swallow bad regexes for incremental search. - } - if (parsedQuery) { - cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30) - } else { - clearSearchHighlight(cm) - cm.scrollTo(originalScrollPos.left, originalScrollPos.top) - } - } - function onPromptKeyDown(e, query, close) { - var keyName = CodeMirror.keyName(e) - if ( - keyName == 'Esc' || - keyName == 'Ctrl-C' || - keyName == 'Ctrl-[' || - (keyName == 'Backspace' && query == '') - ) { - vimGlobalState.searchHistoryController.pushInput(query) - vimGlobalState.searchHistoryController.reset() - updateSearchQuery(cm, originalQuery) - clearSearchHighlight(cm) - cm.scrollTo(originalScrollPos.left, originalScrollPos.top) - CodeMirror.e_stop(e) - clearInputState(cm) - close() - cm.focus() - } else if (keyName == 'Up' || keyName == 'Down') { - CodeMirror.e_stop(e) - } else if (keyName == 'Ctrl-U') { - // Ctrl-U clears input. - CodeMirror.e_stop(e) - close('') - } - } - switch (command.searchArgs.querySrc) { - case 'prompt': - var macroModeState = vimGlobalState.macroModeState - if (macroModeState.isPlaying) { - var query = macroModeState.replaySearchQueries.shift() - handleQuery(query, true /** ignoreCase */, false /** smartCase */) - } else { - showPrompt(cm, { - onClose: onPromptClose, - prefix: promptPrefix, - desc: searchPromptDesc, - onKeyUp: onPromptKeyUp, - onKeyDown: onPromptKeyDown - }) - } - break - case 'wordUnderCursor': - var word = expandWordUnderCursor( - cm, - false /** inclusive */, - true /** forward */, - false /** bigWord */, - true /** noSymbol */ - ) - var isKeyword = true - if (!word) { - word = expandWordUnderCursor( - cm, - false /** inclusive */, - true /** forward */, - false /** bigWord */, - false /** noSymbol */ - ) - isKeyword = false - } - if (!word) { - return - } - var query = cm - .getLine(word.start.line) - .substring(word.start.ch, word.end.ch) - if (isKeyword && wholeWordOnly) { - query = '\\b' + query + '\\b' - } else { - query = escapeRegex(query) - } - - // cachedCursor is used to save the old position of the cursor - // when * or # causes vim to seek for the nearest word and shift - // the cursor before entering the motion. - vimGlobalState.jumpList.cachedCursor = cm.getCursor() - cm.setCursor(word.start) - - handleQuery(query, true /** ignoreCase */, false /** smartCase */) - break - } - }, - processEx: function (cm, vim, command) { - function onPromptClose(input) { - // Give the prompt some time to close so that if processCommand shows - // an error, the elements don't overlap. - vimGlobalState.exCommandHistoryController.pushInput(input) - vimGlobalState.exCommandHistoryController.reset() - exCommandDispatcher.processCommand(cm, input) - } - function onPromptKeyDown(e, input, close) { - var keyName = CodeMirror.keyName(e), - up, - offset - if ( - keyName === 'Esc' || - keyName === 'Ctrl-C' || - keyName === 'Ctrl-[' || - (keyName === 'Backspace' && input === '') - ) { - vimGlobalState.exCommandHistoryController.pushInput(input) - vimGlobalState.exCommandHistoryController.reset() - CodeMirror.e_stop(e) - clearInputState(cm) - close() - cm.focus() - } - if (keyName === 'Up' || keyName === 'Down') { - CodeMirror.e_stop(e) - up = keyName === 'Up' - offset = e.target ? e.target.selectionEnd : 0 - input = - vimGlobalState.exCommandHistoryController.nextMatch(input, up) || - '' - close(input) - if (offset && e.target) - e.target.selectionEnd = e.target.selectionStart = Math.min( - offset, - e.target.value.length - ) - } else if (keyName === 'Ctrl-U') { - // Ctrl-U clears input. - CodeMirror.e_stop(e) - close('') - } else { - if ( - keyName !== 'Left' && - keyName !== 'Right' && - keyName !== 'Ctrl' && - keyName !== 'Alt' && - keyName !== 'Shift' - ) { - vimGlobalState.exCommandHistoryController.reset() - } - } - } - if (command.type === 'keyToEx') { - // Handle user defined Ex to Ex mappings - exCommandDispatcher.processCommand(cm, command.exArgs.input) - } else { - if (vim.visualMode) { - showPrompt(cm, { - onClose: onPromptClose, - prefix: ':', - value: "'<,'>", - onKeyDown: onPromptKeyDown - }) - } else { - showPrompt(cm, { - onClose: onPromptClose, - prefix: ':', - onKeyDown: onPromptKeyDown - }) - } - } - }, - evalInput: function (cm, vim) { - // If the motion command is set, execute both the operator and motion. - // Otherwise return. - var inputState = vim.inputState - var motion = inputState.motion - var motionArgs = inputState.motionArgs || {} - var operator = inputState.operator - var operatorArgs = inputState.operatorArgs || {} - var registerName = inputState.registerName - var sel = vim.sel - // TODO: Make sure cm and vim selections are identical outside visual mode. - var origHead = copyCursor( - vim.visualMode - ? clipCursorToContent(cm, sel.head) - : cm.getCursor('head') - ) - var origAnchor = copyCursor( - vim.visualMode - ? clipCursorToContent(cm, sel.anchor) - : cm.getCursor('anchor') - ) - var oldHead = copyCursor(origHead) - var oldAnchor = copyCursor(origAnchor) - var newHead, newAnchor - var repeat - if (operator) { - this.recordLastEdit(vim, inputState) - } - if (inputState.repeatOverride !== undefined) { - // If repeatOverride is specified, that takes precedence over the - // input state's repeat. Used by Ex mode and can be user defined. - repeat = inputState.repeatOverride - } else { - repeat = inputState.getRepeat() - } - if (repeat > 0 && motionArgs.explicitRepeat) { - motionArgs.repeatIsExplicit = true - } else if ( - motionArgs.noRepeat || - (!motionArgs.explicitRepeat && repeat === 0) - ) { - repeat = 1 - motionArgs.repeatIsExplicit = false - } - if (inputState.selectedCharacter) { - // If there is a character input, stick it in all of the arg arrays. - motionArgs.selectedCharacter = operatorArgs.selectedCharacter = - inputState.selectedCharacter - } - motionArgs.repeat = repeat - clearInputState(cm) - if (motion) { - var motionResult = motions[motion](cm, origHead, motionArgs, vim) - vim.lastMotion = motions[motion] - if (!motionResult) { - return - } - if (motionArgs.toJumplist) { - var jumpList = vimGlobalState.jumpList - // if the current motion is # or *, use cachedCursor - var cachedCursor = jumpList.cachedCursor - if (cachedCursor) { - recordJumpPosition(cm, cachedCursor, motionResult) - delete jumpList.cachedCursor - } else { - recordJumpPosition(cm, origHead, motionResult) - } - } - if (motionResult instanceof Array) { - newAnchor = motionResult[0] - newHead = motionResult[1] - } else { - newHead = motionResult - } - // TODO: Handle null returns from motion commands better. - if (!newHead) { - newHead = copyCursor(origHead) - } - if (vim.visualMode) { - if (!(vim.visualBlock && newHead.ch === Infinity)) { - newHead = clipCursorToContent(cm, newHead, vim.visualBlock) - } - if (newAnchor) { - newAnchor = clipCursorToContent(cm, newAnchor, true) - } - newAnchor = newAnchor || oldAnchor - sel.anchor = newAnchor - sel.head = newHead - updateCmSelection(cm) - updateMark( - cm, - vim, - '<', - cursorIsBefore(newAnchor, newHead) ? newAnchor : newHead - ) - updateMark( - cm, - vim, - '>', - cursorIsBefore(newAnchor, newHead) ? newHead : newAnchor - ) - } else if (!operator) { - newHead = clipCursorToContent(cm, newHead) - cm.setCursor(newHead.line, newHead.ch) - } - } - if (operator) { - if (operatorArgs.lastSel) { - // Replaying a visual mode operation - newAnchor = oldAnchor - var lastSel = operatorArgs.lastSel - var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line) - var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch) - if (lastSel.visualLine) { - // Linewise Visual mode: The same number of lines. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch) - } else if (lastSel.visualBlock) { - // Blockwise Visual mode: The same number of lines and columns. - newHead = Pos( - oldAnchor.line + lineOffset, - oldAnchor.ch + chOffset - ) - } else if (lastSel.head.line == lastSel.anchor.line) { - // Normal Visual mode within one line: The same number of characters. - newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset) - } else { - // Normal Visual mode with several lines: The same number of lines, in the - // last line the same number of characters as in the last line the last time. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch) - } - vim.visualMode = true - vim.visualLine = lastSel.visualLine - vim.visualBlock = lastSel.visualBlock - sel = vim.sel = { - anchor: newAnchor, - head: newHead - } - updateCmSelection(cm) - } else if (vim.visualMode) { - operatorArgs.lastSel = { - anchor: copyCursor(sel.anchor), - head: copyCursor(sel.head), - visualBlock: vim.visualBlock, - visualLine: vim.visualLine - } - } - var curStart, curEnd, linewise, mode - var cmSel - if (vim.visualMode) { - // Init visual op - curStart = cursorMin(sel.head, sel.anchor) - curEnd = cursorMax(sel.head, sel.anchor) - linewise = vim.visualLine || operatorArgs.linewise - mode = vim.visualBlock ? 'block' : linewise ? 'line' : 'char' - cmSel = makeCmSelection( - cm, - { - anchor: curStart, - head: curEnd - }, - mode - ) - if (linewise) { - var ranges = cmSel.ranges - if (mode == 'block') { - // Linewise operators in visual block mode extend to end of line - for (var i = 0; i < ranges.length; i++) { - ranges[i].head.ch = lineLength(cm, ranges[i].head.line) - } - } else if (mode == 'line') { - ranges[0].head = Pos(ranges[0].head.line + 1, 0) - } - } - } else { - // Init motion op - curStart = copyCursor(newAnchor || oldAnchor) - curEnd = copyCursor(newHead || oldHead) - if (cursorIsBefore(curEnd, curStart)) { - var tmp = curStart - curStart = curEnd - curEnd = tmp - } - linewise = motionArgs.linewise || operatorArgs.linewise - if (linewise) { - // Expand selection to entire line. - expandSelectionToLine(cm, curStart, curEnd) - } else if (motionArgs.forward) { - // Clip to trailing newlines only if the motion goes forward. - clipToLine(cm, curStart, curEnd) - } - mode = 'char' - var exclusive = !motionArgs.inclusive || linewise - cmSel = makeCmSelection( - cm, - { - anchor: curStart, - head: curEnd - }, - mode, - exclusive - ) - } - cm.setSelections(cmSel.ranges, cmSel.primary) - vim.lastMotion = null - operatorArgs.repeat = repeat // For indent in visual mode. - operatorArgs.registerName = registerName - // Keep track of linewise as it affects how paste and change behave. - operatorArgs.linewise = linewise - var operatorMoveTo = operators[operator]( - cm, - operatorArgs, - cmSel.ranges, - oldAnchor, - newHead - ) - if (vim.visualMode) { - exitVisualMode(cm, operatorMoveTo != null) - } - if (operatorMoveTo) { - cm.setCursor(operatorMoveTo) - } - } - }, - recordLastEdit: function (vim, inputState, actionCommand) { - var macroModeState = vimGlobalState.macroModeState - if (macroModeState.isPlaying) { - return - } - vim.lastEditInputState = inputState - vim.lastEditActionCommand = actionCommand - macroModeState.lastInsertModeChanges.changes = [] - macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false - } - } - - /** - * typedef {Object{line:number,ch:number}} Cursor An object containing the - * position of the cursor. - */ - // All of the functions below return Cursor objects. - var motions = { - moveToTopLine: function (cm, _head, motionArgs) { - var line = getUserVisibleLines(cm).top + motionArgs.repeat - 1 - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))) - }, - moveToMiddleLine: function (cm) { - var range = getUserVisibleLines(cm) - var line = Math.floor((range.top + range.bottom) * 0.5) - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))) - }, - moveToBottomLine: function (cm, _head, motionArgs) { - var line = getUserVisibleLines(cm).bottom - motionArgs.repeat + 1 - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))) - }, - expandToLine: function (_cm, head, motionArgs) { - // Expands forward to end of line, and then to next line if repeat is - // >1. Does not handle backward motion! - var cur = head - return Pos(cur.line + motionArgs.repeat - 1, Infinity) - }, - findNext: function (cm, _head, motionArgs) { - var state = getSearchState(cm) - var query = state.getQuery() - if (!query) { - return - } - var prev = !motionArgs.forward - // If search is initiated with ? instead of /, negate direction. - prev = state.isReversed() ? !prev : prev - highlightSearchMatches(cm, query) - return findNext(cm, prev /** prev */, query, motionArgs.repeat) - }, - goToMark: function (cm, _head, motionArgs, vim) { - var pos = getMarkPos(cm, vim, motionArgs.selectedCharacter) - if (pos) { - return motionArgs.linewise - ? { - line: pos.line, - ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) - } - : pos - } - return null - }, - moveToOtherHighlightedEnd: function (cm, _head, motionArgs, vim) { - if (vim.visualBlock && motionArgs.sameLine) { - var sel = vim.sel - return [ - clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)), - clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch)) - ] - } else { - return [vim.sel.head, vim.sel.anchor] - } - }, - jumpToMark: function (cm, head, motionArgs, vim) { - var best = head - for (var i = 0; i < motionArgs.repeat; i++) { - var cursor = best - for (var key in vim.marks) { - if (!isLowerCase(key)) { - continue - } - var mark = vim.marks[key].find() - var isWrongDirection = motionArgs.forward - ? cursorIsBefore(mark, cursor) - : cursorIsBefore(cursor, mark) - - if (isWrongDirection) { - continue - } - if (motionArgs.linewise && mark.line == cursor.line) { - continue - } - - var equal = cursorEqual(cursor, best) - var between = motionArgs.forward - ? cursorIsBetween(cursor, mark, best) - : cursorIsBetween(best, mark, cursor) - - if (equal || between) { - best = mark - } - } - } - - if (motionArgs.linewise) { - // Vim places the cursor on the first non-whitespace character of - // the line if there is one, else it places the cursor at the end - // of the line, regardless of whether a mark was found. - best = Pos( - best.line, - findFirstNonWhiteSpaceCharacter(cm.getLine(best.line)) - ) - } - return best - }, - moveByCharacters: function (_cm, head, motionArgs) { - var cur = head - var repeat = motionArgs.repeat - var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat - return Pos(cur.line, ch) - }, - moveByLines: function (cm, head, motionArgs, vim) { - var cur = head - var endCh = cur.ch - // Depending what our last motion was, we may want to do different - // things. If our last motion was moving vertically, we want to - // preserve the HPos from our last horizontal move. If our last motion - // was going to the end of a line, moving vertically we should go to - // the end of the line, etc. - switch (vim.lastMotion) { - case this.moveByLines: - case this.moveByDisplayLines: - case this.moveByScroll: - case this.moveToColumn: - case this.moveToEol: - endCh = vim.lastHPos - break - default: - vim.lastHPos = endCh - } - var repeat = motionArgs.repeat + (motionArgs.repeatOffset || 0) - var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat - var first = cm.firstLine() - var last = cm.lastLine() - // Vim go to line begin or line end when cursor at first/last line and - // move to previous/next line is triggered. - if (line < first && cur.line == first) { - return this.moveToStartOfLine(cm, head, motionArgs, vim) - } else if (line > last && cur.line == last) { - return this.moveToEol(cm, head, motionArgs, vim) - } - if (motionArgs.toFirstChar) { - endCh = findFirstNonWhiteSpaceCharacter(cm.getLine(line)) - vim.lastHPos = endCh - } - vim.lastHSPos = cm.charCoords(Pos(line, endCh), 'div').left - return Pos(line, endCh) - }, - moveByDisplayLines: function (cm, head, motionArgs, vim) { - var cur = head - switch (vim.lastMotion) { - case this.moveByDisplayLines: - case this.moveByScroll: - case this.moveByLines: - case this.moveToColumn: - case this.moveToEol: - break - default: - vim.lastHSPos = cm.charCoords(cur, 'div').left - } - var repeat = motionArgs.repeat - var res = cm.findPosV( - cur, - motionArgs.forward ? repeat : -repeat, - 'line', - vim.lastHSPos - ) - if (res.hitSide) { - if (motionArgs.forward) { - var lastCharCoords = cm.charCoords(res, 'div') - var goalCoords = { - top: lastCharCoords.top + 8, - left: vim.lastHSPos - } - var res = cm.coordsChar(goalCoords, 'div') - } else { - var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div') - resCoords.left = vim.lastHSPos - res = cm.coordsChar(resCoords, 'div') - } - } - vim.lastHPos = res.ch - return res - }, - moveByPage: function (cm, head, motionArgs) { - // CodeMirror only exposes functions that move the cursor page down, so - // doing this bad hack to move the cursor and move it back. evalInput - // will move the cursor to where it should be in the end. - var curStart = head - var repeat = motionArgs.repeat - return cm.findPosV( - curStart, - motionArgs.forward ? repeat : -repeat, - 'page' - ) - }, - moveByParagraph: function (cm, head, motionArgs) { - var dir = motionArgs.forward ? 1 : -1 - return findParagraph(cm, head, motionArgs.repeat, dir) - }, - moveByScroll: function (cm, head, motionArgs, vim) { - var scrollbox = cm.getScrollInfo() - var curEnd = null - var repeat = motionArgs.repeat - if (!repeat) { - repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight()) - } - var orig = cm.charCoords(head, 'local') - motionArgs.repeat = repeat - var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim) - if (!curEnd) { - return null - } - var dest = cm.charCoords(curEnd, 'local') - cm.scrollTo(null, scrollbox.top + dest.top - orig.top) - return curEnd - }, - moveByWords: function (cm, head, motionArgs) { - return moveToWord( - cm, - head, - motionArgs.repeat, - !!motionArgs.forward, - !!motionArgs.wordEnd, - !!motionArgs.bigWord - ) - }, - moveTillCharacter: function (cm, _head, motionArgs) { - var repeat = motionArgs.repeat - var curEnd = moveToCharacter( - cm, - repeat, - motionArgs.forward, - motionArgs.selectedCharacter - ) - var increment = motionArgs.forward ? -1 : 1 - recordLastCharacterSearch(increment, motionArgs) - if (!curEnd) return null - curEnd.ch += increment - return curEnd - }, - moveToCharacter: function (cm, head, motionArgs) { - var repeat = motionArgs.repeat - recordLastCharacterSearch(0, motionArgs) - logger.debug('moveToCharacter:', motionArgs) - return ( - moveToCharacter( - cm, - repeat, - motionArgs.forward, - motionArgs.selectedCharacter - ) || head - ) - }, - moveToSymbol: function (cm, head, motionArgs) { - var repeat = motionArgs.repeat - return ( - findSymbol( - cm, - repeat, - motionArgs.forward, - motionArgs.selectedCharacter - ) || head - ) - }, - moveToColumn: function (cm, head, motionArgs, vim) { - var repeat = motionArgs.repeat - // repeat is equivalent to which column we want to move to! - vim.lastHPos = repeat - 1 - vim.lastHSPos = cm.charCoords(head, 'div').left - return moveToColumn(cm, repeat) - }, - moveToEol: function (cm, head, motionArgs, vim) { - var cur = head - vim.lastHPos = Infinity - var retval = Pos(cur.line + motionArgs.repeat - 1, Infinity) - var end = cm.clipPos(retval) - end.ch-- - vim.lastHSPos = cm.charCoords(end, 'div').left - return retval - }, - moveToFirstNonWhiteSpaceCharacter: function (cm, head) { - // Go to the start of the line where the text begins, or the end for - // whitespace-only lines - var cursor = head - return Pos( - cursor.line, - findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line)) - ) - }, - moveToMatchedSymbol: function (cm, head) { - var cursor = head - var line = cursor.line - var ch = cursor.ch - var lineText = cm.getLine(line) - var symbol - for (; ch < lineText.length; ch++) { - symbol = lineText.charAt(ch) - if (symbol && isMatchableSymbol(symbol)) { - var style = cm.getTokenTypeAt(Pos(line, ch + 1)) - if (style !== 'string' && style !== 'comment') { - break - } - } - } - if (ch < lineText.length) { - var matched = cm.findMatchingBracket(Pos(line, ch)) - return matched.to - } else { - return cursor - } - }, - moveToStartOfLine: function (_cm, head) { - return Pos(head.line, 0) - }, - moveToLineOrEdgeOfDocument: function (cm, _head, motionArgs) { - var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine() - if (motionArgs.repeatIsExplicit) { - lineNum = motionArgs.repeat - cm.getOption('firstLineNumber') - } - return Pos( - lineNum, - findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum)) - ) - }, - textObjectManipulation: function (cm, head, motionArgs, vim) { - // TODO: lots of possible exceptions that can be thrown here. Try da( - // outside of a () block. - - // TODO: adding <> >< to this map doesn't work, presumably because - // they're operators - var mirroredPairs = { - '(': ')', - ')': '(', - '{': '}', - '}': '{', - '[': ']', - ']': '[' - } - var selfPaired = { "'": true, '"': true } - - var character = motionArgs.selectedCharacter - // 'b' refers to '()' block. - // 'B' refers to '{}' block. - if (character == 'b') { - character = '(' - } else if (character == 'B') { - character = '{' - } - - // Inclusive is the difference between a and i - // TODO: Instead of using the additional text object map to perform text - // object operations, merge the map into the defaultKeyMap and use - // motionArgs to define behavior. Define separate entries for 'aw', - // 'iw', 'a[', 'i[', etc. - var inclusive = !motionArgs.textObjectInner - - var tmp - if (mirroredPairs[character]) { - tmp = selectCompanionObject(cm, head, character, inclusive) - } else if (selfPaired[character]) { - tmp = findBeginningAndEnd(cm, head, character, inclusive) - } else if (character === 'W') { - tmp = expandWordUnderCursor( - cm, - inclusive, - true /** forward */, - true /** bigWord */ - ) - } else if (character === 'w') { - tmp = expandWordUnderCursor( - cm, - inclusive, - true /** forward */, - false /** bigWord */ - ) - } else if (character === 'p') { - tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive) - motionArgs.linewise = true - if (vim.visualMode) { - if (!vim.visualLine) { - vim.visualLine = true - } - } else { - var operatorArgs = vim.inputState.operatorArgs - if (operatorArgs) { - operatorArgs.linewise = true - } - tmp.end.line-- - } - } else { - // No text object defined for this, don't move. - return null - } - - if (!cm.state.vim.visualMode) { - return [tmp.start, tmp.end] - } else { - return expandSelection(cm, tmp.start, tmp.end) - } - }, - - repeatLastCharacterSearch: function (cm, head, motionArgs) { - var lastSearch = vimGlobalState.lastCharacterSearch - var repeat = motionArgs.repeat - var forward = motionArgs.forward === lastSearch.forward - var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1) - cm.moveH(-increment, 'char') - motionArgs.inclusive = !!forward - var curEnd = moveToCharacter( - cm, - repeat, - forward, - lastSearch.selectedCharacter - ) - if (!curEnd) { - cm.moveH(increment, 'char') - return head - } - curEnd.ch += increment - return curEnd - } - } - - function defineMotion(name, fn) { - motions[name] = fn - } - - function fillArray(val, times) { - var arr = [] - for (var i = 0; i < times; i++) { - arr.push(val) - } - return arr - } - /** - * An operator acts on a text selection. It receives the list of selections - * as input. The corresponding CodeMirror selection is guaranteed to - * match the input selection. - */ - var operators = { - change: function (cm, args, ranges) { - var finalHead, text - var vim = cm.state.vim - vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = - vim.visualBlock - if (!vim.visualMode) { - var anchor = ranges[0].anchor, - head = ranges[0].head - text = cm.getRange(anchor, head) - var lastState = vim.lastEditInputState || {} - if (lastState.motion == 'moveByWords' && !isWhiteSpaceString(text)) { - // Exclude trailing whitespace if the range is not all whitespace. - var match = /\s+$/.exec(text) - if (match && lastState.motionArgs && lastState.motionArgs.forward) { - head = offsetCursor(head, 0, -match[0].length) - text = text.slice(0, -match[0].length) - } - } - var prevLineEnd = new Pos(anchor.line - 1, Number.MAX_VALUE) - var wasLastLine = cm.firstLine() == cm.lastLine() - if (head.line > cm.lastLine() && args.linewise && !wasLastLine) { - cm.replaceRange('', prevLineEnd, head) - } else { - cm.replaceRange('', anchor, head) - } - if (args.linewise) { - // Push the next line back down, if there is a next line. - if (!wasLastLine) { - cm.setCursor(prevLineEnd) - CodeMirror.commands.newlineAndIndent(cm) - } - // make sure cursor ends up at the end of the line. - anchor.ch = Number.MAX_VALUE - } - finalHead = anchor - } else { - text = cm.getSelection() - var replacement = fillArray('', ranges.length) - cm.replaceSelections(replacement) - finalHead = cursorMin(ranges[0].head, ranges[0].anchor) - } - vimGlobalState.registerController.pushText( - args.registerName, - 'change', - text, - args.linewise, - ranges.length > 1 - ) - actions.enterInsertMode(cm, { head: finalHead }, cm.state.vim) - }, - // delete is a javascript keyword. - delete: function (cm, args, ranges) { - var finalHead, text - var vim = cm.state.vim - if (!vim.visualBlock) { - var anchor = ranges[0].anchor, - head = ranges[0].head - if ( - args.linewise && - head.line != cm.firstLine() && - anchor.line == cm.lastLine() && - anchor.line == head.line - 1 - ) { - // Special case for dd on last line (and first line). - if (anchor.line == cm.firstLine()) { - anchor.ch = 0 - } else { - anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1)) - } - } - text = cm.getRange(anchor, head) - cm.replaceRange('', anchor, head) - finalHead = anchor - if (args.linewise) { - finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor) - } - } else { - text = cm.getSelection() - var replacement = fillArray('', ranges.length) - cm.replaceSelections(replacement) - finalHead = ranges[0].anchor - } - vimGlobalState.registerController.pushText( - args.registerName, - 'delete', - text, - args.linewise, - vim.visualBlock - ) - var includeLineBreak = vim.insertMode - return clipCursorToContent(cm, finalHead, includeLineBreak) - }, - indent: function (cm, args, ranges) { - var vim = cm.state.vim - var startLine = ranges[0].anchor.line - var endLine = vim.visualBlock - ? ranges[ranges.length - 1].anchor.line - : ranges[0].head.line - // In visual mode, n> shifts the selection right n times, instead of - // shifting n lines right once. - var repeat = vim.visualMode ? args.repeat : 1 - if (args.linewise) { - // The only way to delete a newline is to delete until the start of - // the next line, so in linewise mode evalInput will include the next - // line. We don't want this in indent, so we go back a line. - endLine-- - } - for (var i = startLine; i <= endLine; i++) { - for (var j = 0; j < repeat; j++) { - cm.indentLine(i, args.indentRight) - } - } - return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor) - }, - changeCase: function (cm, args, ranges, oldAnchor, newHead) { - var selections = cm.getSelections() - var swapped = [] - var toLower = args.toLower - for (var j = 0; j < selections.length; j++) { - var toSwap = selections[j] - var text = '' - if (toLower === true) { - text = toSwap.toLowerCase() - } else if (toLower === false) { - text = toSwap.toUpperCase() - } else { - for (var i = 0; i < toSwap.length; i++) { - var character = toSwap.charAt(i) - text += isUpperCase(character) - ? character.toLowerCase() - : character.toUpperCase() - } - } - swapped.push(text) - } - cm.replaceSelections(swapped) - if (args.shouldMoveCursor) { - return newHead - } else if ( - !cm.state.vim.visualMode && - args.linewise && - ranges[0].anchor.line + 1 == ranges[0].head.line - ) { - return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor) - } else if (args.linewise) { - return oldAnchor - } else { - return cursorMin(ranges[0].anchor, ranges[0].head) - } - }, - yank: function (cm, args, ranges, oldAnchor) { - var vim = cm.state.vim - var text = cm.getSelection() - var endPos = vim.visualMode - ? cursorMin( - vim.sel.anchor, - vim.sel.head, - ranges[0].head, - ranges[0].anchor - ) - : oldAnchor - vimGlobalState.registerController.pushText( - args.registerName, - 'yank', - text, - args.linewise, - vim.visualBlock - ) - return endPos - } - } - - function defineOperator(name, fn) { - operators[name] = fn - } - - var actions = { - jumpListWalk: function (cm, actionArgs, vim) { - if (vim.visualMode) { - return - } - var repeat = actionArgs.repeat - var forward = actionArgs.forward - var jumpList = vimGlobalState.jumpList - - var mark = jumpList.move(cm, forward ? repeat : -repeat) - var markPos = mark ? mark.find() : undefined - markPos = markPos || cm.getCursor() - cm.setCursor(markPos) - }, - scroll: function (cm, actionArgs, vim) { - if (vim.visualMode) { - return - } - var repeat = actionArgs.repeat || 1 - var lineHeight = cm.defaultTextHeight() - var top = cm.getScrollInfo().top - var delta = lineHeight * repeat - var newPos = actionArgs.forward ? top + delta : top - delta - var cursor = copyCursor(cm.getCursor()) - var cursorCoords = cm.charCoords(cursor, 'local') - if (actionArgs.forward) { - if (newPos > cursorCoords.top) { - cursor.line += (newPos - cursorCoords.top) / lineHeight - cursor.line = Math.ceil(cursor.line) - cm.setCursor(cursor) - cursorCoords = cm.charCoords(cursor, 'local') - cm.scrollTo(null, cursorCoords.top) - } else { - // Cursor stays within bounds. Just reposition the scroll window. - cm.scrollTo(null, newPos) - } - } else { - var newBottom = newPos + cm.getScrollInfo().clientHeight - if (newBottom < cursorCoords.bottom) { - cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight - cursor.line = Math.floor(cursor.line) - cm.setCursor(cursor) - cursorCoords = cm.charCoords(cursor, 'local') - cm.scrollTo( - null, - cursorCoords.bottom - cm.getScrollInfo().clientHeight - ) - } else { - // Cursor stays within bounds. Just reposition the scroll window. - cm.scrollTo(null, newPos) - } - } - }, - scrollToCursor: function (cm, actionArgs) { - var lineNum = cm.getCursor().line - var charCoords = cm.charCoords(Pos(lineNum, 0), 'local') - var height = cm.getScrollInfo().clientHeight - var y = charCoords.top - var lineHeight = charCoords.bottom - y - switch (actionArgs.position) { - case 'center': - y = y - height / 2 + lineHeight - break - case 'bottom': - y = y - height + lineHeight - break - } - cm.scrollTo(null, y) - }, - replayMacro: function (cm, actionArgs, vim) { - var registerName = actionArgs.selectedCharacter - var repeat = actionArgs.repeat - var macroModeState = vimGlobalState.macroModeState - if (registerName == '@') { - registerName = macroModeState.latestRegister - } - while (repeat--) { - executeMacroRegister(cm, vim, macroModeState, registerName) - } - }, - enterMacroRecordMode: function (cm, actionArgs) { - var macroModeState = vimGlobalState.macroModeState - var registerName = actionArgs.selectedCharacter - if (vimGlobalState.registerController.isValidRegister(registerName)) { - macroModeState.enterMacroRecordMode(cm, registerName) - } - }, - toggleOverwrite: function (cm) { - if (!cm.state.overwrite) { - cm.toggleOverwrite(true) - cm.setOption('keyMap', 'vim-replace') - CodeMirror.signal(cm, 'vim-mode-change', { mode: 'replace' }) - } else { - cm.toggleOverwrite(false) - cm.setOption('keyMap', 'vim-insert') - CodeMirror.signal(cm, 'vim-mode-change', { mode: 'insert' }) - } - }, - enterInsertMode: function (cm, actionArgs, vim) { - if (cm.getOption('readOnly')) { - return - } - cm.getWrapperElement().classList.add('insert-mode') - cm.getWrapperElement().classList.remove('visual-mode') - cm.getWrapperElement().classList.remove('normal-mode') - vim.insertMode = true - vim.insertModeRepeat = (actionArgs && actionArgs.repeat) || 1 - var insertAt = actionArgs ? actionArgs.insertAt : null - var sel = vim.sel - var head = actionArgs.head || cm.getCursor('head') - var height = cm.listSelections().length - if (insertAt == 'eol') { - head = Pos(head.line, lineLength(cm, head.line)) - } else if (insertAt == 'charAfter') { - head = offsetCursor(head, 0, 1) - } else if (insertAt == 'firstNonBlank') { - head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head) - } else if (insertAt == 'startOfSelectedArea') { - logger.debug('startOfSelectedArea:', vim.visualBlock) - logger.debug('sel:', JSON.stringify(sel, null, 2)) - if (!vim.visualBlock) { - if (sel.head.line < sel.anchor.line) { - head = sel.head - } else { - head = Pos(sel.anchor.line, 0) - } - } else { - head = Pos( - Math.min(sel.head.line, sel.anchor.line), - Math.min(sel.head.ch, sel.anchor.ch) - ) - height = Math.abs(sel.head.line - sel.anchor.line) + 1 - } - } else if (insertAt == 'endOfSelectedArea') { - if (!vim.visualBlock) { - if (sel.head.line >= sel.anchor.line) { - head = offsetCursor(sel.head, 0, 1) - } else { - head = Pos(sel.anchor.line, 0) - } - } else { - head = Pos( - Math.min(sel.head.line, sel.anchor.line), - Math.max(sel.head.ch + 1, sel.anchor.ch) - ) - height = Math.abs(sel.head.line - sel.anchor.line) + 1 - } - } else if (insertAt == 'inplace') { - if (vim.visualMode) { - return - } - } - cm.setOption('disableInput', false) - if (vim.visualMode) { - exitVisualMode(cm) - } - if (actionArgs && actionArgs.replace) { - // Handle Replace-mode as a special case of insert mode. - cm.toggleOverwrite(true) - cm.setOption('keyMap', 'vim-replace') - CodeMirror.signal(cm, 'vim-mode-change', { mode: 'replace' }) - } else { - cm.toggleOverwrite(false) - cm.setOption('keyMap', 'vim-insert') - CodeMirror.signal(cm, 'vim-mode-change', { mode: 'insert' }) - } - if (!vimGlobalState.macroModeState.isPlaying) { - // Only record if not replaying. - cm.on('change', onChange) - CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown) - } - selectForInsert(cm, head, height) - }, - toggleVisualMode: function (cm, actionArgs, vim) { - logger.debug('toggleVisualMode', actionArgs) - var repeat = actionArgs.repeat - var anchor = cm.getCursor() - var head - // TODO: The repeat should actually select number of characters/lines - // equal to the repeat times the size of the previous visual - // operation. - if (!vim.visualMode) { - // Entering visual mode - vim.visualMode = true - vim.visualLine = !!actionArgs.linewise - vim.visualBlock = !!actionArgs.blockwise - head = clipCursorToContent( - cm, - Pos(anchor.line, anchor.ch + repeat - 1), - true /** includeLineBreak */ - ) - vim.sel = { - anchor: anchor, - head: head - } - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'visual', - subMode: vim.visualLine - ? 'linewise' - : vim.visualBlock - ? 'blockwise' - : '' - }) - updateCmSelection(cm) - updateMark(cm, vim, '<', cursorMin(anchor, head)) - updateMark(cm, vim, '>', cursorMax(anchor, head)) - } else if ( - vim.visualLine ^ actionArgs.linewise || - vim.visualBlock ^ actionArgs.blockwise - ) { - // Toggling between modes - vim.visualLine = !!actionArgs.linewise - vim.visualBlock = !!actionArgs.blockwise - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'visual', - subMode: vim.visualLine - ? 'linewise' - : vim.visualBlock - ? 'blockwise' - : '' - }) - updateCmSelection(cm) - } else { - exitVisualMode(cm) - } - }, - reselectLastSelection: function (cm, _actionArgs, vim) { - var lastSelection = vim.lastSelection - if (vim.visualMode) { - updateLastSelection(cm, vim) - } - if (lastSelection) { - var anchor = lastSelection.anchorMark.find() - var head = lastSelection.headMark.find() - if (!anchor || !head) { - // If the marks have been destroyed due to edits, do nothing. - return - } - vim.sel = { - anchor: anchor, - head: head - } - vim.visualMode = true - vim.visualLine = lastSelection.visualLine - vim.visualBlock = lastSelection.visualBlock - updateCmSelection(cm) - updateMark(cm, vim, '<', cursorMin(anchor, head)) - updateMark(cm, vim, '>', cursorMax(anchor, head)) - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'visual', - subMode: vim.visualLine - ? 'linewise' - : vim.visualBlock - ? 'blockwise' - : '' - }) - } - }, - joinLines: function (cm, actionArgs, vim) { - var curStart, curEnd - if (vim.visualMode) { - curStart = cm.getCursor('anchor') - curEnd = cm.getCursor('head') - if (cursorIsBefore(curEnd, curStart)) { - var tmp = curEnd - curEnd = curStart - curStart = tmp - } - curEnd.ch = lineLength(cm, curEnd.line) - 1 - } else { - // Repeat is the number of lines to join. Minimum 2 lines. - var repeat = Math.max(actionArgs.repeat, 2) - curStart = cm.getCursor() - curEnd = clipCursorToContent( - cm, - Pos(curStart.line + repeat - 1, Infinity) - ) - } - var finalCh = 0 - for (var i = curStart.line; i < curEnd.line; i++) { - finalCh = lineLength(cm, curStart.line) - var tmp = Pos(curStart.line + 1, lineLength(cm, curStart.line + 1)) - var text = cm.getRange(curStart, tmp) - text = text.replace(/\n\s*/g, ' ') - cm.replaceRange(text, curStart, tmp) - } - var curFinalPos = Pos(curStart.line, finalCh) - if (vim.visualMode) { - exitVisualMode(cm, false) - } - cm.setCursor(curFinalPos) - }, - newLineAndEnterInsertMode: function (cm, actionArgs, vim) { - vim.insertMode = true - var insertAt = copyCursor(cm.getCursor()) - if (insertAt.line === cm.firstLine() && !actionArgs.after) { - // Special case for inserting newline before start of document. - cm.replaceRange('\n', Pos(cm.firstLine(), 0)) - cm.setCursor(cm.firstLine(), 0) - } else { - insertAt.line = actionArgs.after ? insertAt.line : insertAt.line - 1 - insertAt.ch = lineLength(cm, insertAt.line) - cm.setCursor(insertAt) - var newlineFn = - CodeMirror.commands.newlineAndIndentContinueComment || - CodeMirror.commands.newlineAndIndent - newlineFn(cm) - } - this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim) - }, - paste: function (cm, actionArgs, vim) { - var cur = copyCursor(cm.getCursor()) - var register = vimGlobalState.registerController.getRegister( - actionArgs.registerName - ) - var text = register.toString() - if (!text) { - return - } - if (actionArgs.matchIndent) { - var tabSize = cm.getOption('tabSize') - // length that considers tabs and tabSize - var whitespaceLength = function (str) { - var tabs = str.split('\t').length - 1 - var spaces = str.split(' ').length - 1 - return tabs * tabSize + spaces * 1 - } - var currentLine = cm.getLine(cm.getCursor().line) - var indent = whitespaceLength(currentLine.match(/^\s*/)[0]) - // chomp last newline b/c don't want it to match /^\s*/gm - var chompedText = text.replace(/\n$/, '') - var wasChomped = text !== chompedText - var firstIndent = whitespaceLength(text.match(/^\s*/)[0]) - var text = chompedText.replace(/^\s*/gm, function (wspace) { - var newIndent = indent + (whitespaceLength(wspace) - firstIndent) - if (newIndent < 0) { - return '' - } else if (cm.getOption('indentWithTabs')) { - var quotient = Math.floor(newIndent / tabSize) - return Array(quotient + 1).join('\t') - } else { - return Array(newIndent + 1).join(' ') - } - }) - text += wasChomped ? '\n' : '' - } - if (actionArgs.repeat > 1) { - var text = Array(actionArgs.repeat + 1).join(text) - } - var linewise = register.linewise - var blockwise = register.blockwise - if (linewise) { - if (vim.visualMode) { - text = vim.visualLine - ? text.slice(0, -1) - : '\n' + text.slice(0, text.length - 1) + '\n' - } else if (actionArgs.after) { - // Move the newline at the end to the start instead, and paste just - // before the newline character of the line we are on right now. - text = '\n' + text.slice(0, text.length - 1) - cur.ch = lineLength(cm, cur.line) - } else { - cur.ch = 0 - } - } else { - if (blockwise) { - text = text.split('\n') - for (var i = 0; i < text.length; i++) { - text[i] = text[i] == '' ? ' ' : text[i] - } - } - cur.ch += actionArgs.after ? 1 : 0 - } - var curPosFinal - var idx - if (vim.visualMode) { - // save the pasted text for reselection if the need arises - vim.lastPastedText = text - var lastSelectionCurEnd - var selectedArea = getSelectedAreaRange(cm, vim) - var selectionStart = selectedArea[0] - var selectionEnd = selectedArea[1] - var selectedText = cm.getSelection() - var selections = cm.listSelections() - var emptyStrings = new Array(selections.length).join('1').split('1') - // save the curEnd marker before it get cleared due to cm.replaceRange. - if (vim.lastSelection) { - lastSelectionCurEnd = vim.lastSelection.headMark.find() - } - // push the previously selected text to unnamed register - vimGlobalState.registerController.unnamedRegister.setText( - selectedText - ) - if (blockwise) { - // first delete the selected text - cm.replaceSelections(emptyStrings) - // Set new selections as per the block length of the yanked text - selectionEnd = Pos( - selectionStart.line + text.length - 1, - selectionStart.ch - ) - cm.setCursor(selectionStart) - selectBlock(cm, selectionEnd) - cm.replaceSelections(text) - curPosFinal = selectionStart - } else if (vim.visualBlock) { - cm.replaceSelections(emptyStrings) - cm.setCursor(selectionStart) - cm.replaceRange(text, selectionStart, selectionStart) - curPosFinal = selectionStart - } else { - cm.replaceRange(text, selectionStart, selectionEnd) - curPosFinal = cm.posFromIndex( - cm.indexFromPos(selectionStart) + text.length - 1 - ) - } - // restore the the curEnd marker - if (lastSelectionCurEnd) { - vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd) - } - if (linewise) { - curPosFinal.ch = 0 - } - } else { - if (blockwise) { - cm.setCursor(cur) - for (var i = 0; i < text.length; i++) { - var line = cur.line + i - if (line > cm.lastLine()) { - cm.replaceRange('\n', Pos(line, 0)) - } - var lastCh = lineLength(cm, line) - if (lastCh < cur.ch) { - extendLineToColumn(cm, line, cur.ch) - } - } - cm.setCursor(cur) - selectBlock(cm, Pos(cur.line + text.length - 1, cur.ch)) - cm.replaceSelections(text) - curPosFinal = cur - } else { - cm.replaceRange(text, cur) - // Now fine tune the cursor to where we want it. - if (linewise && actionArgs.after) { - curPosFinal = Pos( - cur.line + 1, - findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1)) - ) - } else if (linewise && !actionArgs.after) { - curPosFinal = Pos( - cur.line, - findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line)) - ) - } else if (!linewise && actionArgs.after) { - idx = cm.indexFromPos(cur) - curPosFinal = cm.posFromIndex(idx + text.length - 1) - } else { - idx = cm.indexFromPos(cur) - curPosFinal = cm.posFromIndex(idx + text.length) - } - } - } - if (vim.visualMode) { - exitVisualMode(cm, false) - } - cm.setCursor(curPosFinal) - }, - undo: function (cm, actionArgs) { - cm.operation(function () { - repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)() - cm.setCursor(cm.getCursor('anchor')) - }) - }, - redo: function (cm, actionArgs) { - repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)() - }, - setRegister: function (_cm, actionArgs, vim) { - vim.inputState.registerName = actionArgs.selectedCharacter - }, - setMark: function (cm, actionArgs, vim) { - var markName = actionArgs.selectedCharacter - updateMark(cm, vim, markName, cm.getCursor()) - }, - replace: function (cm, actionArgs, vim) { - var replaceWith = actionArgs.selectedCharacter - var curStart = cm.getCursor() - var replaceTo - var curEnd - var selections = cm.listSelections() - if (vim.visualMode) { - curStart = cm.getCursor('start') - curEnd = cm.getCursor('end') - } else { - var line = cm.getLine(curStart.line) - replaceTo = curStart.ch + actionArgs.repeat - if (replaceTo > line.length) { - replaceTo = line.length - } - curEnd = Pos(curStart.line, replaceTo) - } - if (replaceWith == '\n') { - if (!vim.visualMode) - cm.replaceRange('', curStart, curEnd) - // special case, where vim help says to replace by just one line-break - ;( - CodeMirror.commands.newlineAndIndentContinueComment || - CodeMirror.commands.newlineAndIndent - )(cm) - } else { - var replaceWithStr = cm.getRange(curStart, curEnd) - // replace all characters in range by selected, but keep linebreaks - replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith) - if (vim.visualBlock) { - // Tabs are split in visua block before replacing - var spaces = new Array(cm.getOption('tabSize') + 1).join(' ') - replaceWithStr = cm.getSelection() - replaceWithStr = replaceWithStr - .replace(/\t/g, spaces) - .replace(/[^\n]/g, replaceWith) - .split('\n') - cm.replaceSelections(replaceWithStr) - } else { - cm.replaceRange(replaceWithStr, curStart, curEnd) - } - if (vim.visualMode) { - curStart = cursorIsBefore(selections[0].anchor, selections[0].head) - ? selections[0].anchor - : selections[0].head - cm.setCursor(curStart) - exitVisualMode(cm, false) - } else { - cm.setCursor(offsetCursor(curEnd, 0, -1)) - } - } - }, - incrementNumberToken: function (cm, actionArgs) { - var cur = cm.getCursor() - var lineStr = cm.getLine(cur.line) - var re = /-?\d+/g - var match - var start - var end - var numberStr - var token - while ((match = re.exec(lineStr)) !== null) { - token = match[0] - start = match.index - end = start + token.length - if (cur.ch < end) break - } - if (!actionArgs.backtrack && end <= cur.ch) return - if (token) { - var increment = actionArgs.increase ? 1 : -1 - var number = parseInt(token) + increment * actionArgs.repeat - var from = Pos(cur.line, start) - var to = Pos(cur.line, end) - numberStr = number.toString() - cm.replaceRange(numberStr, from, to) - } else { - return - } - cm.setCursor(Pos(cur.line, start + numberStr.length - 1)) - }, - repeatLastEdit: function (cm, actionArgs, vim) { - var lastEditInputState = vim.lastEditInputState - if (!lastEditInputState) { - return - } - var repeat = actionArgs.repeat - if (repeat && actionArgs.repeatIsExplicit) { - vim.lastEditInputState.repeatOverride = repeat - } else { - repeat = vim.lastEditInputState.repeatOverride || repeat - } - repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */) - }, - indent: function (cm, actionArgs) { - cm.indentLine(cm.getCursor().line, actionArgs.indentRight) - }, - exitInsertMode: exitInsertMode - } - - function defineAction(name, fn) { - actions[name] = fn - } - - /* - * Below are miscellaneous utility functions used by vim.js - */ - - /** - * Clips cursor to ensure that line is within the buffer's range - * If includeLineBreak is true, then allow cur.ch == lineLength. - */ - function clipCursorToContent(cm, cur, includeLineBreak) { - var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine()) - var maxCh = lineLength(cm, line) - 1 - maxCh = includeLineBreak ? maxCh + 1 : maxCh - var ch = Math.min(Math.max(0, cur.ch), maxCh) - return Pos(line, ch) - } - function copyArgs(args) { - var ret = {} - for (var prop in args) { - if (args.hasOwnProperty(prop)) { - ret[prop] = args[prop] - } - } - return ret - } - function offsetCursor(cur, offsetLine, offsetCh) { - if (typeof offsetLine === 'object') { - offsetCh = offsetLine.ch - offsetLine = offsetLine.line - } - return Pos(cur.line + offsetLine, cur.ch + offsetCh) - } - function getOffset(anchor, head) { - return { - line: head.line - anchor.line, - ch: head.line - anchor.line - } - } - function commandMatches(keys, keyMap, context, inputState) { - // Partial matches are not applied. They inform the key handler - // that the current key sequence is a subsequence of a valid key - // sequence, so that the key buffer is not cleared. - var match, - partial = [], - full = [] - for (var i = 0; i < keyMap.length; i++) { - var command = keyMap[i] - if ( - (context == 'insert' && command.context != 'insert') || - (command.context && command.context != context) || - (inputState.operator && command.type == 'action') || - !(match = commandMatch(keys, command.keys)) - ) { - continue - } - if (match == 'partial') { - partial.push(command) - } - if (match == 'full') { - full.push(command) - } - } - return { - partial: partial.length && partial, - full: full.length && full - } - } - function commandMatch(pressed, mapped) { - if (mapped.slice(-11) == '') { - // Last character matches anything. - var prefixLen = mapped.length - 11 - var pressedPrefix = pressed.slice(0, prefixLen) - var mappedPrefix = mapped.slice(0, prefixLen) - return pressedPrefix == mappedPrefix && pressed.length > prefixLen - ? 'full' - : mappedPrefix.indexOf(pressedPrefix) == 0 - ? 'partial' - : false - } else { - return pressed == mapped - ? 'full' - : mapped.indexOf(pressed) == 0 - ? 'partial' - : false - } - } - function lastChar(keys) { - var match = /^.*(<[^>]+>)$/.exec(keys) - var selectedCharacter = match ? match[1] : keys.slice(-1) - if (selectedCharacter.length > 1) { - switch (selectedCharacter) { - case '': - selectedCharacter = '\n' - break - case '': - selectedCharacter = ' ' - break - default: - selectedCharacter = '' - break - } - } - return selectedCharacter - } - function repeatFn(cm, fn, repeat) { - return function () { - for (var i = 0; i < repeat; i++) { - fn(cm) - } - } - } - function copyCursor(cur) { - return Pos(cur.line, cur.ch) - } - function cursorEqual(cur1, cur2) { - return cur1.ch == cur2.ch && cur1.line == cur2.line - } - function cursorIsBefore(cur1, cur2) { - if (cur1.line < cur2.line) { - return true - } - if (cur1.line == cur2.line && cur1.ch < cur2.ch) { - return true - } - return false - } - function cursorMin(cur1, cur2) { - if (arguments.length > 2) { - cur2 = cursorMin.apply( - undefined, - Array.prototype.slice.call(arguments, 1) - ) - } - return cursorIsBefore(cur1, cur2) ? cur1 : cur2 - } - function cursorMax(cur1, cur2) { - if (arguments.length > 2) { - cur2 = cursorMax.apply( - undefined, - Array.prototype.slice.call(arguments, 1) - ) - } - return cursorIsBefore(cur1, cur2) ? cur2 : cur1 - } - function cursorIsBetween(cur1, cur2, cur3) { - // returns true if cur2 is between cur1 and cur3. - var cur1before2 = cursorIsBefore(cur1, cur2) - var cur2before3 = cursorIsBefore(cur2, cur3) - return cur1before2 && cur2before3 - } - function lineLength(cm, lineNum) { - return cm.getLine(lineNum).length - } - function trim(s) { - if (s.trim) { - return s.trim() - } - return s.replace(/^\s+|\s+$/g, '') - } - function escapeRegex(s) { - return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1') - } - function extendLineToColumn(cm, lineNum, column) { - var endCh = lineLength(cm, lineNum) - var spaces = new Array(column - endCh + 1).join(' ') - cm.setCursor(Pos(lineNum, endCh)) - cm.replaceRange(spaces, cm.getCursor()) - } - // This functions selects a rectangular block - // of text with selectionEnd as any of its corner - // Height of block: - // Difference in selectionEnd.line and first/last selection.line - // Width of the block: - // Distance between selectionEnd.ch and any(first considered here) selection.ch - function selectBlock(cm, selectionEnd) { - var selections = [], - ranges = cm.listSelections() - var head = copyCursor(cm.clipPos(selectionEnd)) - var isClipped = !cursorEqual(selectionEnd, head) - var curHead = cm.getCursor('head') - var primIndex = getIndex(ranges, curHead) - var wasClipped = cursorEqual( - ranges[primIndex].head, - ranges[primIndex].anchor - ) - var max = ranges.length - 1 - var index = max - primIndex > primIndex ? max : 0 - var base = ranges[index].anchor - - var firstLine = Math.min(base.line, head.line) - var lastLine = Math.max(base.line, head.line) - var baseCh = base.ch, - headCh = head.ch - - var dir = ranges[index].head.ch - baseCh - var newDir = headCh - baseCh - if (dir > 0 && newDir <= 0) { - baseCh++ - if (!isClipped) { - headCh-- - } - } else if (dir < 0 && newDir >= 0) { - baseCh-- - if (!wasClipped) { - headCh++ - } - } else if (dir < 0 && newDir == -1) { - baseCh-- - headCh++ - } - for (var line = firstLine; line <= lastLine; line++) { - var range = { - anchor: new Pos(line, baseCh), - head: new Pos(line, headCh) - } - selections.push(range) - } - cm.setSelections(selections) - selectionEnd.ch = headCh - base.ch = baseCh - return base - } - function selectForInsert(cm, head, height) { - var sel = [] - for (var i = 0; i < height; i++) { - var lineHead = offsetCursor(head, i, 0) - sel.push({ anchor: lineHead, head: lineHead }) - } - cm.setSelections(sel, 0) - } - // getIndex returns the index of the cursor in the selections. - function getIndex(ranges, cursor, end) { - for (var i = 0; i < ranges.length; i++) { - var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor) - var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor) - if (atAnchor || atHead) { - return i - } - } - return -1 - } - function getSelectedAreaRange(cm, vim) { - var lastSelection = vim.lastSelection - var getCurrentSelectedAreaRange = function () { - var selections = cm.listSelections() - var start = selections[0] - var end = selections[selections.length - 1] - var selectionStart = cursorIsBefore(start.anchor, start.head) - ? start.anchor - : start.head - var selectionEnd = cursorIsBefore(end.anchor, end.head) - ? end.head - : end.anchor - return [selectionStart, selectionEnd] - } - var getLastSelectedAreaRange = function () { - var selectionStart = cm.getCursor() - var selectionEnd = cm.getCursor() - var block = lastSelection.visualBlock - if (block) { - var width = block.width - var height = block.height - selectionEnd = Pos( - selectionStart.line + height, - selectionStart.ch + width - ) - var selections = [] - // selectBlock creates a 'proper' rectangular block. - // We do not want that in all cases, so we manually set selections. - for (var i = selectionStart.line; i < selectionEnd.line; i++) { - var anchor = Pos(i, selectionStart.ch) - var head = Pos(i, selectionEnd.ch) - var range = { anchor: anchor, head: head } - selections.push(range) - } - cm.setSelections(selections) - } else { - var start = lastSelection.anchorMark.find() - var end = lastSelection.headMark.find() - var line = end.line - start.line - var ch = end.ch - start.ch - selectionEnd = { - line: selectionEnd.line + line, - ch: line ? selectionEnd.ch : ch + selectionEnd.ch - } - if (lastSelection.visualLine) { - selectionStart = Pos(selectionStart.line, 0) - selectionEnd = Pos( - selectionEnd.line, - lineLength(cm, selectionEnd.line) - ) - } - cm.setSelection(selectionStart, selectionEnd) - } - return [selectionStart, selectionEnd] - } - if (!vim.visualMode) { - // In case of replaying the action. - return getLastSelectedAreaRange() - } else { - return getCurrentSelectedAreaRange() - } - } - // Updates the previous selection with the current selection's values. This - // should only be called in visual mode. - function updateLastSelection(cm, vim) { - var anchor = vim.sel.anchor - var head = vim.sel.head - // To accommodate the effect of lastPastedText in the last selection - if (vim.lastPastedText) { - head = cm.posFromIndex( - cm.indexFromPos(anchor) + vim.lastPastedText.length - ) - vim.lastPastedText = null - } - vim.lastSelection = { - anchorMark: cm.setBookmark(anchor), - headMark: cm.setBookmark(head), - anchor: copyCursor(anchor), - head: copyCursor(head), - visualMode: vim.visualMode, - visualLine: vim.visualLine, - visualBlock: vim.visualBlock - } - } - function expandSelection(cm, start, end) { - var sel = cm.state.vim.sel - var head = sel.head - var anchor = sel.anchor - var tmp - if (cursorIsBefore(end, start)) { - tmp = end - end = start - start = tmp - } - if (cursorIsBefore(head, anchor)) { - head = cursorMin(start, head) - anchor = cursorMax(anchor, end) - } else { - anchor = cursorMin(start, anchor) - head = cursorMax(head, end) - head = offsetCursor(head, 0, -1) - if (head.ch == -1 && head.line != cm.firstLine()) { - head = Pos(head.line - 1, lineLength(cm, head.line - 1)) - } - } - return [anchor, head] - } - /** - * Updates the CodeMirror selection to match the provided vim selection. - * If no arguments are given, it uses the current vim selection state. - */ - function updateCmSelection(cm, sel, mode) { - var vim = cm.state.vim - sel = sel || vim.sel - var mode = - mode || vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char' - var cmSel = makeCmSelection(cm, sel, mode) - cm.setSelections(cmSel.ranges, cmSel.primary) - updateFakeCursor(cm) - } - function makeCmSelection(cm, sel, mode, exclusive) { - var head = copyCursor(sel.head) - var anchor = copyCursor(sel.anchor) - if (mode == 'char') { - var headOffset = - !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0 - var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0 - head = offsetCursor(sel.head, 0, headOffset) - anchor = offsetCursor(sel.anchor, 0, anchorOffset) - return { - ranges: [{ anchor: anchor, head: head }], - primary: 0 - } - } else if (mode == 'line') { - if (!cursorIsBefore(sel.head, sel.anchor)) { - anchor.ch = 0 - - var lastLine = cm.lastLine() - if (head.line > lastLine) { - head.line = lastLine - } - head.ch = lineLength(cm, head.line) - } else { - head.ch = 0 - anchor.ch = lineLength(cm, anchor.line) - } - return { - ranges: [{ anchor: anchor, head: head }], - primary: 0 - } - } else if (mode == 'block') { - var top = Math.min(anchor.line, head.line), - left = Math.min(anchor.ch, head.ch), - bottom = Math.max(anchor.line, head.line), - right = Math.max(anchor.ch, head.ch) + 1 - var height = bottom - top + 1 - var primary = head.line == top ? 0 : height - 1 - var ranges = [] - for (var i = 0; i < height; i++) { - ranges.push({ - anchor: Pos(top + i, left), - head: Pos(top + i, right) - }) - } - return { - ranges: ranges, - primary: primary - } - } - } - function getHead(cm) { - var cur = cm.getCursor('head') - if (cm.getSelection().length == 1) { - // Small corner case when only 1 character is selected. The "real" - // head is the left of head and anchor. - cur = cursorMin(cur, cm.getCursor('anchor')) - } - return cur - } - - /** - * If moveHead is set to false, the CodeMirror selection will not be - * touched. The caller assumes the responsibility of putting the cursor - * in the right place. - */ - function exitVisualMode(cm, moveHead) { - var vim = cm.state.vim - if (moveHead !== false) { - cm.setCursor(clipCursorToContent(cm, vim.sel.head)) - } - updateLastSelection(cm, vim) - vim.visualMode = false - vim.visualLine = false - vim.visualBlock = false - CodeMirror.signal(cm, 'vim-mode-change', { mode: 'normal' }) - if (vim.fakeCursor) { - vim.fakeCursor.clear() - } - } - - // Remove any trailing newlines from the selection. For - // example, with the caret at the start of the last word on the line, - // 'dw' should word, but not the newline, while 'w' should advance the - // caret to the first character of the next line. - function clipToLine(cm, curStart, curEnd) { - var selection = cm.getRange(curStart, curEnd) - // Only clip if the selection ends with trailing newline + whitespace - if (/\n\s*$/.test(selection)) { - var lines = selection.split('\n') - // We know this is all whitespace. - lines.pop() - - // Cases: - // 1. Last word is an empty line - do not clip the trailing '\n' - // 2. Last word is not an empty line - clip the trailing '\n' - var line - // Find the line containing the last word, and clip all whitespace up - // to it. - for ( - var line = lines.pop(); - lines.length > 0 && line && isWhiteSpaceString(line); - line = lines.pop() - ) { - curEnd.line-- - curEnd.ch = 0 - } - // If the last word is not an empty line, clip an additional newline - if (line) { - curEnd.line-- - curEnd.ch = lineLength(cm, curEnd.line) - } else { - curEnd.ch = 0 - } - } - } - - // Expand the selection to line ends. - function expandSelectionToLine(_cm, curStart, curEnd) { - curStart.ch = 0 - curEnd.ch = 0 - curEnd.line++ - } - - function findFirstNonWhiteSpaceCharacter(text) { - if (!text) { - return 0 - } - var firstNonWS = text.search(/\S/) - return firstNonWS == -1 ? text.length : firstNonWS - } - - function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) { - var cur = getHead(cm) - var line = cm.getLine(cur.line) - var idx = cur.ch - - // Seek to first word or non-whitespace character, depending on if - // noSymbol is true. - var test = noSymbol ? wordCharTest[0] : bigWordCharTest[0] - while (!test(line.charAt(idx))) { - idx++ - if (idx >= line.length) { - return null - } - } - - if (bigWord) { - test = bigWordCharTest[0] - } else { - test = wordCharTest[0] - if (!test(line.charAt(idx))) { - test = wordCharTest[1] - } - } - - var end = idx, - start = idx - while (test(line.charAt(end)) && end < line.length) { - end++ - } - while (test(line.charAt(start)) && start >= 0) { - start-- - } - start++ - - if (inclusive) { - // If present, include all whitespace after word. - // Otherwise, include all whitespace before word, except indentation. - var wordEnd = end - while (/\s/.test(line.charAt(end)) && end < line.length) { - end++ - } - if (wordEnd == end) { - var wordStart = start - while (/\s/.test(line.charAt(start - 1)) && start > 0) { - start-- - } - if (!start) { - start = wordStart - } - } - } - return { start: Pos(cur.line, start), end: Pos(cur.line, end) } - } - - function recordJumpPosition(cm, oldCur, newCur) { - if (!cursorEqual(oldCur, newCur)) { - vimGlobalState.jumpList.add(cm, oldCur, newCur) - } - } - - function recordLastCharacterSearch(increment, args) { - vimGlobalState.lastCharacterSearch.increment = increment - vimGlobalState.lastCharacterSearch.forward = args.forward - vimGlobalState.lastCharacterSearch.selectedCharacter = - args.selectedCharacter - } - - var symbolToMode = { - '(': 'bracket', - ')': 'bracket', - '{': 'bracket', - '}': 'bracket', - '[': 'section', - ']': 'section', - '*': 'comment', - '/': 'comment', - m: 'method', - M: 'method', - '#': 'preprocess' - } - var findSymbolModes = { - bracket: { - isComplete: function (state) { - if (state.nextCh === state.symb) { - state.depth++ - if (state.depth >= 1) return true - } else if (state.nextCh === state.reverseSymb) { - state.depth-- - } - return false - } - }, - section: { - init: function (state) { - state.curMoveThrough = true - state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}' - }, - isComplete: function (state) { - return state.index === 0 && state.nextCh === state.symb - } - }, - comment: { - isComplete: function (state) { - var found = state.lastCh === '*' && state.nextCh === '/' - state.lastCh = state.nextCh - return found - } - }, - // TODO: The original Vim implementation only operates on level 1 and 2. - // The current implementation doesn't check for code block level and - // therefore it operates on any levels. - method: { - init: function (state) { - state.symb = state.symb === 'm' ? '{' : '}' - state.reverseSymb = state.symb === '{' ? '}' : '{' - }, - isComplete: function (state) { - if (state.nextCh === state.symb) return true - return false - } - }, - preprocess: { - init: function (state) { - state.index = 0 - }, - isComplete: function (state) { - if (state.nextCh === '#') { - var token = state.lineText.match(/#(\w+)/)[1] - if (token === 'endif') { - if (state.forward && state.depth === 0) { - return true - } - state.depth++ - } else if (token === 'if') { - if (!state.forward && state.depth === 0) { - return true - } - state.depth-- - } - if (token === 'else' && state.depth === 0) return true - } - return false - } - } - } - function findSymbol(cm, repeat, forward, symb) { - var cur = copyCursor(cm.getCursor()) - var increment = forward ? 1 : -1 - var endLine = forward ? cm.lineCount() : -1 - var curCh = cur.ch - var line = cur.line - var lineText = cm.getLine(line) - var state = { - lineText: lineText, - nextCh: lineText.charAt(curCh), - lastCh: null, - index: curCh, - symb: symb, - reverseSymb: (forward - ? { ')': '(', '}': '{' } - : { '(': ')', '{': '}' })[symb], - forward: forward, - depth: 0, - curMoveThrough: false - } - var mode = symbolToMode[symb] - if (!mode) return cur - var init = findSymbolModes[mode].init - var isComplete = findSymbolModes[mode].isComplete - if (init) { - init(state) - } - while (line !== endLine && repeat) { - state.index += increment - state.nextCh = state.lineText.charAt(state.index) - if (!state.nextCh) { - line += increment - state.lineText = cm.getLine(line) || '' - if (increment > 0) { - state.index = 0 - } else { - var lineLen = state.lineText.length - state.index = lineLen > 0 ? lineLen - 1 : 0 - } - state.nextCh = state.lineText.charAt(state.index) - } - if (isComplete(state)) { - cur.line = line - cur.ch = state.index - repeat-- - } - } - if (state.nextCh || state.curMoveThrough) { - return Pos(line, state.index) - } - return cur - } - - /** - * Returns the boundaries of the next word. If the cursor in the middle of - * the word, then returns the boundaries of the current word, starting at - * the cursor. If the cursor is at the start/end of a word, and we are going - * forward/backward, respectively, find the boundaries of the next word. - * - * @param {CodeMirror} cm CodeMirror object. - * @param {Cursor} cur The cursor position. - * @param {boolean} forward True to search forward. False to search - * backward. - * @param {boolean} bigWord True if punctuation count as part of the word. - * False if only [a-zA-Z0-9] characters count as part of the word. - * @param {boolean} emptyLineIsWord True if empty lines should be treated - * as words. - * @return {Object{from:number, to:number, line: number}} The boundaries of - * the word, or null if there are no more words. - */ - function findWord(cm, cur, forward, bigWord, emptyLineIsWord) { - var lineNum = cur.line - var pos = cur.ch - var line = cm.getLine(lineNum) - var dir = forward ? 1 : -1 - var charTests = bigWord ? bigWordCharTest : wordCharTest - - if (emptyLineIsWord && line == '') { - lineNum += dir - line = cm.getLine(lineNum) - if (!isLine(cm, lineNum)) { - return null - } - pos = forward ? 0 : line.length - } - - while (true) { - if (emptyLineIsWord && line == '') { - return { from: 0, to: 0, line: lineNum } - } - var stop = dir > 0 ? line.length : -1 - var wordStart = stop, - wordEnd = stop - // Find bounds of next word. - while (pos != stop) { - var foundWord = false - for (var i = 0; i < charTests.length && !foundWord; ++i) { - if (charTests[i](line.charAt(pos))) { - wordStart = pos - // Advance to end of word. - while (pos != stop && charTests[i](line.charAt(pos))) { - pos += dir - } - wordEnd = pos - foundWord = wordStart != wordEnd - if ( - wordStart == cur.ch && - lineNum == cur.line && - wordEnd == wordStart + dir - ) { - // We started at the end of a word. Find the next one. - continue - } else { - return { - from: Math.min(wordStart, wordEnd + 1), - to: Math.max(wordStart, wordEnd), - line: lineNum - } - } - } - } - if (!foundWord) { - pos += dir - } - } - // Advance to next/prev line. - lineNum += dir - if (!isLine(cm, lineNum)) { - return null - } - line = cm.getLine(lineNum) - pos = dir > 0 ? 0 : line.length - } - } - - /** - * @param {CodeMirror} cm CodeMirror object. - * @param {Pos} cur The position to start from. - * @param {int} repeat Number of words to move past. - * @param {boolean} forward True to search forward. False to search - * backward. - * @param {boolean} wordEnd True to move to end of word. False to move to - * beginning of word. - * @param {boolean} bigWord True if punctuation count as part of the word. - * False if only alphabet characters count as part of the word. - * @return {Cursor} The position the cursor should move to. - */ - function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) { - var curStart = copyCursor(cur) - var words = [] - if ((forward && !wordEnd) || (!forward && wordEnd)) { - repeat++ - } - // For 'e', empty lines are not considered words, go figure. - var emptyLineIsWord = !(forward && wordEnd) - for (var i = 0; i < repeat; i++) { - var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord) - if (!word) { - var eodCh = lineLength(cm, cm.lastLine()) - words.push( - forward - ? { line: cm.lastLine(), from: eodCh, to: eodCh } - : { line: 0, from: 0, to: 0 } - ) - break - } - words.push(word) - cur = Pos(word.line, forward ? word.to - 1 : word.from) - } - var shortCircuit = words.length != repeat - var firstWord = words[0] - var lastWord = words.pop() - if (forward && !wordEnd) { - // w - if ( - !shortCircuit && - (firstWord.from != curStart.ch || firstWord.line != curStart.line) - ) { - // We did not start in the middle of a word. Discard the extra word at the end. - lastWord = words.pop() - } - return Pos(lastWord.line, lastWord.from) - } else if (forward && wordEnd) { - return Pos(lastWord.line, lastWord.to - 1) - } else if (!forward && wordEnd) { - // ge - if ( - !shortCircuit && - (firstWord.to != curStart.ch || firstWord.line != curStart.line) - ) { - // We did not start in the middle of a word. Discard the extra word at the end. - lastWord = words.pop() - } - return Pos(lastWord.line, lastWord.to) - } else { - // b - return Pos(lastWord.line, lastWord.from) - } - } - - function moveToCharacter(cm, repeat, forward, character) { - var cur = cm.getCursor() - var start = cur.ch - var idx - for (var i = 0; i < repeat; i++) { - var line = cm.getLine(cur.line) - idx = charIdxInLine(start, line, character, forward, true) - if (idx == -1) { - return null - } - start = idx - } - return Pos(cm.getCursor().line, idx) - } - - function moveToColumn(cm, repeat) { - // repeat is always >= 1, so repeat - 1 always corresponds - // to the column we want to go to. - var line = cm.getCursor().line - return clipCursorToContent(cm, Pos(line, repeat - 1)) - } - - function updateMark(cm, vim, markName, pos) { - if (!inArray(markName, validMarks)) { - return - } - if (vim.marks[markName]) { - vim.marks[markName].clear() - } - vim.marks[markName] = cm.setBookmark(pos) - } - - function charIdxInLine(start, line, character, forward, includeChar) { - // Search for char in line. - // motion_options: {forward, includeChar} - // If includeChar = true, include it too. - // If forward = true, search forward, else search backwards. - // If char is not found on this line, do nothing - var idx - if (forward) { - idx = line.indexOf(character, start + 1) - if (idx != -1 && !includeChar) { - idx -= 1 - } - } else { - idx = line.lastIndexOf(character, start - 1) - if (idx != -1 && !includeChar) { - idx += 1 - } - } - return idx - } - - function findParagraph(cm, head, repeat, dir, inclusive) { - var line = head.line - var min = cm.firstLine() - var max = cm.lastLine() - var start, - end, - i = line - function isEmpty(i) { - return !cm.getLine(i) - } - function isBoundary(i, dir, any) { - if (any) { - return isEmpty(i) != isEmpty(i + dir) - } - return !isEmpty(i) && isEmpty(i + dir) - } - if (dir) { - while (min <= i && i <= max && repeat > 0) { - if (isBoundary(i, dir)) { - repeat-- - } - i += dir - } - return new Pos(i, 0) - } - - var vim = cm.state.vim - if (vim.visualLine && isBoundary(line, 1, true)) { - var anchor = vim.sel.anchor - if (isBoundary(anchor.line, -1, true)) { - if (!inclusive || anchor.line != line) { - line += 1 - } - } - } - var startState = isEmpty(line) - for (i = line; i <= max && repeat; i++) { - if (isBoundary(i, 1, true)) { - if (!inclusive || isEmpty(i) != startState) { - repeat-- - } - } - } - end = new Pos(i, 0) - // select boundary before paragraph for the last one - if (i > max && !startState) { - startState = true - } else { - inclusive = false - } - for (i = line; i > min; i--) { - if (!inclusive || isEmpty(i) == startState || i == line) { - if (isBoundary(i, -1, true)) { - break - } - } - } - start = new Pos(i, 0) - return { start: start, end: end } - } - - // TODO: perhaps this finagling of start and end positions belonds - // in codemirror/replaceRange? - function selectCompanionObject(cm, head, symb, inclusive) { - var cur = head, - start, - end - - var bracketRegexp = { - '(': /[()]/, - ')': /[()]/, - '[': /[[\]]/, - ']': /[[\]]/, - '{': /[{}]/, - '}': /[{}]/ - }[symb] - var openSym = { - '(': '(', - ')': '(', - '[': '[', - ']': '[', - '{': '{', - '}': '{' - }[symb] - var curChar = cm.getLine(cur.line).charAt(cur.ch) - // Due to the behavior of scanForBracket, we need to add an offset if the - // cursor is on a matching open bracket. - var offset = curChar === openSym ? 1 : 0 - - start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, undefined, { - bracketRegex: bracketRegexp - }) - end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, undefined, { - bracketRegex: bracketRegexp - }) - - if (!start || !end) { - return { start: cur, end: cur } - } - - start = start.pos - end = end.pos - - if ( - (start.line == end.line && start.ch > end.ch) || - start.line > end.line - ) { - var tmp = start - start = end - end = tmp - } - - if (inclusive) { - end.ch += 1 - } else { - start.ch += 1 - } - - return { start: start, end: end } - } - - // Takes in a symbol and a cursor and tries to simulate text objects that - // have identical opening and closing symbols - // TODO support across multiple lines - function findBeginningAndEnd(cm, head, symb, inclusive) { - var cur = copyCursor(head) - var line = cm.getLine(cur.line) - var chars = line.split('') - var start, end, i, len - var firstIndex = chars.indexOf(symb) - - // the decision tree is to always look backwards for the beginning first, - // but if the cursor is in front of the first instance of the symb, - // then move the cursor forward - if (cur.ch < firstIndex) { - cur.ch = firstIndex - // Why is this line even here??? - // cm.setCursor(cur.line, firstIndex+1); - } - // otherwise if the cursor is currently on the closing symbol - else if (firstIndex < cur.ch && chars[cur.ch] == symb) { - end = cur.ch // assign end to the current cursor - --cur.ch // make sure to look backwards - } - - // if we're currently on the symbol, we've got a start - if (chars[cur.ch] == symb && !end) { - start = cur.ch + 1 // assign start to ahead of the cursor - } else { - // go backwards to find the start - for (i = cur.ch; i > -1 && !start; i--) { - if (chars[i] == symb) { - start = i + 1 - } - } - } - - // look forwards for the end symbol - if (start && !end) { - for (i = start, len = chars.length; i < len && !end; i++) { - if (chars[i] == symb) { - end = i - } - } - } - - // nothing found - if (!start || !end) { - return { start: cur, end: cur } - } - - // include the symbols - if (inclusive) { - --start - ++end - } - - return { - start: Pos(cur.line, start), - end: Pos(cur.line, end) - } - } - - // Search functions - defineOption('pcre', true, 'boolean') - function SearchState() {} - SearchState.prototype = { - getQuery: function () { - return vimGlobalState.query - }, - setQuery: function (query) { - vimGlobalState.query = query - }, - getOverlay: function () { - return this.searchOverlay - }, - setOverlay: function (overlay) { - this.searchOverlay = overlay - }, - isReversed: function () { - return vimGlobalState.isReversed - }, - setReversed: function (reversed) { - vimGlobalState.isReversed = reversed - }, - getScrollbarAnnotate: function () { - return this.annotate - }, - setScrollbarAnnotate: function (annotate) { - this.annotate = annotate - } - } - function getSearchState(cm) { - var vim = cm.state.vim - return vim.searchState_ || (vim.searchState_ = new SearchState()) - } - function dialog(cm, template, shortText, onClose, options) { - if (cm.openDialog) { - cm.openDialog(template, onClose, { - bottom: true, - value: options.value, - onKeyDown: options.onKeyDown, - onKeyUp: options.onKeyUp, - selectValueOnOpen: false - }) - } else { - onClose(prompt(shortText, '')) - } - } - function splitBySlash(argString) { - var slashes = findUnescapedSlashes(argString) || [] - if (!slashes.length) return [] - var tokens = [] - // in case of strings like foo/bar - if (slashes[0] !== 0) return - for (var i = 0; i < slashes.length; i++) { - if (typeof slashes[i] === 'number') { - tokens.push(argString.substring(slashes[i] + 1, slashes[i + 1])) - } - } - return tokens - } - - function findUnescapedSlashes(str) { - var escapeNextChar = false - var slashes = [] - for (var i = 0; i < str.length; i++) { - var c = str.charAt(i) - if (!escapeNextChar && c == '/') { - slashes.push(i) - } - escapeNextChar = !escapeNextChar && c == '\\' - } - return slashes - } - - // Translates a search string from ex (vim) syntax into javascript form. - function translateRegex(str) { - // When these match, add a '\' if unescaped or remove one if escaped. - var specials = '|(){' - // Remove, but never add, a '\' for these. - var unescape = '}' - var escapeNextChar = false - var out = [] - for (var i = -1; i < str.length; i++) { - var c = str.charAt(i) || '' - var n = str.charAt(i + 1) || '' - var specialComesNext = n && specials.indexOf(n) != -1 - if (escapeNextChar) { - if (c !== '\\' || !specialComesNext) { - out.push(c) - } - escapeNextChar = false - } else { - if (c === '\\') { - escapeNextChar = true - // Treat the unescape list as special for removing, but not adding '\'. - if (n && unescape.indexOf(n) != -1) { - specialComesNext = true - } - // Not passing this test means removing a '\'. - if (!specialComesNext || n === '\\') { - out.push(c) - } - } else { - out.push(c) - if (specialComesNext && n !== '\\') { - out.push('\\') - } - } - } - } - return out.join('') - } - - // Translates the replace part of a search and replace from ex (vim) syntax into - // javascript form. Similar to translateRegex, but additionally fixes back references - // (translates '\[0..9]' to '$[0..9]') and follows different rules for escaping '$'. - var charUnescapes = { '\\n': '\n', '\\r': '\r', '\\t': '\t' } - function translateRegexReplace(str) { - var escapeNextChar = false - var out = [] - for (var i = -1; i < str.length; i++) { - var c = str.charAt(i) || '' - var n = str.charAt(i + 1) || '' - if (charUnescapes[c + n]) { - out.push(charUnescapes[c + n]) - i++ - } else if (escapeNextChar) { - // At any point in the loop, escapeNextChar is true if the previous - // character was a '\' and was not escaped. - out.push(c) - escapeNextChar = false - } else { - if (c === '\\') { - escapeNextChar = true - if (isNumber(n) || n === '$') { - out.push('$') - } else if (n !== '/' && n !== '\\') { - out.push('\\') - } - } else { - if (c === '$') { - out.push('$') - } - out.push(c) - if (n === '/') { - out.push('\\') - } - } - } - } - return out.join('') - } - - // Unescape \ and / in the replace part, for PCRE mode. - var unescapes = { - '\\/': '/', - '\\\\': '\\', - '\\n': '\n', - '\\r': '\r', - '\\t': '\t' - } - function unescapeRegexReplace(str) { - var stream = new CodeMirror.StringStream(str) - var output = [] - while (!stream.eol()) { - // Search for \. - while (stream.peek() && stream.peek() != '\\') { - output.push(stream.next()) - } - var matched = false - for (var matcher in unescapes) { - if (stream.match(matcher, true)) { - matched = true - output.push(unescapes[matcher]) - break - } - } - if (!matched) { - // Don't change anything - output.push(stream.next()) - } - } - return output.join('') - } - - /** - * Extract the regular expression from the query and return a Regexp object. - * Returns null if the query is blank. - * If ignoreCase is passed in, the Regexp object will have the 'i' flag set. - * If smartCase is passed in, and the query contains upper case letters, - * then ignoreCase is overridden, and the 'i' flag will not be set. - * If the query contains the /i in the flag part of the regular expression, - * then both ignoreCase and smartCase are ignored, and 'i' will be passed - * through to the Regex object. - */ - function parseQuery(query, ignoreCase, smartCase) { - // First update the last search register - var lastSearchRegister = - vimGlobalState.registerController.getRegister('/') - lastSearchRegister.setText(query) - // Check if the query is already a regex. - if (query instanceof RegExp) { - return query - } - // First try to extract regex + flags from the input. If no flags found, - // extract just the regex. IE does not accept flags directly defined in - // the regex string in the form /regex/flags - var slashes = findUnescapedSlashes(query) - var regexPart - var forceIgnoreCase - if (!slashes.length) { - // Query looks like 'regexp' - regexPart = query - } else { - // Query looks like 'regexp/...' - regexPart = query.substring(0, slashes[0]) - var flagsPart = query.substring(slashes[0]) - forceIgnoreCase = flagsPart.indexOf('i') != -1 - } - if (!regexPart) { - return null - } - if (!getOption('pcre')) { - regexPart = translateRegex(regexPart) - } - if (smartCase) { - ignoreCase = /^[^A-Z]*$/.test(regexPart) - } - var regexp = new RegExp( - regexPart, - ignoreCase || forceIgnoreCase ? 'i' : undefined - ) - return regexp - } - function showConfirm(cm, text) { - if (cm.openNotification) { - cm.openNotification('' + text + '', { - bottom: true, - duration: 5000 - }) - } else { - alert(text) - } - } - function makePrompt(prefix, desc) { - var raw = - '' + - (prefix || '') + - '' - if (desc) { - raw += ' ' + desc + '' - } - return raw - } - var searchPromptDesc = '(Javascript regexp)' - function showPrompt(cm, options) { - var shortText = (options.prefix || '') + ' ' + (options.desc || '') - var prompt = makePrompt(options.prefix, options.desc) - dialog(cm, prompt, shortText, options.onClose, options) - } - function regexEqual(r1, r2) { - if (r1 instanceof RegExp && r2 instanceof RegExp) { - var props = ['global', 'multiline', 'ignoreCase', 'source'] - for (var i = 0; i < props.length; i++) { - var prop = props[i] - if (r1[prop] !== r2[prop]) { - return false - } - } - return true - } - return false - } - // Returns true if the query is valid. - function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) { - if (!rawQuery) { - return - } - var state = getSearchState(cm) - var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase) - if (!query) { - return - } - highlightSearchMatches(cm, query) - if (regexEqual(query, state.getQuery())) { - return query - } - state.setQuery(query) - return query - } - function searchOverlay(query) { - if (query.source.charAt(0) == '^') { - var matchSol = true - } - return { - token: function (stream) { - if (matchSol && !stream.sol()) { - stream.skipToEnd() - return - } - var match = stream.match(query, false) - if (match) { - if (match[0].length == 0) { - // Matched empty string, skip to next. - stream.next() - return 'searching' - } - if (!stream.sol()) { - // Backtrack 1 to match \b - stream.backUp(1) - if (!query.exec(stream.next() + match[0])) { - stream.next() - return null - } - } - stream.match(query) - return 'searching' - } - while (!stream.eol()) { - stream.next() - if (stream.match(query, false)) break - } - }, - query: query - } - } - function highlightSearchMatches(cm, query) { - var searchState = getSearchState(cm) - var overlay = searchState.getOverlay() - if (!overlay || query != overlay.query) { - if (overlay) { - cm.removeOverlay(overlay) - } - overlay = searchOverlay(query) - cm.addOverlay(overlay) - if (cm.showMatchesOnScrollbar) { - if (searchState.getScrollbarAnnotate()) { - searchState.getScrollbarAnnotate().clear() - } - searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query)) - } - searchState.setOverlay(overlay) - } - } - function findNext(cm, prev, query, repeat) { - if (repeat === undefined) { - repeat = 1 - } - return cm.operation(function () { - var pos = cm.getCursor() - var cursor = cm.getSearchCursor(query, pos) - for (var i = 0; i < repeat; i++) { - var found = cursor.find(prev) - if (i == 0 && found && cursorEqual(cursor.from(), pos)) { - found = cursor.find(prev) - } - if (!found) { - // SearchCursor may have returned null because it hit EOF, wrap - // around and try again. - cursor = cm.getSearchCursor( - query, - prev ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) - ) - if (!cursor.find(prev)) { - return - } - } - } - return cursor.from() - }) - } - function clearSearchHighlight(cm) { - var state = getSearchState(cm) - cm.removeOverlay(getSearchState(cm).getOverlay()) - state.setOverlay(null) - if (state.getScrollbarAnnotate()) { - state.getScrollbarAnnotate().clear() - state.setScrollbarAnnotate(null) - } - } - /** - * Check if pos is in the specified range, INCLUSIVE. - * Range can be specified with 1 or 2 arguments. - * If the first range argument is an array, treat it as an array of line - * numbers. Match pos against any of the lines. - * If the first range argument is a number, - * if there is only 1 range argument, check if pos has the same line - * number - * if there are 2 range arguments, then check if pos is in between the two - * range arguments. - */ - function isInRange(pos, start, end) { - if (typeof pos !== 'number') { - // Assume it is a cursor position. Get the line number. - pos = pos.line - } - if (start instanceof Array) { - return inArray(pos, start) - } else { - if (end) { - return pos >= start && pos <= end - } else { - return pos == start - } - } - } - function getUserVisibleLines(cm) { - var scrollInfo = cm.getScrollInfo() - var occludeToleranceTop = 6 - var occludeToleranceBottom = 10 - var from = cm.coordsChar( - { left: 0, top: occludeToleranceTop + scrollInfo.top }, - 'local' - ) - var bottomY = - scrollInfo.clientHeight - occludeToleranceBottom + scrollInfo.top - var to = cm.coordsChar({ left: 0, top: bottomY }, 'local') - return { top: from.line, bottom: to.line } - } - - function getMarkPos(cm, vim, markName) { - if (markName == "'") { - var history = cm.doc.history.done - var event = history[history.length - 2] - return event && event.ranges && event.ranges[0].head - } - - var mark = vim.marks[markName] - return mark && mark.find() - } - - var ExCommandDispatcher = function () { - this.buildCommandMap_() - } - ExCommandDispatcher.prototype = { - processCommand: function (cm, input, opt_params) { - var that = this - cm.operation(function () { - cm.curOp.isVimOp = true - that._processCommand(cm, input, opt_params) - }) - }, - _processCommand: function (cm, input, opt_params) { - var vim = cm.state.vim - var commandHistoryRegister = - vimGlobalState.registerController.getRegister(':') - var previousCommand = commandHistoryRegister.toString() - if (vim.visualMode) { - exitVisualMode(cm) - } - var inputStream = new CodeMirror.StringStream(input) - // update ": with the latest command whether valid or invalid - commandHistoryRegister.setText(input) - var params = opt_params || {} - params.input = input - try { - this.parseInput_(cm, inputStream, params) - } catch (e) { - showConfirm(cm, e) - throw e - } - var command - var commandName - if (!params.commandName) { - // If only a line range is defined, move to the line. - if (params.line !== undefined) { - commandName = 'move' - } - } else { - command = this.matchCommand_(params.commandName) - if (command) { - commandName = command.name - if (command.excludeFromCommandHistory) { - commandHistoryRegister.setText(previousCommand) - } - this.parseCommandArgs_(inputStream, params, command) - if (command.type == 'exToKey') { - // Handle Ex to Key mapping. - for (var i = 0; i < command.toKeys.length; i++) { - CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping') - } - return - } else if (command.type == 'exToEx') { - // Handle Ex to Ex mapping. - this.processCommand(cm, command.toInput) - return - } - } - } - if (!commandName) { - showConfirm(cm, 'Not an editor command ":' + input + '"') - return - } - try { - exCommands[commandName](cm, params) - // Possibly asynchronous commands (e.g. substitute, which might have a - // user confirmation), are responsible for calling the callback when - // done. All others have it taken care of for them here. - if ((!command || !command.possiblyAsync) && params.callback) { - params.callback() - } - } catch (e) { - showConfirm(cm, e) - throw e - } - }, - parseInput_: function (cm, inputStream, result) { - inputStream.eatWhile(':') - // Parse range. - if (inputStream.eat('%')) { - result.line = cm.firstLine() - result.lineEnd = cm.lastLine() - } else { - result.line = this.parseLineSpec_(cm, inputStream) - if (result.line !== undefined && inputStream.eat(',')) { - result.lineEnd = this.parseLineSpec_(cm, inputStream) - } - } - - // Parse command name. - var commandMatch = inputStream.match(/^(\w+)/) - if (commandMatch) { - result.commandName = commandMatch[1] - } else { - result.commandName = inputStream.match(/.*/)[0] - } - - return result - }, - parseLineSpec_: function (cm, inputStream) { - var numberMatch = inputStream.match(/^(\d+)/) - if (numberMatch) { - // Absolute line number plus offset (N+M or N-M) is probably a typo, - // not something the user actually wanted. (NB: vim does allow this.) - return parseInt(numberMatch[1], 10) - 1 - } - switch (inputStream.next()) { - case '.': - return this.parseLineSpecOffset_(inputStream, cm.getCursor().line) - case '$': - return this.parseLineSpecOffset_(inputStream, cm.lastLine()) - case "'": - var markName = inputStream.next() - var markPos = getMarkPos(cm, cm.state.vim, markName) - if (!markPos) throw new Error('Mark not set') - return this.parseLineSpecOffset_(inputStream, markPos.line) - case '-': - case '+': - inputStream.backUp(1) - // Offset is relative to current line if not otherwise specified. - return this.parseLineSpecOffset_(inputStream, cm.getCursor().line) - default: - inputStream.backUp(1) - return undefined - } - }, - parseLineSpecOffset_: function (inputStream, line) { - var offsetMatch = inputStream.match(/^([+-])?(\d+)/) - if (offsetMatch) { - var offset = parseInt(offsetMatch[2], 10) - if (offsetMatch[1] == '-') { - line -= offset - } else { - line += offset - } - } - return line - }, - parseCommandArgs_: function (inputStream, params, command) { - if (inputStream.eol()) { - return - } - params.argString = inputStream.match(/.*/)[0] - // Parse command-line arguments - var delim = command.argDelimiter || /\s+/ - var args = trim(params.argString).split(delim) - if (args.length && args[0]) { - params.args = args - } - }, - matchCommand_: function (commandName) { - // Return the command in the command map that matches the shortest - // prefix of the passed in command name. The match is guaranteed to be - // unambiguous if the defaultExCommandMap's shortNames are set up - // correctly. (see @code{defaultExCommandMap}). - for (var i = commandName.length; i > 0; i--) { - var prefix = commandName.substring(0, i) - if (this.commandMap_[prefix]) { - var command = this.commandMap_[prefix] - if (command.name.indexOf(commandName) === 0) { - return command - } - } - } - return null - }, - buildCommandMap_: function () { - this.commandMap_ = {} - for (var i = 0; i < defaultExCommandMap.length; i++) { - var command = defaultExCommandMap[i] - var key = command.shortName || command.name - this.commandMap_[key] = command - } - }, - map: function (lhs, rhs, ctx) { - if (lhs != ':' && lhs.charAt(0) == ':') { - if (ctx) { - throw Error('Mode not supported for ex mappings') - } - var commandName = lhs.substring(1) - if (rhs != ':' && rhs.charAt(0) == ':') { - // Ex to Ex mapping - this.commandMap_[commandName] = { - name: commandName, - type: 'exToEx', - toInput: rhs.substring(1), - user: true - } - } else { - // Ex to key mapping - this.commandMap_[commandName] = { - name: commandName, - type: 'exToKey', - toKeys: rhs, - user: true - } - } - } else { - if (rhs != ':' && rhs.charAt(0) == ':') { - // Key to Ex mapping. - var mapping = { - keys: lhs, - type: 'keyToEx', - exArgs: { input: rhs.substring(1) } - } - if (ctx) { - mapping.context = ctx - } - defaultKeymap.unshift(mapping) - } else { - // Key to key mapping - var mapping = { - keys: lhs, - type: 'keyToKey', - toKeys: rhs - } - if (ctx) { - mapping.context = ctx - } - defaultKeymap.unshift(mapping) - } - } - }, - unmap: function (lhs, ctx) { - if (lhs != ':' && lhs.charAt(0) == ':') { - // Ex to Ex or Ex to key mapping - if (ctx) { - throw Error('Mode not supported for ex mappings') - } - var commandName = lhs.substring(1) - if ( - this.commandMap_[commandName] && - this.commandMap_[commandName].user - ) { - delete this.commandMap_[commandName] - return - } - } else { - // Key to Ex or key to key mapping - var keys = lhs - for (var i = 0; i < defaultKeymap.length; i++) { - if ( - keys == defaultKeymap[i].keys && - defaultKeymap[i].context === ctx - ) { - defaultKeymap.splice(i, 1) - return - } - } - } - throw Error('No such mapping.') - } - } - - var exCommands = { - colorscheme: function (cm, params) { - if (!params.args || params.args.length < 1) { - showConfirm(cm, cm.getOption('theme')) - return - } - cm.setOption('theme', params.args[0]) - }, - map: function (cm, params, ctx) { - var mapArgs = params.args - if (!mapArgs || mapArgs.length < 2) { - if (cm) { - showConfirm(cm, 'Invalid mapping: ' + params.input) - } - return - } - exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx) - }, - imap: function (cm, params) { - this.map(cm, params, 'insert') - }, - nmap: function (cm, params) { - this.map(cm, params, 'normal') - }, - vmap: function (cm, params) { - this.map(cm, params, 'visual') - }, - unmap: function (cm, params, ctx) { - var mapArgs = params.args - if (!mapArgs || mapArgs.length < 1) { - if (cm) { - showConfirm(cm, 'No such mapping: ' + params.input) - } - return - } - exCommandDispatcher.unmap(mapArgs[0], ctx) - }, - move: function (cm, params) { - commandDispatcher.processCommand(cm, cm.state.vim, { - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { forward: false, explicitRepeat: true, linewise: true }, - repeatOverride: params.line + 1 - }) - }, - set: function (cm, params) { - var setArgs = params.args - // Options passed through to the setOption/getOption calls. May be passed in by the - // local/global versions of the set command - var setCfg = params.setCfg || {} - if (!setArgs || setArgs.length < 1) { - if (cm) { - showConfirm(cm, 'Invalid mapping: ' + params.input) - } - return - } - var expr = setArgs[0].split('=') - var optionName = expr[0] - var value = expr[1] - var forceGet = false - - if (optionName.charAt(optionName.length - 1) == '?') { - // If post-fixed with ?, then the set is actually a get. - if (value) { - throw Error('Trailing characters: ' + params.argString) - } - optionName = optionName.substring(0, optionName.length - 1) - forceGet = true - } - if (value === undefined && optionName.substring(0, 2) == 'no') { - // To set boolean options to false, the option name is prefixed with - // 'no'. - optionName = optionName.substring(2) - value = false - } - - var optionIsBoolean = - options[optionName] && options[optionName].type == 'boolean' - if (optionIsBoolean && value == undefined) { - // Calling set with a boolean option sets it to true. - value = true - } - // If no value is provided, then we assume this is a get. - if ((!optionIsBoolean && value === undefined) || forceGet) { - var oldValue = getOption(optionName, cm, setCfg) - if (oldValue instanceof Error) { - showConfirm(cm, oldValue.message) - } else if (oldValue === true || oldValue === false) { - showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName) - } else { - showConfirm(cm, ' ' + optionName + '=' + oldValue) - } - } else { - var setOptionReturn = setOption(optionName, value, cm, setCfg) - if (setOptionReturn instanceof Error) { - showConfirm(cm, setOptionReturn.message) - } - } - }, - setlocal: function (cm, params) { - // setCfg is passed through to setOption - params.setCfg = { scope: 'local' } - this.set(cm, params) - }, - setglobal: function (cm, params) { - // setCfg is passed through to setOption - params.setCfg = { scope: 'global' } - this.set(cm, params) - }, - registers: function (cm, params) { - var regArgs = params.args - var registers = vimGlobalState.registerController.registers - var regInfo = '----------Registers----------

' - if (!regArgs) { - for (var registerName in registers) { - var text = registers[registerName].toString() - if (text.length) { - regInfo += '"' + registerName + ' ' + text + '
' - } - } - } else { - var registerName - regArgs = regArgs.join('') - for (var i = 0; i < regArgs.length; i++) { - registerName = regArgs.charAt(i) - if ( - !vimGlobalState.registerController.isValidRegister(registerName) - ) { - continue - } - var register = registers[registerName] || new Register() - regInfo += - '"' + registerName + ' ' + register.toString() + '
' - } - } - showConfirm(cm, regInfo) - }, - sort: function (cm, params) { - var reverse, ignoreCase, unique, number, pattern - function parseArgs() { - if (params.argString) { - var args = new CodeMirror.StringStream(params.argString) - if (args.eat('!')) { - reverse = true - } - if (args.eol()) { - return - } - if (!args.eatSpace()) { - return 'Invalid arguments' - } - var opts = args.match(/([dinuox]+)?\s*(\/.+\/)?\s*/) - if (!opts && !args.eol()) { - return 'Invalid arguments' - } - if (opts[1]) { - ignoreCase = opts[1].indexOf('i') != -1 - unique = opts[1].indexOf('u') != -1 - var decimal = - opts[1].indexOf('d') != -1 || (opts[1].indexOf('n') != -1 && 1) - var hex = opts[1].indexOf('x') != -1 && 1 - var octal = opts[1].indexOf('o') != -1 && 1 - if (decimal + hex + octal > 1) { - return 'Invalid arguments' - } - number = - (decimal && 'decimal') || (hex && 'hex') || (octal && 'octal') - } - if (opts[2]) { - pattern = new RegExp( - opts[2].substr(1, opts[2].length - 2), - ignoreCase ? 'i' : '' - ) - } - } - } - var err = parseArgs() - if (err) { - showConfirm(cm, err + ': ' + params.argString) - return - } - var lineStart = params.line || cm.firstLine() - var lineEnd = params.lineEnd || params.line || cm.lastLine() - if (lineStart == lineEnd) { - return - } - var curStart = Pos(lineStart, 0) - var curEnd = Pos(lineEnd, lineLength(cm, lineEnd)) - var text = cm.getRange(curStart, curEnd).split('\n') - var numberRegex = - pattern || number == 'decimal' - ? /(-?)([\d]+)/ - : number == 'hex' - ? /(-?)(?:0x)?([0-9a-f]+)/i - : number == 'octal' - ? /([0-7]+)/ - : null - var radix = - number == 'decimal' - ? 10 - : number == 'hex' - ? 16 - : number == 'octal' - ? 8 - : null - var numPart = [], - textPart = [] - if (number || pattern) { - for (var i = 0; i < text.length; i++) { - var matchPart = pattern ? text[i].match(pattern) : null - if (matchPart && matchPart[0] != '') { - numPart.push(matchPart) - } else if (!pattern && numberRegex.exec(text[i])) { - numPart.push(text[i]) - } else { - textPart.push(text[i]) - } - } - } else { - textPart = text - } - function compareFn(a, b) { - if (reverse) { - var tmp - tmp = a - a = b - b = tmp - } - if (ignoreCase) { - a = a.toLowerCase() - b = b.toLowerCase() - } - var anum = number && numberRegex.exec(a) - var bnum = number && numberRegex.exec(b) - if (!anum) { - return a < b ? -1 : 1 - } - anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix) - bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix) - return anum - bnum - } - function comparePatternFn(a, b) { - if (reverse) { - var tmp - tmp = a - a = b - b = tmp - } - if (ignoreCase) { - a[0] = a[0].toLowerCase() - b[0] = b[0].toLowerCase() - } - return a[0] < b[0] ? -1 : 1 - } - numPart.sort(pattern ? comparePatternFn : compareFn) - if (pattern) { - for (var i = 0; i < numPart.length; i++) { - numPart[i] = numPart[i].input - } - } else if (!number) { - textPart.sort(compareFn) - } - text = !reverse ? textPart.concat(numPart) : numPart.concat(textPart) - if (unique) { - // Remove duplicate lines - var textOld = text - var lastLine - text = [] - for (var i = 0; i < textOld.length; i++) { - if (textOld[i] != lastLine) { - text.push(textOld[i]) - } - lastLine = textOld[i] - } - } - cm.replaceRange(text.join('\n'), curStart, curEnd) - }, - global: function (cm, params) { - // a global command is of the form - // :[range]g/pattern/[cmd] - // argString holds the string /pattern/[cmd] - var argString = params.argString - if (!argString) { - showConfirm(cm, 'Regular Expression missing from global') - return - } - // range is specified here - var lineStart = params.line !== undefined ? params.line : cm.firstLine() - var lineEnd = params.lineEnd || params.line || cm.lastLine() - // get the tokens from argString - var tokens = splitBySlash(argString) - var regexPart = argString, - cmd - if (tokens.length) { - regexPart = tokens[0] - cmd = tokens.slice(1, tokens.length).join('/') - } - if (regexPart) { - // If regex part is empty, then use the previous query. Otherwise - // use the regex part as the new query. - try { - updateSearchQuery( - cm, - regexPart, - true /** ignoreCase */, - true /** smartCase */ - ) - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + regexPart) - return - } - } - // now that we have the regexPart, search for regex matches in the - // specified range of lines - var query = getSearchState(cm).getQuery() - var matchedLines = [], - content = '' - for (var i = lineStart; i <= lineEnd; i++) { - var matched = query.test(cm.getLine(i)) - if (matched) { - matchedLines.push(i + 1) - content += cm.getLine(i) + '
' - } - } - // if there is no [cmd], just display the list of matched lines - if (!cmd) { - showConfirm(cm, content) - return - } - var index = 0 - var nextCommand = function () { - if (index < matchedLines.length) { - var command = matchedLines[index] + cmd - exCommandDispatcher.processCommand(cm, command, { - callback: nextCommand - }) - } - index++ - } - nextCommand() - }, - substitute: function (cm, params) { - if (!cm.getSearchCursor) { - throw new Error( - 'Search feature not available. Requires searchcursor.js or ' + - 'any other getSearchCursor implementation.' - ) - } - var argString = params.argString - var tokens = argString ? splitBySlash(argString) : [] - var regexPart, - replacePart = '', - trailing, - flagsPart, - count - var confirm = false // Whether to confirm each replace. - var global = false // True to replace all instances on a line, false to replace only 1. - if (tokens.length) { - regexPart = tokens[0] - replacePart = tokens[1] - if (regexPart && regexPart[regexPart.length - 1] === '$') { - regexPart = regexPart.slice(0, regexPart.length - 1) + '\\n' - replacePart = replacePart ? replacePart + '\n' : '\n' - } - if (replacePart !== undefined) { - if (getOption('pcre')) { - replacePart = unescapeRegexReplace(replacePart) - } else { - replacePart = translateRegexReplace(replacePart) - } - vimGlobalState.lastSubstituteReplacePart = replacePart - } - trailing = tokens[2] ? tokens[2].split(' ') : [] - } else { - // either the argString is empty or its of the form ' hello/world' - // actually splitBySlash returns a list of tokens - // only if the string starts with a '/' - if (argString && argString.length) { - showConfirm( - cm, - 'Substitutions should be of the form ' + ':s/pattern/replace/' - ) - return - } - } - // After the 3rd slash, we can have flags followed by a space followed - // by count. - if (trailing) { - flagsPart = trailing[0] - count = parseInt(trailing[1]) - if (flagsPart) { - if (flagsPart.indexOf('c') != -1) { - confirm = true - flagsPart.replace('c', '') - } - if (flagsPart.indexOf('g') != -1) { - global = true - flagsPart.replace('g', '') - } - regexPart = regexPart + '/' + flagsPart - } - } - if (regexPart) { - // If regex part is empty, then use the previous query. Otherwise use - // the regex part as the new query. - try { - updateSearchQuery( - cm, - regexPart, - true /** ignoreCase */, - true /** smartCase */ - ) - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + regexPart) - return - } - } - replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart - if (replacePart === undefined) { - showConfirm(cm, 'No previous substitute regular expression') - return - } - var state = getSearchState(cm) - var query = state.getQuery() - var lineStart = - params.line !== undefined ? params.line : cm.getCursor().line - var lineEnd = params.lineEnd || lineStart - if (lineStart == cm.firstLine() && lineEnd == cm.lastLine()) { - lineEnd = Infinity - } - if (count) { - lineStart = lineEnd - lineEnd = lineStart + count - 1 - } - var startPos = clipCursorToContent(cm, Pos(lineStart, 0)) - var cursor = cm.getSearchCursor(query, startPos) - doReplace( - cm, - confirm, - global, - lineStart, - lineEnd, - cursor, - query, - replacePart, - params.callback - ) - }, - redo: CodeMirror.commands.redo, - undo: CodeMirror.commands.undo, - write: function (cm) { - if (CodeMirror.commands.save) { - // If a save command is defined, call it. - CodeMirror.commands.save(cm) - } else if (cm.save) { - // Saves to text area if no save command is defined and cm.save() is available. - cm.save() - } - }, - nohlsearch: function (cm) { - clearSearchHighlight(cm) - }, - yank: function (cm) { - var cur = copyCursor(cm.getCursor()) - var line = cur.line - var lineText = cm.getLine(line) - vimGlobalState.registerController.pushText( - '0', - 'yank', - lineText, - true, - true - ) - }, - delmarks: function (cm, params) { - if (!params.argString || !trim(params.argString)) { - showConfirm(cm, 'Argument required') - return - } - - var state = cm.state.vim - var stream = new CodeMirror.StringStream(trim(params.argString)) - while (!stream.eol()) { - stream.eatSpace() - - // Record the streams position at the beginning of the loop for use - // in error messages. - var count = stream.pos - - if (!stream.match(/[a-zA-Z]/, false)) { - showConfirm( - cm, - 'Invalid argument: ' + params.argString.substring(count) - ) - return - } - - var sym = stream.next() - // Check if this symbol is part of a range - if (stream.match('-', true)) { - // This symbol is part of a range. - - // The range must terminate at an alphabetic character. - if (!stream.match(/[a-zA-Z]/, false)) { - showConfirm( - cm, - 'Invalid argument: ' + params.argString.substring(count) - ) - return - } - - var startMark = sym - var finishMark = stream.next() - // The range must terminate at an alphabetic character which - // shares the same case as the start of the range. - if ( - (isLowerCase(startMark) && isLowerCase(finishMark)) || - (isUpperCase(startMark) && isUpperCase(finishMark)) - ) { - var start = startMark.charCodeAt(0) - var finish = finishMark.charCodeAt(0) - if (start >= finish) { - showConfirm( - cm, - 'Invalid argument: ' + params.argString.substring(count) - ) - return - } - - // Because marks are always ASCII values, and we have - // determined that they are the same case, we can use - // their char codes to iterate through the defined range. - for (var j = 0; j <= finish - start; j++) { - var mark = String.fromCharCode(start + j) - delete state.marks[mark] - } - } else { - showConfirm(cm, 'Invalid argument: ' + startMark + '-') - return - } - } else { - // This symbol is a valid mark, and is not part of a range. - delete state.marks[sym] - } - } - } - } - - var exCommandDispatcher = new ExCommandDispatcher() - - /** - * @param {CodeMirror} cm CodeMirror instance we are in. - * @param {boolean} confirm Whether to confirm each replace. - * @param {Cursor} lineStart Line to start replacing from. - * @param {Cursor} lineEnd Line to stop replacing at. - * @param {RegExp} query Query for performing matches with. - * @param {string} replaceWith Text to replace matches with. May contain $1, - * $2, etc for replacing captured groups using Javascript replace. - * @param {function()} callback A callback for when the replace is done. - */ - function doReplace( - cm, - confirm, - global, - lineStart, - lineEnd, - searchCursor, - query, - replaceWith, - callback - ) { - // Set up all the functions. - cm.state.vim.exMode = true - var done = false - var lastPos = searchCursor.from() - function replaceAll() { - cm.operation(function () { - while (!done) { - replace() - next() - } - stop() - }) - } - function replace() { - var text = cm.getRange(searchCursor.from(), searchCursor.to()) - var newText = text.replace(query, replaceWith) - searchCursor.replace(newText) - } - function next() { - // The below only loops to skip over multiple occurrences on the same - // line when 'global' is not true. - while ( - searchCursor.findNext() && - isInRange(searchCursor.from(), lineStart, lineEnd) - ) { - if (!global && lastPos && searchCursor.from().line == lastPos.line) { - continue - } - cm.scrollIntoView(searchCursor.from(), 30) - cm.setSelection(searchCursor.from(), searchCursor.to()) - lastPos = searchCursor.from() - done = false - return - } - done = true - } - function stop(close) { - if (close) { - close() - } - cm.focus() - if (lastPos) { - cm.setCursor(lastPos) - var vim = cm.state.vim - vim.exMode = false - vim.lastHPos = vim.lastHSPos = lastPos.ch - } - if (callback) { - callback() - } - } - function onPromptKeyDown(e, _value, close) { - // Swallow all keys. - CodeMirror.e_stop(e) - var keyName = CodeMirror.keyName(e) - switch (keyName) { - case 'Y': - replace() - next() - break - case 'N': - next() - break - case 'A': - // replaceAll contains a call to close of its own. We don't want it - // to fire too early or multiple times. - var savedCallback = callback - callback = undefined - cm.operation(replaceAll) - callback = savedCallback - break - case 'L': - replace() - // fall through and exit. - case 'Q': - case 'Esc': - case 'Ctrl-C': - case 'Ctrl-[': - stop(close) - break - } - if (done) { - stop(close) - } - return true - } - - // Actually do replace. - next() - if (done) { - showConfirm(cm, 'No matches for ' + query.source) - return - } - if (!confirm) { - replaceAll() - if (callback) { - callback() - } - return - } - showPrompt(cm, { - prefix: 'replace with ' + replaceWith + ' (y/n/a/q/l)', - onKeyDown: onPromptKeyDown - }) - } - - CodeMirror.keyMap.vim = { - attach: attachVimMap, - detach: detachVimMap - // call: cmKey - } - - function exitInsertMode(cm) { - var vim = cm.state.vim - var macroModeState = vimGlobalState.macroModeState - var insertModeChangeRegister = - vimGlobalState.registerController.getRegister('.') - var isPlaying = macroModeState.isPlaying - var lastChange = macroModeState.lastInsertModeChanges - // In case of visual block, the insertModeChanges are not saved as a - // single word, so we convert them to a single word - // so as to update the ". register as expected in real vim. - var text = [] - if (!isPlaying) { - var selLength = lastChange.inVisualBlock - ? vim.lastSelection.visualBlock.height - : 1 - var changes = lastChange.changes - var text = [] - var i = 0 - // In case of multiple selections in blockwise visual, - // the inserted text, for example: 'foo', is stored as - // 'f', 'f', InsertModeKey 'o', 'o', 'o', 'o'. (if you have a block with 2 lines). - // We push the contents of the changes array as per the following: - // 1. In case of InsertModeKey, just increment by 1. - // 2. In case of a character, jump by selLength (2 in the example). - while (i < changes.length) { - // This loop will convert 'ffoooo' to 'foo'. - text.push(changes[i]) - if (changes[i] instanceof InsertModeKey) { - i++ - } else { - i += selLength - } - } - lastChange.changes = text - cm.off('change', onChange) - CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown) - } - if (!isPlaying && vim.insertModeRepeat > 1) { - // Perform insert mode repeat for commands like 3,a and 3,o. - repeatLastEdit( - cm, - vim, - vim.insertModeRepeat - 1, - true /** repeatForInsert */ - ) - vim.lastEditInputState.repeatOverride = vim.insertModeRepeat - } - delete vim.insertModeRepeat - vim.insertMode = false - cm.setCursor(cm.getCursor().line, cm.getCursor().ch - 1) - cm.setOption('keyMap', 'vim') - cm.setOption('disableInput', true) - cm.toggleOverwrite(false) // exit replace mode if we were in it. - // update the ". register before exiting insert mode - insertModeChangeRegister.setText(lastChange.changes.join('')) - CodeMirror.signal(cm, 'vim-mode-change', { mode: 'normal' }) - if (macroModeState.isRecording) { - logInsertModeChange(macroModeState) - } - } - - function _mapCommand(command) { - defaultKeymap.unshift(command) - } - - function mapCommand(keys, type, name, args, extra) { - var command = { keys: keys, type: type } - command[type] = name - command[type + 'Args'] = args - for (var key in extra) { - command[key] = extra[key] - } - _mapCommand(command) - } - - // The timeout in milliseconds for the two-character ESC keymap should be - // adjusted according to your typing speed to prevent false positives. - defineOption('insertModeEscKeysTimeout', 200, 'number') - - CodeMirror.keyMap['vim-insert'] = { - // TODO: override navigation keys so that Esc will cancel automatic - // indentation from o, O, i_ - // fallthrough: ['default'], - fallthrough: [], - attach: attachVimMap, - detach: detachVimMap - // call: cmKey - } - - CodeMirror.keyMap['vim-replace'] = { - Backspace: 'goCharLeft', - fallthrough: ['vim-insert'], - attach: attachVimMap, - detach: detachVimMap - // call: cmKey - } - - function executeMacroRegister(cm, vim, macroModeState, registerName) { - var register = vimGlobalState.registerController.getRegister(registerName) - if (registerName == ':') { - // Read-only register containing last Ex command. - if (register.keyBuffer[0]) { - exCommandDispatcher.processCommand(cm, register.keyBuffer[0]) - } - macroModeState.isPlaying = false - return - } - var keyBuffer = register.keyBuffer - var imc = 0 - macroModeState.isPlaying = true - macroModeState.replaySearchQueries = register.searchQueries.slice(0) - for (var i = 0; i < keyBuffer.length; i++) { - var text = keyBuffer[i] - var match, key - while (text) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - match = /<\w+-.+?>|<\w+>|./.exec(text) - key = match[0] - text = text.substring(match.index + key.length) - CodeMirror.Vim.handleKey(cm, key, 'macro') - if (vim.insertMode) { - var changes = register.insertModeChanges[imc++].changes - vimGlobalState.macroModeState.lastInsertModeChanges.changes = - changes - repeatInsertModeChanges(cm, changes, 1) - exitInsertMode(cm) - } - } - } - macroModeState.isPlaying = false - } - - function logKey(macroModeState, key) { - if (macroModeState.isPlaying) { - return - } - var registerName = macroModeState.latestRegister - var register = vimGlobalState.registerController.getRegister(registerName) - if (register) { - register.pushText(key) - } - } - - function logInsertModeChange(macroModeState) { - if (macroModeState.isPlaying) { - return - } - var registerName = macroModeState.latestRegister - var register = vimGlobalState.registerController.getRegister(registerName) - if (register && register.pushInsertModeChanges) { - register.pushInsertModeChanges(macroModeState.lastInsertModeChanges) - } - } - - function logSearchQuery(macroModeState, query) { - if (macroModeState.isPlaying) { - return - } - var registerName = macroModeState.latestRegister - var register = vimGlobalState.registerController.getRegister(registerName) - if (register && register.pushSearchQuery) { - register.pushSearchQuery(query) - } - } - - /** - * Listens for changes made in insert mode. - * Should only be active in insert mode. - */ - function onChange(cm, changeObj) { - var macroModeState = vimGlobalState.macroModeState - var lastChange = macroModeState.lastInsertModeChanges - if (!macroModeState.isPlaying) { - while (changeObj) { - lastChange.expectCursorActivityForChange = true - if ( - changeObj.origin == '+input' || - changeObj.origin == 'paste' || - changeObj.origin === undefined /* only in testing */ - ) { - var text = changeObj.text.join('\n') - if (lastChange.maybeReset) { - lastChange.changes = [] - lastChange.maybeReset = false - } - if (cm.state.overwrite && !/\n/.test(text)) { - lastChange.changes.push([text]) - } else { - lastChange.changes.push(text) - } - } - // Change objects may be chained with next. - changeObj = changeObj.next - } - } - } - - /** - * Listens for any kind of cursor activity on CodeMirror. - */ - function onCursorActivity(cm) { - var vim = cm.state.vim - if (vim.insertMode) { - // Tracking cursor activity in insert mode (for macro support). - var macroModeState = vimGlobalState.macroModeState - if (macroModeState.isPlaying) { - return - } - var lastChange = macroModeState.lastInsertModeChanges - if (lastChange.expectCursorActivityForChange) { - lastChange.expectCursorActivityForChange = false - } else { - // Cursor moved outside the context of an edit. Reset the change. - lastChange.maybeReset = true - } - } else if (!cm.curOp.isVimOp) { - handleExternalSelection(cm, vim) - } - if (vim.visualMode) { - updateFakeCursor(cm) - } - } - function updateFakeCursor(cm) { - var vim = cm.state.vim - var from = clipCursorToContent(cm, copyCursor(vim.sel.head)) - var to = offsetCursor(from, 0, 1) - if (vim.fakeCursor) { - vim.fakeCursor.clear() - } - vim.fakeCursor = cm.markText(from, to, { - className: 'cm-animate-fat-cursor' - }) - } - function handleExternalSelection(cm, vim) { - var anchor = cm.getCursor('anchor') - var head = cm.getCursor('head') - // Enter or exit visual mode to match mouse selection. - if (vim.visualMode && !cm.somethingSelected()) { - exitVisualMode(cm, false) - } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) { - vim.visualMode = true - vim.visualLine = false - CodeMirror.signal(cm, 'vim-mode-change', { mode: 'visual' }) - } - if (vim.visualMode) { - // Bind CodeMirror selection model to vim selection model. - // Mouse selections are considered visual characterwise. - var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0 - var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0 - head = offsetCursor(head, 0, headOffset) - anchor = offsetCursor(anchor, 0, anchorOffset) - vim.sel = { - anchor: anchor, - head: head - } - updateMark(cm, vim, '<', cursorMin(head, anchor)) - updateMark(cm, vim, '>', cursorMax(head, anchor)) - } else if (!vim.insertMode) { - // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse. - vim.lastHPos = cm.getCursor().ch - } - } - - /** Wrapper for special keys pressed in insert mode */ - function InsertModeKey(keyName) { - this.keyName = keyName - } - - /** - * Handles raw key down events from the text area. - * - Should only be active in insert mode. - * - For recording deletes in insert mode. - */ - function onKeyEventTargetKeyDown(e) { - var macroModeState = vimGlobalState.macroModeState - var lastChange = macroModeState.lastInsertModeChanges - var keyName = CodeMirror.keyName(e) - if (!keyName) { - return - } - function onKeyFound() { - if (lastChange.maybeReset) { - lastChange.changes = [] - lastChange.maybeReset = false - } - lastChange.changes.push(new InsertModeKey(keyName)) - return true - } - if ( - keyName.indexOf('Delete') != -1 || - keyName.indexOf('Backspace') != -1 - ) { - CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound) - } - } - - /** - * Repeats the last edit, which includes exactly 1 command and at most 1 - * insert. Operator and motion commands are read from lastEditInputState, - * while action commands are read from lastEditActionCommand. - * - * If repeatForInsert is true, then the function was called by - * exitInsertMode to repeat the insert mode changes the user just made. The - * corresponding enterInsertMode call was made with a count. - */ - function repeatLastEdit(cm, vim, repeat, repeatForInsert) { - var macroModeState = vimGlobalState.macroModeState - macroModeState.isPlaying = true - var isAction = !!vim.lastEditActionCommand - var cachedInputState = vim.inputState - function repeatCommand() { - if (isAction) { - commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand) - } else { - commandDispatcher.evalInput(cm, vim) - } - } - function repeatInsert(repeat) { - if (macroModeState.lastInsertModeChanges.changes.length > 0) { - // For some reason, repeat cw in desktop VIM does not repeat - // insert mode changes. Will conform to that behavior. - repeat = !vim.lastEditActionCommand ? 1 : repeat - var changeObject = macroModeState.lastInsertModeChanges - repeatInsertModeChanges(cm, changeObject.changes, repeat) - } - } - vim.inputState = vim.lastEditInputState - if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) { - // o and O repeat have to be interlaced with insert repeats so that the - // insertions appear on separate lines instead of the last line. - for (var i = 0; i < repeat; i++) { - repeatCommand() - repeatInsert(1) - } - } else { - if (!repeatForInsert) { - // Hack to get the cursor to end up at the right place. If I is - // repeated in insert mode repeat, cursor will be 1 insert - // change set left of where it should be. - repeatCommand() - } - repeatInsert(repeat) - } - vim.inputState = cachedInputState - if (vim.insertMode && !repeatForInsert) { - // Don't exit insert mode twice. If repeatForInsert is set, then we - // were called by an exitInsertMode call lower on the stack. - exitInsertMode(cm) - } - macroModeState.isPlaying = false - } - - function repeatInsertModeChanges(cm, changes, repeat) { - function keyHandler(binding) { - if (typeof binding === 'string') { - CodeMirror.commands[binding](cm) - } else { - binding(cm) - } - return true - } - var head = cm.getCursor('head') - var inVisualBlock = - vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock - if (inVisualBlock) { - // Set up block selection again for repeating the changes. - var vim = cm.state.vim - var lastSel = vim.lastSelection - var offset = getOffset(lastSel.anchor, lastSel.head) - selectForInsert(cm, head, offset.line + 1) - repeat = cm.listSelections().length - cm.setCursor(head) - } - for (var i = 0; i < repeat; i++) { - if (inVisualBlock) { - cm.setCursor(offsetCursor(head, i, 0)) - } - for (var j = 0; j < changes.length; j++) { - var change = changes[j] - if (change instanceof InsertModeKey) { - CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler) - } else if (typeof change === 'string') { - var cur = cm.getCursor() - cm.replaceRange(change, cur, cur) - } else { - var start = cm.getCursor() - var end = offsetCursor(start, 0, change[0].length) - cm.replaceRange(change[0], start, end) - } - } - } - if (inVisualBlock) { - cm.setCursor(offsetCursor(head, 0, 1)) - } - } - - resetVimGlobalState() - - vimApi.commandDispatcher = commandDispatcher - vimApi.exCommandDispatcher = exCommandDispatcher - return vimApi - } - - // Initialize Vim and make it available as an API. - return (CodeMirror.Vim = Vim()) -} diff --git a/src/vim.js b/src/vim.js index 83a3021..87446b4 100644 --- a/src/vim.js +++ b/src/vim.js @@ -1,8 +1,14 @@ -import { logger } from 'inkdrop' -import vimKeymap from './keymap' -import { CompositeDisposable, Disposable } from 'event-kit' -import CodeMirror from 'codemirror' -import { clipboard } from 'electron' +const { vim, Vim } = require('@replit/codemirror-vim') +const { actions } = require('inkdrop') +const { + registerClipboardTextOnFocus, + registerClipboardText +} = require('./clipboard') + +console.log('module.paths:', module.paths) +console.log('view', require.resolve('@codemirror/view')) +console.log('view::', require('@codemirror/view')) +console.log('registerClipboardTextOnFocus:', registerClipboardTextOnFocus()) class Plugin { config = { @@ -16,1155 +22,20 @@ class Plugin { } activate() { - this.vim = vimKeymap(CodeMirror) - if (inkdrop.isEditorActive()) { - this.activateMode(inkdrop.getActiveEditor()) - } - inkdrop.onEditorLoad(this.handleEditorLoad) + this.Vim = Vim + this.extension = [vim(), registerClipboardTextOnFocus()] + inkdrop.store.dispatch(actions.mde.addExtension(this.extension)) + inkdrop.window.on('focus', this.handleAppFocus) } deactivate() { - if (this.disposables) { - this.disposables.dispose() - } - if (inkdrop.isEditorActive()) { - this.deactivateMode(inkdrop.getActiveEditor()) - } - } - - activateMode(editor) { - const { cm } = editor - this.originalKeyMap = cm.getOption('keyMap') - cm.setOption('keyMap', 'vim') - cm.on('vim-mode-change', this.handleVimModeChange) - cm.on('focus', this.handleFocusEditor) - - const el = cm.getWrapperElement() - el.classList.add('vim-mode', 'normal-mode') - - this.registerCommands() - this.registerExCommands() - } - - deactivateMode(editor) { - const { cm } = editor - if (cm && this.originalKeyMap) { - cm.setOption('keyMap', this.originalKeyMap) - cm.off('vim-mode-change', this.handleVimModeChange) - const el = cm.getWrapperElement() - el.classList.remove('vim-mode') - } - } - - normalizeKeyName(key) { - switch (key) { - case 'Enter': - return 'enter' - case ' ': - return 'space' - case 'ArrowRight': - return 'right' - case 'ArrowLeft': - return 'left' - case 'ArrowUp': - return 'up' - case 'ArrowDown': - return 'down' - default: - if (key.match(/^[A-Z]$/)) { - return `shift-${key}` - } - return key - } - } - - startBufferingKey(command, customBufferingModeClass) { - const wrapper = this.getCodeMirror().getWrapperElement() - logger.debug('Start key buffering') - wrapper.classList.add('key-buffering') - if (customBufferingModeClass) { - wrapper.classList.add('key-buffering-' + customBufferingModeClass) - } - this.pendingCommand = command - } - - stopBufferingKey() { - logger.debug('Stop key buffering') - const wrapper = this.getCodeMirror().getWrapperElement() - const classes = Array.prototype.slice.apply(wrapper.classList) - for (const i of classes) { - if (i.startsWith('key-buffering')) { - wrapper.classList.remove(i) - } - } - this.pendingCommand = undefined - } - - isBufferingKey() { - const wrapper = this.getCodeMirror().getWrapperElement() - return wrapper.classList.contains('key-buffering') - } - - bufferKey(key) { - const cm = this.getCodeMirror() - const vim = this.vim.maybeInitVimState(cm) - const vimKey = this.vim.cmKeyToVimKey("'" + key + "'") - vim.inputState.keyBuffer = vim.inputState.keyBuffer + vimKey - logger.debug('keyBuffer:', vim.inputState.keyBuffer, vim.inputState) - } - - isInsertMode() { - const wrapper = this.getCodeMirror().getWrapperElement() - return wrapper.classList.contains('insert-mode') - } - - registerCommands() { - const disposables = new CompositeDisposable() - const editor = inkdrop.getActiveEditor() - const { cm } = editor - const wrapper = cm.getWrapperElement() - - const doKeyToKey = async command => { - logger.debug('doKeyToKey:', command) - let keys = command.toKeys - while (keys) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - const match = /<\w+-.+?>|<\w+>|./.exec(keys) - let key = match[0] - logger.debug('key:', key) - keys = keys.substring(match.index + key.length) - - if (this.isBufferingKey()) { - this.handleEditorKeyDown(new KeyboardEvent('keydown', { key })) - } else { - if (key.match(/^[A-Z]$/)) { - key = 'shift-' + key - } - const { exactMatchCandidates } = inkdrop.keymaps.findMatchCandidates([ - key - ]) - logger.debug('exactMatchCandidates:', exactMatchCandidates) - const bindings = inkdrop.keymaps.findExactMatches( - exactMatchCandidates, - document.activeElement - ) - const b = bindings[0] - if (b) { - inkdrop.commands.dispatch(document.activeElement, b.command) - } else { - logger.debug('command not found for key:', key) - } - } - } - } - - // bind key to command - const h = command => { - return e => { - logger.debug( - 'command:', - command, - 'state:', - Object.assign({}, cm.state.vim.inputState) - ) - e.stopPropagation() - const vim = this.vim.maybeInitVimState(cm) - return cm.operation(() => { - cm.curOp.isVimOp = true - try { - if (command.type === 'keyToKey') { - doKeyToKey(command) - } else { - this.vim.commandDispatcher.processCommand(cm, vim, command) - } - } catch (e) { - // clear VIM state in case it's in a bad state. - cm.state.vim = undefined - this.vim.maybeInitVimState(cm) - if (!CodeMirror.Vim.suppressErrorLogging) { - console.error(e) - } - throw e - } - return true - }) - } - } - // bind keystroke to command - const b = command => { - return e => { - logger.debug( - 'buffer command:', - command, - 'state:', - Object.assign({}, cm.state.vim.inputState), - e.originalEvent - ) - this.startBufferingKey(h(command), 'command') - this.bufferKey(e.originalEvent.key) - } - } - // bind keystroke to operator - const p = command => { - return e => { - logger.debug( - 'operator command:', - command, - 'state:', - Object.assign({}, cm.state.vim.inputState), - e.originalEvent, - e - ) - const vim = this.vim.maybeInitVimState(cm) - if ( - !vim.inputState.operator && - !this.isBufferingKey() && - !vim.visualMode - ) { - this.startBufferingKey(e => { - const el = cm.getInputField() - const keyName = this.normalizeKeyName(e.key) - const keyBinding = inkdrop.keymaps.findKeyBindings({ - keystrokes: keyName, - target: el - }) - if (keyBinding.length > 0) { - inkdrop.commands.dispatch(el, keyBinding[0].command) - return true - } else { - return false - } - }, 'operator') - if (e.originalEvent) { - this.bufferKey(e.originalEvent.key) - } else { - logger.debug('buffer key:', command.keys) - this.bufferKey(command.keys) - } - } - return h(command)(e) - } - } - const handlers = { - 'vim:native!': () => {}, - 'vim:reset-normal-mode': e => { - CodeMirror.Vim.clearInputState(cm) - this.stopBufferingKey() - e.stopPropagation() - }, - 'vim:exit-visual-mode': e => { - logger.debug('exit-visual-mode') - CodeMirror.Vim.clearInputState(cm) - CodeMirror.Vim.exitVisualMode(cm) - this.stopBufferingKey() - e.stopPropagation() - }, - 'vim:exit-insert-mode': e => { - logger.debug('exit-insert-mode') - CodeMirror.Vim.clearInputState(cm) - CodeMirror.Vim.exitInsertMode(cm) - this.stopBufferingKey() - e.stopPropagation() - }, - 'vim:move-left': h({ - keys: 'h', - type: 'motion', - motion: 'moveByCharacters', - motionArgs: { forward: false } - }), - 'vim:move-right': h({ - keys: 'l', - type: 'motion', - motion: 'moveByCharacters', - motionArgs: { forward: true } - }), - 'vim:move-up': (command => { - return e => { - const seamlessJumpToTitleEnabled = inkdrop.config.get('vim.seamlessJumpToTitle') - const cur = cm.getCursor() - if (cur.line === 0 && cur.ch === 0 && seamlessJumpToTitleEnabled) { - e.stopPropagation() - inkdrop.commands.dispatch(document.body, 'editor:title:focus') - } else { - command(e) - } - } - })( - h({ - keys: 'k', - type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: false, linewise: true } - }) - ), - 'vim:move-down': h({ - keys: 'j', - type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: true, linewise: true } - }), - 'vim:move-up-by-display-lines': h({ - keys: 'gk', - type: 'motion', - motion: 'moveByDisplayLines', - motionArgs: { forward: false } - }), - 'vim:move-down-by-display-lines': h({ - keys: 'gj', - type: 'motion', - motion: 'moveByDisplayLines', - motionArgs: { forward: true } - }), - - 'vim:move-to-next-word': h({ - keys: 'w', - type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: false } - }), - 'vim:move-to-next-whole-word': h({ - keys: 'W', - type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: false, bigWord: true } - }), - 'vim:move-to-end-of-word': h({ - keys: 'e', - type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: true, wordEnd: true, inclusive: true } - }), - 'vim:move-to-previous-end-of-word': h({ - keys: 'ge', - type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: true, inclusive: true } - }), - 'vim:move-to-end-of-whole-word': h({ - keys: 'E', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: true, - wordEnd: true, - bigWord: true, - inclusive: true - } - }), - 'vim:move-to-previous-end-of-whole-word': h({ - keys: 'gE', - type: 'motion', - motion: 'moveByWords', - motionArgs: { - forward: false, - wordEnd: true, - bigWord: true, - inclusive: true - } - }), - 'vim:move-to-previous-word': h({ - keys: 'b', - type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: false } - }), - 'vim:move-to-previous-whole-word': h({ - keys: 'B', - type: 'motion', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: false, bigWord: true } - }), - 'vim:move-to-next-paragraph': h({ - keys: '}', - type: 'motion', - motion: 'moveByParagraph', - motionArgs: { forward: true, toJumplist: true } - }), - 'vim:move-to-previous-paragraph': h({ - keys: '{', - type: 'motion', - motion: 'moveByParagraph', - motionArgs: { forward: false, toJumplist: true } - }), - 'vim:move-to-beginning-of-line-with-zero': (() => { - const handler = h({ - keys: '0', - type: 'motion', - motion: 'moveToStartOfLine' - }) - return e => { - const vim = this.vim.maybeInitVimState(cm) - if (vim.inputState.getRepeat() > 0) { - vim.inputState.pushRepeatDigit('0') - } else { - return handler(e) - } - } - })(), - 'vim:move-to-beginning-of-line': h({ - keys: '0', - type: 'motion', - motion: 'moveToStartOfLine' - }), - 'vim:move-to-first-character-of-line': h({ - keys: '^', - type: 'motion', - motion: 'moveToFirstNonWhiteSpaceCharacter' - }), - 'vim:move-to-first-character-of-line-and-down': h({ - keys: '_', - type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: true, toFirstChar: true, repeatOffset: -1 } - }), - 'vim:move-to-last-character-of-line': h({ - keys: '$', - type: 'motion', - motion: 'moveToEol', - motionArgs: { inclusive: true } - }), - 'vim:move-to-last-nonblank-character-of-line-and-down': () => { - '???' - }, - 'vim:move-to-first-character-of-line-up': h({ - keys: '-', - type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: false, toFirstChar: true } - }), - 'vim:move-to-first-character-of-line-down': h({ - keys: '+', - type: 'motion', - motion: 'moveByLines', - motionArgs: { forward: true, toFirstChar: true } - }), - - 'vim:move-to-start-of-file': h({ - keys: 'gg', - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { - forward: false, - explicitRepeat: true, - linewise: true, - toJumplist: true - } - }), - 'vim:scroll-half-screen-up': h({ - keys: '', - type: 'motion', - motion: 'moveByScroll', - motionArgs: { forward: false, explicitRepeat: true } - }), - 'vim:scroll-full-screen-up': h({ - keys: '', - type: 'motion', - motion: 'moveByPage', - motionArgs: { forward: false } - }), - 'vim:scroll-half-screen-down': h({ - keys: '', - type: 'motion', - motion: 'moveByScroll', - motionArgs: { forward: true, explicitRepeat: true } - }), - 'vim:scroll-full-screen-down': h({ - keys: '', - type: 'motion', - motion: 'moveByPage', - motionArgs: { forward: true } - }), - 'vim:scroll-down': h({ - keys: '', - type: 'action', - action: 'scroll', - actionArgs: { forward: true, linewise: true } - }), - 'vim:scroll-up': h({ - keys: '', - type: 'action', - action: 'scroll', - actionArgs: { forward: false, linewise: true } - }), - 'vim:scroll-cursor-to-top': h({ - keys: 'z', - type: 'action', - action: 'scrollToCursor', - actionArgs: { position: 'top' }, - motion: 'moveToFirstNonWhiteSpaceCharacter' - }), - 'vim:scroll-cursor-to-top-leave': h({ - keys: 'zt', - type: 'action', - action: 'scrollToCursor', - actionArgs: { position: 'top' } - }), - 'vim:scroll-cursor-to-middle': h({ - keys: 'z.', - type: 'action', - action: 'scrollToCursor', - actionArgs: { position: 'center' }, - motion: 'moveToFirstNonWhiteSpaceCharacter' - }), - 'vim:scroll-cursor-to-middle-leave': h({ - keys: 'zz', - type: 'action', - action: 'scrollToCursor', - actionArgs: { position: 'center' } - }), - 'vim:scroll-cursor-to-bottom': h({ - keys: 'z-', - type: 'action', - action: 'scrollToCursor', - actionArgs: { position: 'bottom' } - }), - 'vim:scroll-cursor-to-bottom-leave': h({ - keys: 'zb', - type: 'action', - action: 'scrollToCursor', - actionArgs: { position: 'bottom' }, - motion: 'moveToFirstNonWhiteSpaceCharacter' - }), - 'vim:move-to-line': h({ - keys: 'G', - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { - forward: true, - explicitRepeat: true, - linewise: true, - toJumplist: true - } - }), - 'vim:move-to-top-of-screen': h({ - keys: 'H', - type: 'motion', - motion: 'moveToTopLine', - motionArgs: { linewise: true, toJumplist: true } - }), - 'vim:move-to-bottom-of-screen': h({ - keys: 'L', - type: 'motion', - motion: 'moveToBottomLine', - motionArgs: { linewise: true, toJumplist: true } - }), - 'vim:move-to-middle-of-screen': h({ - keys: 'M', - type: 'motion', - motion: 'moveToMiddleLine', - motionArgs: { linewise: true, toJumplist: true } - }), - - 'vim:delete': p({ keys: 'd', type: 'operator', operator: 'delete' }), - 'vim:delete-to-last-character-of-line': h({ - keys: 'D', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveToEol', - motionArgs: { inclusive: true }, - context: 'normal' - }), - 'vim:change': p({ keys: 'c', type: 'operator', operator: 'change' }), - 'vim:change-to-last-character-of-line': h({ - keys: 'C', - type: 'operatorMotion', - operator: 'change', - motion: 'moveToEol', - motionArgs: { inclusive: true }, - context: 'normal' - }), - 'vim:substitute-line': h({ - keys: 'S', - type: 'keyToKey', - toKeys: 'cc', - context: 'normal' - }), - 'vim:substitute-line-visual': h({ - keys: 'S', - type: 'keyToKey', - toKeys: 'VdO', - context: 'visual' - }), - 'vim:replace': b({ - keys: 'r', - type: 'action', - action: 'replace', - isEdit: true - }), - 'vim:insert-at-beginning-of-line': h({ - keys: 'I', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { insertAt: 'firstNonBlank' }, - context: 'normal' - }), - 'vim:text-object-manipulation-inner': b({ - keys: 'i', - type: 'motion', - motion: 'textObjectManipulation', - motionArgs: { textObjectInner: true } - }), - 'vim:text-object-manipulation': b({ - keys: 'a', - type: 'motion', - motion: 'textObjectManipulation' - }), - 'vim:indent': p({ - keys: '>', - type: 'operator', - operator: 'indent', - operatorArgs: { indentRight: true } - }), - 'vim:outdent': p({ - keys: '<', - type: 'operator', - operator: 'indent', - operatorArgs: { indentRight: false } - }), - 'vim:auto-indent': () => { - 'not supported' - }, - 'vim:reselect-last-selection': h({ - keys: 'gv', - type: 'action', - action: 'reselectLastSelection' - }), - 'vim:join': h({ - keys: 'J', - type: 'action', - action: 'joinLines', - isEdit: true - }), - - 'vim:yank': p({ keys: 'y', type: 'operator', operator: 'yank' }), - 'vim:yank-line': h({ - keys: 'Y', - type: 'operatorMotion', - operator: 'yank', - motion: 'expandToLine', - motionArgs: { linewise: true }, - context: 'normal' - }), - 'vim:put-before': h({ - keys: 'P', - type: 'action', - action: 'paste', - isEdit: true, - actionArgs: { after: false, isEdit: true } - }), - 'vim:put-after': h({ - keys: 'p', - type: 'action', - action: 'paste', - isEdit: true, - actionArgs: { after: true, isEdit: true } - }), - - 'vim:toggle-case': h({ - keys: 'g~', - type: 'operator', - operator: 'changeCase' - }), - 'vim:upper-case': h({ - keys: 'gU', - type: 'operator', - operator: 'changeCase', - operatorArgs: { toLower: false }, - isEdit: true - }), - 'vim:lower-case': h({ - keys: 'gu', - type: 'operator', - operator: 'changeCase', - operatorArgs: { toLower: true }, - isEdit: true - }), - 'vim:toggle-case-now': h({ - keys: '~', - type: 'operatorMotion', - operator: 'changeCase', - motion: 'moveByCharacters', - motionArgs: { forward: true }, - operatorArgs: { shouldMoveCursor: true }, - context: 'normal' - }), - - 'vim:mark': b({ - keys: 'm', - type: 'action', - action: 'setMark' - }), - 'vim:move-to-mark-literal': b({ - keys: '`', - type: 'motion', - motion: 'goToMark', - motionArgs: { toJumplist: true } - }), - 'vim:move-to-mark': b({ - keys: "'", - type: 'motion', - motion: 'goToMark', - motionArgs: { toJumplist: true, linewise: true } - }), - - 'vim:find': b({ - keys: 'f', - type: 'motion', - motion: 'moveToCharacter', - motionArgs: { forward: true, inclusive: true } - }), - 'vim:find-backwards': b({ - keys: 'F', - type: 'motion', - motion: 'moveToCharacter', - motionArgs: { forward: false } - }), - 'vim:till': b({ - keys: 't', - type: 'motion', - motion: 'moveTillCharacter', - motionArgs: { forward: true, inclusive: true } - }), - 'vim:till-backwards': b({ - keys: 'T', - type: 'motion', - motion: 'moveTillCharacter', - motionArgs: { forward: false } - }), - 'vim:repeat-find': h({ - keys: ';', - type: 'motion', - motion: 'repeatLastCharacterSearch', - motionArgs: { forward: true } - }), - 'vim:repeat-find-reverse': h({ - keys: ',', - type: 'motion', - motion: 'repeatLastCharacterSearch', - motionArgs: { forward: false } - }), - - 'vim:search': h({ - keys: '/', - type: 'search', - searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true } - }), - 'vim:reverse-search': h({ - keys: '?', - type: 'search', - searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true } - }), - 'vim:search-current-word': h({ - keys: '*', - type: 'search', - searchArgs: { - forward: true, - querySrc: 'wordUnderCursor', - wholeWordOnly: true, - toJumplist: true - } - }), - 'vim:reverse-search-current-word': h({ - keys: '#', - type: 'search', - searchArgs: { - forward: false, - querySrc: 'wordUnderCursor', - wholeWordOnly: true, - toJumplist: true - } - }), - 'vim:repeat-search': h({ - keys: 'n', - type: 'motion', - motion: 'findNext', - motionArgs: { forward: true, toJumplist: true } - }), - 'vim:repeat-search-backwards': h({ - keys: 'N', - type: 'motion', - motion: 'findNext', - motionArgs: { forward: false, toJumplist: true } - }), - - 'vim:bracket-matching-motion': h({ - keys: '%', - type: 'motion', - motion: 'moveToMatchedSymbol', - motionArgs: { inclusive: true, toJumplist: true } - }), - - 'vim:ex-command': h({ keys: ':', type: 'ex' }), - - // normal mode - 'vim:activate-insert-mode': h({ - keys: 'i', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { insertAt: 'inplace' }, - context: 'normal' - }), - 'vim:activate-replace-mode': h({ - keys: 'R', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { replace: true } - }), - 'vim:activate-characterwise-visual-mode': h({ - keys: 'v', - type: 'action', - action: 'toggleVisualMode' - }), - 'vim:activate-linewise-visual-mode': h({ - keys: 'V', - type: 'action', - action: 'toggleVisualMode', - actionArgs: { linewise: true } - }), - 'vim:activate-blockwise-visual-mode': h({ - keys: '', - type: 'action', - action: 'toggleVisualMode', - actionArgs: { blockwise: true } - }), - - 'vim:undo': h({ - keys: 'u', - type: 'action', - action: 'undo', - context: 'normal' - }), - - 'vim:insert-above-with-newline': h({ - keys: 'O', - type: 'action', - action: 'newLineAndEnterInsertMode', - isEdit: true, - interlaceInsertRepeat: true, - actionArgs: { after: false }, - context: 'normal' - }), - 'vim:insert-below-with-newline': h({ - keys: 'o', - type: 'action', - action: 'newLineAndEnterInsertMode', - isEdit: true, - interlaceInsertRepeat: true, - actionArgs: { after: true }, - context: 'normal' - }), - 'vim:insert-after': h({ - keys: 'a', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { insertAt: 'charAfter' }, - context: 'normal' - }), - 'vim:insert-after-end-of-line': h({ - keys: 'A', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { insertAt: 'eol' }, - context: 'normal' - }), - 'vim:delete-right': h({ - keys: 'x', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveByCharacters', - motionArgs: { forward: true }, - operatorMotionArgs: { visualLine: false } - }), - 'vim:delete-left': h({ - keys: 'X', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveByCharacters', - motionArgs: { forward: false }, - operatorMotionArgs: { visualLine: true } - }), - 'vim:substitute': h({ - keys: 's', - type: 'keyToKey', - toKeys: 'cl', - context: 'normal' - }), - 'vim:substitute-visual': h({ - keys: 's', - type: 'keyToKey', - toKeys: 'c', - context: 'visual' - }), - 'vim:repeat': h({ - keys: '.', - type: 'action', - action: 'repeatLastEdit' - }), - - 'vim:increase': h({ - keys: '', - type: 'action', - action: 'incrementNumberToken', - isEdit: true, - actionArgs: { increase: true, backtrack: false } - }), - 'vim:decrease': h({ - keys: '', - type: 'action', - action: 'incrementNumberToken', - isEdit: true, - actionArgs: { increase: false, backtrack: false } - }), - - 'vim:register-prefix': b({ - keys: '"', - type: 'action', - action: 'setRegister' - }), - - // insert mode - 'vim:delete-to-beginning-of-word': h({ - keys: '', - type: 'operatorMotion', - operator: 'delete', - motion: 'moveByWords', - motionArgs: { forward: false, wordEnd: false }, - context: 'insert' - }), - - // visual mode - 'vim:insert-at-start-of-target': h({ - keys: 'I', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { insertAt: 'startOfSelectedArea' }, - context: 'visual' - }), - 'vim:insert-at-end-of-target': h({ - keys: 'A', - type: 'action', - action: 'enterInsertMode', - isEdit: true, - actionArgs: { insertAt: 'endOfSelectedArea' }, - context: 'visual' - }), - 'vim:reverse-selections': h({ - keys: 'o', - type: 'motion', - motion: 'moveToOtherHighlightedEnd', - context: 'visual' - }), - 'vim:reverse-selections-at-same-line': h({ - keys: 'O', - type: 'motion', - motion: 'moveToOtherHighlightedEnd', - motionArgs: { sameLine: true }, - context: 'visual' - }) - } - disposables.add(inkdrop.commands.add(wrapper, handlers)) - disposables.add( - inkdrop.commands.add(document.querySelector('.mde-preview'), { - 'vim:move-to-start-of-file': ({ target }) => { - target.scrollTop = 0 - }, - 'vim:scroll-up': ({ target }) => { - target.scrollTop -= 30 - }, - 'vim:scroll-down': ({ target }) => { - target.scrollTop += 30 - }, - 'vim:scroll-half-screen-up': ({ target }) => { - target.scrollTop -= target.clientHeight / 2 - }, - 'vim:scroll-half-screen-down': ({ target }) => { - target.scrollTop += target.clientHeight / 2 - }, - 'vim:scroll-full-screen-up': ({ target }) => { - target.scrollTop -= target.clientHeight - }, - 'vim:scroll-full-screen-down': ({ target }) => { - target.scrollTop += target.clientHeight - }, - 'vim:move-to-line': ({ target }) => { - target.scrollTop = target.scrollHeight - } - }) - ) - wrapper.addEventListener('textInput', this.handleEditorTextInput) - wrapper.addEventListener('keydown', this.handleEditorKeyDown) - disposables.add( - new Disposable(() => - wrapper.removeEventListener('keydown', this.handleEditorKeyDown) - ) - ) - - this.disposables = disposables - } - - registerExCommands() { - const el = this.getCodeMirror().getWrapperElement() - this.vim.defineEx('write', 'w', () => { - inkdrop.commands.dispatch(el, 'core:save-note') - }) - this.vim.defineEx('next', 'n', () => { - inkdrop.commands.dispatch(el, 'core:open-next-note') - }) - this.vim.defineEx('prev', '', () => { - inkdrop.commands.dispatch(el, 'core:open-prev-note') - }) - this.vim.defineEx('preview', 'p', () => { - inkdrop.commands.dispatch(el, 'view:toggle-preview') - }) - this.vim.defineEx('side-by-side', 'side', () => { - inkdrop.commands.dispatch(el, 'view:toggle-side-by-side') - }) - } - - getCodeMirror() { - return inkdrop.getActiveEditor().cm - } - - yankClipboard() { - const state = this.vim.getVimGlobalState() - const text = clipboard.readText() - const linewise = text.indexOf('\n') >= 0 - state.registerController.pushText('0', 'yank', text, linewise, true) - } - - handleEditorLoad = editor => { - this.activateMode(editor) - } - - handleVimModeChange = (event, _opt) => { - logger.debug('vim mode changed:', event) - const { mode } = event - const cm = this.getCodeMirror() - cm.getWrapperElement().classList.remove('insert-mode') - cm.getWrapperElement().classList.remove('visual-mode') - cm.getWrapperElement().classList.remove('normal-mode') - cm.getWrapperElement().classList.remove('replace-mode') - switch (mode) { - case 'normal': - cm.getWrapperElement().classList.add('normal-mode') - break - case 'visual': - cm.getWrapperElement().classList.add('visual-mode') - break - case 'replace': - cm.getWrapperElement().classList.add('replace-mode') - break - case 'insert': - cm.getWrapperElement().classList.add('insert-mode') - break - } - } - - handleEditorTextInput = event => { - // only process if the event is fired via EventTarget.dispatchEvent() - if (this.isInsertMode() && !event.isTrusted) { - logger.debug('handle text input:', event) - const text = event.data - const cm = this.getCodeMirror() - cm.replaceSelection(text) - } - } - - handleEditorKeyDown = event => { - const keyName = this.normalizeKeyName(event.key) - const cm = this.getCodeMirror() - const vim = this.vim.maybeInitVimState(cm) - const isNumeric = - !event.ctrlKey && - !event.altKey && - !event.metaKey && - !event.shiftKey && - keyName.match(/^\d$/) - - const target = cm.getInputField() - const currentKeyStroke = [ - ...inkdrop.keymaps.queuedKeystrokes.filter(k => !k.startsWith('^')), - keyName - ] - const { partialMatchCandidates, exactMatchCandidates } = - inkdrop.keymaps.findMatchCandidates(currentKeyStroke) - const partialMatches = inkdrop.keymaps.findPartialMatches( - partialMatchCandidates, - target - ) - const exactMatches = inkdrop.keymaps.findExactMatches( - exactMatchCandidates, - target - ) - logger.debug('handleEditorKeyDown: currentKeyStroke:', currentKeyStroke) - logger.debug('handleEditorKeyDown: exactMatches:', exactMatches) - logger.debug('handleEditorKeyDown: partialMatches:', partialMatches) - - if (this.isBufferingKey()) { - logger.debug('handleEditorKeyDown: handle key buffering:', keyName, event) - const b = cm - .getInputField() - .webkitMatchesSelector( - '.CodeMirror.vim-mode:not(.insert-mode) textarea' - ) - logger.debug('handleEditorKeyDown: keybinding check:', exactMatches, b) - - if ( - keyName !== 'Ctrl' && - keyName !== 'Alt' && - keyName !== 'Shift' && - keyName !== 'Meta' - ) { - const { inputState } = vim - const hasOperatorOrMotion = inputState.motion || inputState.operator - if ( - (event.key.length === 1 || keyName === 'space') && - (!isNumeric || !hasOperatorOrMotion) - ) { - inputState.selectedCharacter = event.key - inputState.keyBuffer = '' - - if (exactMatches.length === 0 && partialMatches.length === 0) { - const { pendingCommand } = this - this.stopBufferingKey() - - if (typeof pendingCommand === 'function') { - if (pendingCommand(event)) { - event.stopPropagation() - event.preventDefault() - } - } - } - } else if (isNumeric) { - vim.inputState.pushRepeatDigit(keyName) - } - } - } else if (!this.isInsertMode()) { - if (isNumeric) { - if (exactMatches.length === 0) { - vim.inputState.pushRepeatDigit(keyName) - } - } else { - // push key buffer to the repeat digit - const keys = vim.inputState.keyBuffer - vim.inputState.keyBuffer = '' - const keysMatcher = /^(\d*)(.*)$/.exec(keys) - if (keysMatcher[1] && keysMatcher[1] !== '0') { - vim.inputState.pushRepeatDigit(keysMatcher[1]) - } - } - } + inkdrop.store.dispatch(actions.mde.removeExtension(this.extension)) + this.extension = null + inkdrop.window.off('focus', this.handleAppFocus) } - handleFocusEditor = _event => { - this.yankClipboard() + handleAppFocus() { + registerClipboardText() } } diff --git a/styles/vim.css b/styles/vim.css new file mode 100644 index 0000000..221a33e --- /dev/null +++ b/styles/vim.css @@ -0,0 +1,8 @@ +.editor .mde .cm-editor .cm-scroller.cm-vimMode { + .cm-fat-cursor { + background: var(--editor-caret-color) !important; + } + &:not(.cm-focused) .cm-fat-cursor { + outline: solid 1px var(--editor-caret-color) !important; + } +} diff --git a/styles/vim.less b/styles/vim.less deleted file mode 100644 index 9534aad..0000000 --- a/styles/vim.less +++ /dev/null @@ -1,2 +0,0 @@ -.vim { -} From 86b90f17ecfbbbdc8ea9db80e47dd4bb8c023f10 Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Mon, 2 Jun 2025 15:08:40 +0900 Subject: [PATCH 02/13] feat(ex): add ex commands --- src/ex.js | 17 +++++++++++++++++ src/vim.js | 6 +----- 2 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 src/ex.js diff --git a/src/ex.js b/src/ex.js new file mode 100644 index 0000000..3120da5 --- /dev/null +++ b/src/ex.js @@ -0,0 +1,17 @@ +const { vim, Vim } = require('@replit/codemirror-vim') + +Vim.defineEx('write', 'w', () => { + inkdrop.commands.dispatch(document.body, 'core:save-note') +}) +Vim.defineEx('next', 'n', () => { + inkdrop.commands.dispatch(document.body, 'core:open-next-note') +}) +Vim.defineEx('prev', '', () => { + inkdrop.commands.dispatch(document.body, 'core:open-prev-note') +}) +Vim.defineEx('preview', 'p', () => { + inkdrop.commands.dispatch(document.body, 'view:toggle-preview') +}) +Vim.defineEx('side-by-side', 'side', () => { + inkdrop.commands.dispatch(document.body, 'view:toggle-side-by-side') +}) diff --git a/src/vim.js b/src/vim.js index 87446b4..19e8cfa 100644 --- a/src/vim.js +++ b/src/vim.js @@ -4,11 +4,7 @@ const { registerClipboardTextOnFocus, registerClipboardText } = require('./clipboard') - -console.log('module.paths:', module.paths) -console.log('view', require.resolve('@codemirror/view')) -console.log('view::', require('@codemirror/view')) -console.log('registerClipboardTextOnFocus:', registerClipboardTextOnFocus()) +require('./ex') class Plugin { config = { From 31ff6a9604123b218073db7234d4a4d7a4b10172 Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Mon, 2 Jun 2025 15:14:46 +0900 Subject: [PATCH 03/13] docs(readme): update --- README.md | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 9b078fb..fbe8564 100644 --- a/README.md +++ b/README.md @@ -24,19 +24,20 @@ ipm install vim ## Key customizations -Default vim keymaps are defined [here](https://github.com/inkdropapp/inkdrop-vim/blob/master/keymaps/vim.json) and you can override them in your `keymap.cson` file. +You can customize keybindings in your [init.js](https://developers.inkdrop.app/guides/the-init-file). +For example, -CSS selectors for each mode: - -- Not insert mode: `.CodeMirror.vim-mode:not(.insert-mode):not(.key-buffering) textarea` -- Normal mode: `.CodeMirror.vim-mode.normal-mode:not(.key-buffering) textarea` -- Insert mode: `.CodeMirror.vim-mode.insert-mode textarea` -- Replace mode: `.CodeMirror.vim-mode.replace-mode textarea` -- Visual mode: `.CodeMirror.vim-mode.visual-mode:not(.key-buffering) textarea` - -You can check current keybindings on the _Keybindings_ pane on preferences window: +```js +inkdrop.onEditorLoad(() => { + const Vim = inkdrop.packages.getLoadedPackage('vim').mainModule.Vim -![Preferences](https://raw.githubusercontent.com/inkdropapp/inkdrop-vim/master/docs/preferences.png) + // Map keys + Vim.map('jj', '', 'insert') // in insert mode + Vim.map('Y', 'y$') // in normal mode + // Unmap keys + Vim.unmap('jj', 'insert') +}) +``` ## Ex Commands @@ -67,8 +68,8 @@ The following example defines `:find` command: ```js inkdrop.onEditorLoad(() => { - var CodeMirror = require('codemirror') - CodeMirror.Vim.defineEx('find', 'f', (cm, event) => { + const Vim = inkdrop.packages.getLoadedPackage('vim').mainModule.Vim + Vim.defineEx('find', 'f', (cm, event) => { inkdrop.commands.dispatch(document.body, 'core:find-global') if (event.argString) inkdrop.commands.dispatch(document.body, 'core:search-notes', { @@ -78,15 +79,6 @@ inkdrop.onEditorLoad(() => { }) ``` -## Options - -![options](./docs/options.png) - -### Seamlessly jump to note title - -Whether moving focus seamlessly from the editor to the note title bar by `vim:move-up` command - ## Changelog See the [GitHub releases](https://github.com/inkdropapp/inkdrop-vim/releases) for an overview of what changed in each update. -See [CHANGELOG.md](https://github.com/inkdropapp/inkdrop-vim/blob/master/CHANGELOG.md) for older releases. From 91803e7b1a820e51e40c9a897c299520b6030fc7 Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Thu, 24 Jul 2025 12:10:12 +0900 Subject: [PATCH 04/13] fix(clipboard): yank not working on visual mode --- keymaps/vim.json | 1 - src/clipboard.js | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/keymaps/vim.json b/keymaps/vim.json index 7d0e761..9ebdadc 100644 --- a/keymaps/vim.json +++ b/keymaps/vim.json @@ -1,5 +1,4 @@ { - ".CodeMirror.vim-mode": {}, ".note-list-bar": { "k": "core:open-prev-note", "j": "core:open-next-note" diff --git a/src/clipboard.js b/src/clipboard.js index 1ea5cb5..63b631e 100644 --- a/src/clipboard.js +++ b/src/clipboard.js @@ -2,6 +2,25 @@ const { vim, Vim } = require('@replit/codemirror-vim') const { clipboard } = require('electron') const { EditorView } = require('@codemirror/view') +/** @arg {Pos} cur1 @arg {Pos} cur2 @return {boolean}*/ +function cursorIsBefore(cur1, cur2) { + if (cur1.line < cur2.line) { + return true + } + if (cur1.line == cur2.line && cur1.ch < cur2.ch) { + return true + } + return false +} +/** @arg {Pos} cur1 @arg {Pos} cur2 @return {Pos}*/ +function cursorMin(cur1, cur2) { + if (arguments.length > 2) { + // @ts-ignore + cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1)) + } + return cursorIsBefore(cur1, cur2) ? cur1 : cur2 +} + Vim.defineOperator('yank', (cm, args, ranges, oldAnchor) => { const vim = cm.state.vim const text = cm.getSelection() @@ -15,6 +34,7 @@ Vim.defineOperator('yank', (cm, args, ranges, oldAnchor) => { args.linewise, vim.visualBlock ) + console.log('Yanked text:', text) clipboard.writeText(text) return endPos From b5c17d5fff1bbf12a3b37974867dd61ff5d91745 Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Thu, 24 Jul 2025 16:58:21 +0900 Subject: [PATCH 05/13] chore(target): v6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6c1d4e3..ceae75a 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "lint": "eslint ." }, "engines": { - "inkdrop": "^5.x" + "inkdrop": "^6.x" }, "devDependencies": { "eslint": "^9.28.0", From 5cce3cabf9e69c63fac756bdd91576b58c538b68 Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Fri, 1 Aug 2025 17:04:21 +0900 Subject: [PATCH 06/13] fix(clipboard): override register controller's pushText --- src/clipboard.js | 59 ++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/src/clipboard.js b/src/clipboard.js index 63b631e..013fc89 100644 --- a/src/clipboard.js +++ b/src/clipboard.js @@ -2,43 +2,34 @@ const { vim, Vim } = require('@replit/codemirror-vim') const { clipboard } = require('electron') const { EditorView } = require('@codemirror/view') -/** @arg {Pos} cur1 @arg {Pos} cur2 @return {boolean}*/ -function cursorIsBefore(cur1, cur2) { - if (cur1.line < cur2.line) { - return true - } - if (cur1.line == cur2.line && cur1.ch < cur2.ch) { - return true - } - return false -} -/** @arg {Pos} cur1 @arg {Pos} cur2 @return {Pos}*/ -function cursorMin(cur1, cur2) { - if (arguments.length > 2) { - // @ts-ignore - cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1)) +const origResetVimGlobalState = Vim.resetVimGlobalState_ +Vim.resetVimGlobalState_ = () => { + origResetVimGlobalState.call(Vim) + const state = Vim.getVimGlobalState_() + const origPushText = state.registerController.pushText + state.registerController.pushText = ( + registerName, + operator, + text, + linewise, + blockwise + ) => { + // console.log('pushText', registerName, operator, text, linewise, blockwise) + if (!registerName) { + clipboard.writeText(text) + } + origPushText.call( + state.registerController, + registerName, + operator, + text, + linewise, + blockwise + ) } - return cursorIsBefore(cur1, cur2) ? cur1 : cur2 } -Vim.defineOperator('yank', (cm, args, ranges, oldAnchor) => { - const vim = cm.state.vim - const text = cm.getSelection() - const endPos = vim.visualMode - ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor) - : oldAnchor - Vim.getRegisterController().pushText( - args.registerName, - 'yank', - text, - args.linewise, - vim.visualBlock - ) - console.log('Yanked text:', text) - clipboard.writeText(text) - - return endPos -}) +Vim.resetVimGlobalState_() const registerClipboardText = () => { const text = clipboard.readText() From 131379749f4661f8c8bf019b9c84afe92324eabc Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Thu, 7 Aug 2025 14:51:06 +0900 Subject: [PATCH 07/13] feat(preview): add scroll shortcuts --- keymaps/vim.json | 2 +- src/preview.js | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ src/vim.js | 6 +++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 src/preview.js diff --git a/keymaps/vim.json b/keymaps/vim.json index 9ebdadc..3e1a29a 100644 --- a/keymaps/vim.json +++ b/keymaps/vim.json @@ -3,7 +3,7 @@ "k": "core:open-prev-note", "j": "core:open-next-note" }, - ".mde-preview": { + ".mde-preview-container": { "g g": "vim:move-to-start-of-file", "ctrl-u": "vim:scroll-half-screen-up", "ctrl-b": "vim:scroll-full-screen-up", diff --git a/src/preview.js b/src/preview.js new file mode 100644 index 0000000..89b6094 --- /dev/null +++ b/src/preview.js @@ -0,0 +1,59 @@ +function bindPreviewVimCommands() { + let sub = null + + function bindHandlers(target) { + if (sub) sub.dispose() + if (!target) return + + sub = inkdrop.commands.add(target, { + 'vim:move-to-start-of-file': ({ target }) => { + target.scrollTop = 0 + }, + 'vim:scroll-up': ({ target }) => { + console.log('vim:scroll-up', target) + target.scrollTop -= 30 + }, + 'vim:scroll-down': ({ target }) => { + console.log('vim:scroll-down', target) + target.scrollTop += 30 + }, + 'vim:scroll-half-screen-up': ({ target }) => { + target.scrollTop -= target.clientHeight / 2 + }, + 'vim:scroll-half-screen-down': ({ target }) => { + target.scrollTop += target.clientHeight / 2 + }, + 'vim:scroll-full-screen-up': ({ target }) => { + target.scrollTop -= target.clientHeight + }, + 'vim:scroll-full-screen-down': ({ target }) => { + target.scrollTop += target.clientHeight + }, + 'vim:move-to-line': ({ target }) => { + target.scrollTop = target.scrollHeight + } + }) + } + + const selector = '.mde-preview-container' + const el = document.querySelector(selector) + bindHandlers(el) + + const observer = new MutationObserver(() => { + const el = document.querySelector(selector) + bindHandlers(el) + }) + observer.observe(document.body, { + childList: true, + subtree: true + }) + + return () => { + observer.disconnect() + if (sub) sub.dispose() + } +} + +module.exports = { + bindPreviewVimCommands +} diff --git a/src/vim.js b/src/vim.js index 19e8cfa..88982bc 100644 --- a/src/vim.js +++ b/src/vim.js @@ -4,6 +4,7 @@ const { registerClipboardTextOnFocus, registerClipboardText } = require('./clipboard') +const { bindPreviewVimCommands } = require('./preview') require('./ex') class Plugin { @@ -22,12 +23,17 @@ class Plugin { this.extension = [vim(), registerClipboardTextOnFocus()] inkdrop.store.dispatch(actions.mde.addExtension(this.extension)) inkdrop.window.on('focus', this.handleAppFocus) + + this.unbindPreviewViewCommands = bindPreviewVimCommands() } deactivate() { inkdrop.store.dispatch(actions.mde.removeExtension(this.extension)) this.extension = null inkdrop.window.off('focus', this.handleAppFocus) + + this.unbindPreviewViewCommands() + this.unbindPreviewViewCommands = null } handleAppFocus() { From 4ad5c6ea059de0dbca4c0094fda87c9d8114eefc Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Thu, 7 Aug 2025 15:50:30 +0900 Subject: [PATCH 08/13] fix(style): non-focused styles are not properly applied --- styles/vim.css | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/styles/vim.css b/styles/vim.css index 221a33e..3ac4bc7 100644 --- a/styles/vim.css +++ b/styles/vim.css @@ -1,8 +1,9 @@ -.editor .mde .cm-editor .cm-scroller.cm-vimMode { - .cm-fat-cursor { +.editor .mde .cm-editor { + .cm-scroller.cm-vimMode .cm-fat-cursor { background: var(--editor-caret-color) !important; } - &:not(.cm-focused) .cm-fat-cursor { + &:not(.cm-focused) .cm-scroller.cm-vimMode .cm-fat-cursor { + background: transparent !important; outline: solid 1px var(--editor-caret-color) !important; } } From 57a5e09d4dab6cd460660b8f239361ad853f49d7 Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Wed, 13 Aug 2025 12:33:55 +0900 Subject: [PATCH 09/13] feat(scroll): support cursor scroll margin --- src/ex.js | 2 +- src/scroll.js | 13 +++++++++++++ src/vim.js | 13 ++++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/scroll.js diff --git a/src/ex.js b/src/ex.js index 3120da5..a252878 100644 --- a/src/ex.js +++ b/src/ex.js @@ -1,4 +1,4 @@ -const { vim, Vim } = require('@replit/codemirror-vim') +const { Vim } = require('@replit/codemirror-vim') Vim.defineEx('write', 'w', () => { inkdrop.commands.dispatch(document.body, 'core:save-note') diff --git a/src/scroll.js b/src/scroll.js new file mode 100644 index 0000000..f0354b5 --- /dev/null +++ b/src/scroll.js @@ -0,0 +1,13 @@ +const { vim, CodeMirror, getCM } = require('@replit/codemirror-vim') + +function disableScrollIntoView(view) { + const cm = getCM(view) + cm.scrollIntoView = () => { + // Do nothing to disable the vim's scrollIntoView behavior + // because it conflicts with Inkdrop's scroll behavior with scroll margin support + } +} + +module.exports = { + disableScrollIntoView +} diff --git a/src/vim.js b/src/vim.js index 88982bc..fc73b42 100644 --- a/src/vim.js +++ b/src/vim.js @@ -5,6 +5,7 @@ const { registerClipboardText } = require('./clipboard') const { bindPreviewVimCommands } = require('./preview') +const { disableScrollIntoView } = require('./scroll') require('./ex') class Plugin { @@ -23,8 +24,13 @@ class Plugin { this.extension = [vim(), registerClipboardTextOnFocus()] inkdrop.store.dispatch(actions.mde.addExtension(this.extension)) inkdrop.window.on('focus', this.handleAppFocus) - this.unbindPreviewViewCommands = bindPreviewVimCommands() + + this.sub = inkdrop.onEditorLoad(this.handleEditorLoaded.bind(this)) + setTimeout(() => { + const editorView = inkdrop.getActiveEditor() + if (editorView) this.handleEditorLoaded(editorView) + }, 100) } deactivate() { @@ -34,11 +40,16 @@ class Plugin { this.unbindPreviewViewCommands() this.unbindPreviewViewCommands = null + this.sub.dispose() } handleAppFocus() { registerClipboardText() } + + handleEditorLoaded(view) { + disableScrollIntoView(view) + } } module.exports = new Plugin() From 8c9c5ae9caf6c22e55795bd72f80f07b8e050b9c Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Mon, 1 Sep 2025 15:10:27 +0900 Subject: [PATCH 10/13] fix(readme): how to configure keybindings --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fbe8564..1db6115 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ You can customize keybindings in your [init.js](https://developers.inkdrop.app/g For example, ```js -inkdrop.onEditorLoad(() => { +function configureKeyBindings() { const Vim = inkdrop.packages.getLoadedPackage('vim').mainModule.Vim // Map keys @@ -36,6 +36,12 @@ inkdrop.onEditorLoad(() => { Vim.map('Y', 'y$') // in normal mode // Unmap keys Vim.unmap('jj', 'insert') +} + +const editor = inkdrop.getActiveEditor() +if (editor) configureKeyBindings() +inkdrop.onEditorLoad(() => { + configureKeyBindings() }) ``` From 236447bfb4fff898723e362e60d8c434077a03ff Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Thu, 30 Oct 2025 14:48:20 +0900 Subject: [PATCH 11/13] fix(scroll-margin): no need to disable scrollIntoView hack --- package-lock.json | 2 +- src/scroll.js | 17 +++++++++++------ src/vim.js | 11 ----------- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 32f7171..59e239f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "prettier": "^3.5.3" }, "engines": { - "inkdrop": "^5.x" + "inkdrop": "^6.x" } }, "node_modules/@codemirror/commands": { diff --git a/src/scroll.js b/src/scroll.js index f0354b5..c996e02 100644 --- a/src/scroll.js +++ b/src/scroll.js @@ -1,12 +1,17 @@ +const { ViewPlugin } = require('@codemirror/view') const { vim, CodeMirror, getCM } = require('@replit/codemirror-vim') -function disableScrollIntoView(view) { - const cm = getCM(view) - cm.scrollIntoView = () => { - // Do nothing to disable the vim's scrollIntoView behavior - // because it conflicts with Inkdrop's scroll behavior with scroll margin support +const disableScrollIntoView = ViewPlugin.fromClass( + class { + constructor(view) { + const cm = getCM(view) + cm.scrollIntoView = () => { + // Do nothing to disable the vim's scrollIntoView behavior + // because it conflicts with Inkdrop's scroll behavior with scroll margin support + } + } } -} +) module.exports = { disableScrollIntoView diff --git a/src/vim.js b/src/vim.js index fc73b42..29375cf 100644 --- a/src/vim.js +++ b/src/vim.js @@ -25,12 +25,6 @@ class Plugin { inkdrop.store.dispatch(actions.mde.addExtension(this.extension)) inkdrop.window.on('focus', this.handleAppFocus) this.unbindPreviewViewCommands = bindPreviewVimCommands() - - this.sub = inkdrop.onEditorLoad(this.handleEditorLoaded.bind(this)) - setTimeout(() => { - const editorView = inkdrop.getActiveEditor() - if (editorView) this.handleEditorLoaded(editorView) - }, 100) } deactivate() { @@ -40,16 +34,11 @@ class Plugin { this.unbindPreviewViewCommands() this.unbindPreviewViewCommands = null - this.sub.dispose() } handleAppFocus() { registerClipboardText() } - - handleEditorLoaded(view) { - disableScrollIntoView(view) - } } module.exports = new Plugin() From 3bca92b4a1c6b98dfab9a8a7023f9e851dd672a5 Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Thu, 30 Oct 2025 15:16:53 +0900 Subject: [PATCH 12/13] fix(scroll-margin): it is required for normal mode --- src/vim.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vim.js b/src/vim.js index 29375cf..fa7aa4f 100644 --- a/src/vim.js +++ b/src/vim.js @@ -21,7 +21,11 @@ class Plugin { activate() { this.Vim = Vim - this.extension = [vim(), registerClipboardTextOnFocus()] + this.extension = [ + vim(), + registerClipboardTextOnFocus(), + disableScrollIntoView + ] inkdrop.store.dispatch(actions.mde.addExtension(this.extension)) inkdrop.window.on('focus', this.handleAppFocus) this.unbindPreviewViewCommands = bindPreviewVimCommands() From d8ae1082d2f36509258a7844d373abb53d174214 Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Mon, 10 Nov 2025 17:41:29 +0900 Subject: [PATCH 13/13] fix(utils): `gg` and `G` randomly stop working reset the vim global state when reconfiguring the editor, which happens when opening another note --- package-lock.json | 7 ++++--- src/utils.js | 14 ++++++++++++++ src/vim.js | 4 +++- 3 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 src/utils.js diff --git a/package-lock.json b/package-lock.json index 59e239f..ce05a51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -71,13 +71,14 @@ } }, "node_modules/@codemirror/view": { - "version": "6.37.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.37.0.tgz", - "integrity": "sha512-ghHIeRGfWB8h9Tc3sMdr7D5zp4sZvlCzG36Xjdh2ymmfAwvSaCJAAsL3HLyLEnHcE953+5Uox1bx5OS+YCW/7Q==", + "version": "6.38.6", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.6.tgz", + "integrity": "sha512-qiS0z1bKs5WOvHIAC0Cybmv4AJSkAXgX5aD6Mqd2epSLlVJsQl8NG23jCVouIgkh4All/mrbdsf2UOLFnJw0tw==", "license": "MIT", "peer": true, "dependencies": { "@codemirror/state": "^6.5.0", + "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000..e5df677 --- /dev/null +++ b/src/utils.js @@ -0,0 +1,14 @@ +const { Vim } = require('@replit/codemirror-vim') +const { ViewPlugin } = require('@codemirror/view') + +const editorInitHandler = ViewPlugin.define(_view => { + /* + * NOTE: Reset the Vim global state when opening another note + */ + Vim.resetVimGlobalState_() + return {} +}) + +module.exports = { + editorInitHandler +} diff --git a/src/vim.js b/src/vim.js index fa7aa4f..ca1f2ee 100644 --- a/src/vim.js +++ b/src/vim.js @@ -4,6 +4,7 @@ const { registerClipboardTextOnFocus, registerClipboardText } = require('./clipboard') +const { editorInitHandler } = require('./utils') const { bindPreviewVimCommands } = require('./preview') const { disableScrollIntoView } = require('./scroll') require('./ex') @@ -24,7 +25,8 @@ class Plugin { this.extension = [ vim(), registerClipboardTextOnFocus(), - disableScrollIntoView + disableScrollIntoView, + editorInitHandler ] inkdrop.store.dispatch(actions.mde.addExtension(this.extension)) inkdrop.window.on('focus', this.handleAppFocus)