├── .babelrc
├── .eslintignore
├── .eslintrc.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── docs
├── options.png
└── preferences.png
├── keymaps
└── vim.json
├── lib
├── keymap.js
├── keymap.js.map
├── vim.js
└── vim.js.map
├── package-lock.json
├── package.json
├── prettier.config.js
├── src
├── keymap.js
└── vim.js
└── styles
└── vim.less
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["@babel/preset-env", {
4 | "targets": { "electron": "12.2.1" }
5 | }]
6 | ],
7 | "plugins": [
8 | "@babel/plugin-proposal-class-properties"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | lib
2 | src/keymap.js
3 |
--------------------------------------------------------------------------------
/.eslintrc.yml:
--------------------------------------------------------------------------------
1 | root: true
2 | extends:
3 | - prettier
4 | parser: "@babel/eslint-parser"
5 | env: {}
6 | globals: {}
7 | rules:
8 | no-useless-escape: 0
9 | prefer-const: 2
10 | no-unused-vars:
11 | - 2
12 | -
13 | argsIgnorePattern: ^_
14 | varsIgnorePattern: ^_
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | npm-debug.log
3 | node_modules
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ### 2.2.2
2 |
3 | - fix(option): The seamless focus jump from the editor to the note title bar is now an option and disabled by default
4 |
5 | ### 2.2.1
6 |
7 | - feat(motion): Jump to note title on invoking `vim:move-up` at the first line and char
8 |
9 | ### 2.2.0
10 |
11 | - feat(motion): Support moitons like yG/ygg/dG/dgg (Thanks [jamalmoir](https://github.com/inkdropapp/inkdrop-vim/issues/39))
12 |
13 | ### 2.1.10
14 |
15 | - fix(buffering): space key should be processed as a character input (Thanks [Chris](https://github.com/inkdropapp/inkdrop-vim/issues/29))
16 |
17 | ### 2.1.9
18 |
19 | - fix(keymap): Commands should not work while buffering key in visual mode (Thanks [Kazuhiro](https://forum.inkdrop.app/t/minor-issue-in-vim-plugin/2702))
20 |
21 | ### 2.1.7
22 |
23 | - fix(typo): Number keys not working as expected (Thanks [FORTRAN](https://forum.inkdrop.app/t/vim-plugin/2228/2))
24 |
25 | ### 2.1.6
26 |
27 | - fix(motion): Ignore numeric keys when a modifier key is pressed (Thanks [Basyura](https://github.com/inkdropapp/inkdrop-vim/pull/25))
28 |
29 | ### 2.1.5
30 |
31 | - fix(motion): enter/space/arrow keys not working as expected while key buffering (Thanks [rcashie](https://github.com/inkdropapp/inkdrop-vim/issues/24))
32 |
33 | ### 2.1.4
34 |
35 | - fix(motion): text object manipulation not working for some tokens (Thanks [rcashie](https://github.com/inkdropapp/inkdrop-vim/issues/23))
36 |
37 | ### 2.1.2
38 |
39 | - fix(keymap): remove keybindings of s h, s k, s l since those conflict with the default vim behavior of `s` (Thanks [oniatsu-san](https://github.com/inkdropapp/inkdrop-vim/issues/19))
40 |
41 | ### 2.1.1
42 |
43 | - fix(keymap): change keybinding for `vim:move-to-mark` from " to ' (Thanks [oniatsu-san](https://github.com/inkdropapp/inkdrop-vim/issues/18))
44 |
45 | ### 2.1.0
46 |
47 | - feat(motion): support moving cursor up/down by display lines (g k / g j) (Thanks [jolyon129](https://github.com/inkdropapp/inkdrop-vim/issues/16))
48 |
49 | ### 2.0.1
50 |
51 | - Fix a bug where `vim:scroll-full-screen-up` and `vim:scroll-full-screen-down` not working (Thanks [@basyura](https://github.com/inkdropapp/inkdrop-vim/issues/13#issuecomment-612326857))
52 |
53 | ### 2.0.0
54 |
55 | - (Breaking) The command prefix has been changed from `vim-mode:` to `vim:` so that the keybindings are correctly listed in the plugin settings
56 | - Moving focus between panes (sidebar, note list bar, editor, note title) with `s h` / `s j` / `s k` / `s l`
57 | - Select next/prev item in note list bar (`j` / `k`)
58 | - Scroll markdown preview pane ([Thanks @trietphm](https://github.com/inkdropapp/inkdrop-vim/issues/13))
59 |
60 | ### 1.0.12
61 |
62 | - fix(key-buffering): replace character with "a" does not work ([Thanks seachicken](https://github.com/inkdropapp/inkdrop-vim/issues/11))
63 |
64 | ### 1.0.11
65 |
66 | - fix(debug): typo in debug code that causes an error
67 |
68 | ### 1.0.10
69 |
70 | - fix(operatormotion): do not start key buffering for "D" and "C" operator motions (Thanks shimizu-san)
71 | - fix(buffering): avoid running command with 0 key while key buffering (Thanks volment)
72 |
73 | ### 1.0.8
74 |
75 | - fix(keymap): handle keystrokes as text input which failed to match binding [#8](https://github.com/inkdropapp/inkdrop-vim/issues/8) (Thanks @rtmoranorg)
76 |
77 | ### 1.0.7
78 |
79 | - fix(keymap): substitute keys not working [#4](https://github.com/inkdropapp/inkdrop-vim/issues/4) (Thanks @gregwebs and @giantsol)
80 |
81 | ### 1.0.6
82 |
83 | - fix(keymap): 'X' in visual mode does not work [#7](https://github.com/inkdropapp/inkdrop-vim/issues/7) (Thanks [@usou](https://github.com/usou))
84 |
85 | ### 1.0.5
86 |
87 | - Copy deleted text to clipboard
88 | - Fix invalid selectors for `vim-mode:text-object-manipulation*` keymaps again
89 |
90 | ### 1.0.4
91 |
92 | - Fix invalid selectors for `vim-mode:text-object-manipulation*` keymaps
93 |
94 | ### 1.0.3
95 |
96 | - Support some actions for visual mode ([diff](https://github.com/inkdropapp/inkdrop-vim/commit/4536385f6d74c5e7c7247e7c65e593108925b056))
97 |
98 | ### 1.0.2
99 |
100 | - feat(visual-mode): Support insert-at-start-of-target & insert-at-end-of-target (Thanks [Vikram](https://forum.inkdrop.app/t/vim-inserting-at-beginning-of-line-or-at-target-in-visual-block-mode-doesnt-work/1397/))
101 |
102 | ### 1.0.1
103 |
104 | - fix(keybuffering): Avoid buffering key after processing command
105 | - fix(keybuffering): Avoid incorrect key buffering
106 | - fix(replace): Replacing with numeric character not working
107 |
108 | ### 1.0.0
109 |
110 | - feat(\*): Support inkdrop 4.x
111 |
112 | ### 0.3.2
113 |
114 | - fix(operator): Fix incorrect handling for operators
115 |
116 | ### 0.3.1
117 |
118 | - fix(keymaps): Support key buffering for keys like 'd' and 'c'
119 |
120 | ### 0.3.0
121 |
122 | - fix(keymaps): Support text object manipulations
123 |
124 | ### 0.2.4
125 |
126 | - Support Inkdrop v3.17.1
127 |
128 | ### 0.2.3
129 |
130 | - Support `ge` and `gE` (Thanks [@kiryph](https://github.com/kiryph))
131 |
132 | ### 0.1.0 - First Release
133 |
134 | - Every feature added
135 | - Every bug fixed
136 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2020 Takuya Matsuyama
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vim keybindings plugin for Inkdrop
2 |
3 | Provides Vim modal control for Inkdrop, blending the best of Vim and Inkdrop.
4 |
5 | ## Features
6 |
7 | - All common motions and operators, including text objects
8 | - Operator motion orthogonality
9 | - Visual mode - characterwise, linewise, blockwise
10 | - Incremental highlighted search (`/`, `?`, `#`, `*`, `g#`, `g*`)
11 | - Search/replace with confirm (:substitute, :%s)
12 | - Search history
13 | - Sort (`:sort`)
14 | - Marks (`,`)
15 | - Cross-buffer yank/paste
16 | - Select next/prev item in note list bar (`j` / `k`)
17 | - Scroll markdown preview pane
18 |
19 | ## Install
20 |
21 | ```sh
22 | ipm install vim
23 | ```
24 |
25 | ## Key customizations
26 |
27 | 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.
28 |
29 | CSS selectors for each mode:
30 |
31 | - Not insert mode: `.CodeMirror.vim-mode:not(.insert-mode):not(.key-buffering) textarea`
32 | - Normal mode: `.CodeMirror.vim-mode.normal-mode:not(.key-buffering) textarea`
33 | - Insert mode: `.CodeMirror.vim-mode.insert-mode textarea`
34 | - Replace mode: `.CodeMirror.vim-mode.replace-mode textarea`
35 | - Visual mode: `.CodeMirror.vim-mode.visual-mode:not(.key-buffering) textarea`
36 |
37 | You can check current keybindings on the _Keybindings_ pane on preferences window:
38 |
39 | 
40 |
41 | ## Ex Commands
42 |
43 | ### `:w`, `:write`
44 |
45 | Saves current note immediately to the disk.
46 |
47 | ### `:next`, `:n`
48 |
49 | Opens next note on the note list.
50 |
51 | ### `:prev`
52 |
53 | Opens previous note on the note list.
54 |
55 | ### `:preview`, `:p`
56 |
57 | Toggles HMTL preview.
58 |
59 | ### `:side-by-side`, `:side`
60 |
61 | Toggles side-by-side mode.
62 |
63 | ### Define custom Ex commands
64 |
65 | You can extend Ex commands by writing [init.js](https://docs.inkdrop.app/manual/the-init-file).
66 | The following example defines `:find` command:
67 |
68 | ```js
69 | inkdrop.onEditorLoad(() => {
70 | var CodeMirror = require('codemirror')
71 | CodeMirror.Vim.defineEx('find', 'f', (cm, event) => {
72 | inkdrop.commands.dispatch(document.body, 'core:find-global')
73 | if (event.argString)
74 | inkdrop.commands.dispatch(document.body, 'core:search-notes', {
75 | keyword: event.argString.trim()
76 | })
77 | })
78 | })
79 | ```
80 |
81 | ## Options
82 |
83 | 
84 |
85 | ### Seamlessly jump to note title
86 |
87 | Whether moving focus seamlessly from the editor to the note title bar by `vim:move-up` command
88 |
89 | ## Changelog
90 |
91 | See the [GitHub releases](https://github.com/inkdropapp/inkdrop-vim/releases) for an overview of what changed in each update.
92 | See [CHANGELOG.md](https://github.com/inkdropapp/inkdrop-vim/blob/master/CHANGELOG.md) for older releases.
93 |
--------------------------------------------------------------------------------
/docs/options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inkdropapp/inkdrop-vim/eec2aae437599689eba7eced66d08231a57469d4/docs/options.png
--------------------------------------------------------------------------------
/docs/preferences.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inkdropapp/inkdrop-vim/eec2aae437599689eba7eced66d08231a57469d4/docs/preferences.png
--------------------------------------------------------------------------------
/keymaps/vim.json:
--------------------------------------------------------------------------------
1 | {
2 | ".CodeMirror.vim-mode": {},
3 | ".CodeMirror.vim-mode.normal-mode textarea": {
4 | "escape": "vim:reset-normal-mode"
5 | },
6 | ".CodeMirror.vim-mode:not(.insert-mode):not(.key-buffering) textarea": {
7 | "h": "vim:move-left",
8 | "left": "vim:move-left",
9 | "backspace": "vim:move-left",
10 | "l": "vim:move-right",
11 | "right": "vim:move-right",
12 | "space": "vim:move-right",
13 | "k": "vim:move-up",
14 | "up": "vim:move-up",
15 | "j": "vim:move-down",
16 | "down": "vim:move-down",
17 | "g k": "vim:move-up-by-display-lines",
18 | "g j": "vim:move-down-by-display-lines",
19 | "g v": "vim:reselect-last-selection",
20 |
21 | "w": "vim:move-to-next-word",
22 | "W": "vim:move-to-next-whole-word",
23 | "e": "vim:move-to-end-of-word",
24 | "g e": "vim:move-to-previous-end-of-word",
25 | "E": "vim:move-to-end-of-whole-word",
26 | "g E": "vim:move-to-previous-end-of-whole-word",
27 | "b": "vim:move-to-previous-word",
28 | "B": "vim:move-to-previous-whole-word",
29 | "}": "vim:move-to-next-paragraph",
30 | "{": "vim:move-to-previous-paragraph",
31 | "|": "vim:move-to-beginning-of-line",
32 | "0": "vim:move-to-beginning-of-line-with-zero",
33 | "^": "vim:move-to-first-character-of-line",
34 | "_": "vim:move-to-first-character-of-line-and-down",
35 | "$": "vim:move-to-last-character-of-line",
36 | "g _": "vim:move-to-last-nonblank-character-of-line-and-down",
37 | "-": "vim:move-to-first-character-of-line-up",
38 | "+": "vim:move-to-first-character-of-line-down",
39 | "enter": "vim:move-to-first-character-of-line-down",
40 | "g g": "vim:move-to-start-of-file",
41 | "ctrl-u": "vim:scroll-half-screen-up",
42 | "ctrl-b": "vim:scroll-full-screen-up",
43 | "ctrl-d": "vim:scroll-half-screen-down",
44 | "ctrl-f": "vim:scroll-full-screen-down",
45 | "ctrl-e": "vim:scroll-down",
46 | "ctrl-y": "vim:scroll-up",
47 | "z enter": "vim:scroll-cursor-to-top",
48 | "z t": "vim:scroll-cursor-to-top-leave",
49 | "z .": "vim:scroll-cursor-to-middle",
50 | "z z": "vim:scroll-cursor-to-middle-leave",
51 | "z -": "vim:scroll-cursor-to-bottom",
52 | "z b": "vim:scroll-cursor-to-bottom-leave",
53 | "z s": "vim:scroll-cursor-to-left",
54 | "z e": "vim:scroll-cursor-to-right",
55 | "z M": "editor:fold-all",
56 | "z R": "editor:unfold-all",
57 | "z c": "editor:fold-current-row",
58 | "z o": "editor:unfold-current-row",
59 | "shift-G": "vim:move-to-line",
60 | "H": "vim:move-to-top-of-screen",
61 | "L": "vim:move-to-bottom-of-screen",
62 | "M": "vim:move-to-middle-of-screen",
63 |
64 | "d": "vim:delete",
65 | "D": "vim:delete-to-last-character-of-line",
66 | "c": "vim:change",
67 | "C": "vim:change-to-last-character-of-line",
68 | "r": "vim:replace",
69 | ">": "vim:indent",
70 | "<": "vim:outdent",
71 | "=": "vim:auto-indent",
72 | "J": "vim:join",
73 |
74 | "y": "vim:yank",
75 | "Y": "vim:yank-line",
76 | "P": "vim:put-before",
77 | "p": "vim:put-after",
78 |
79 | "g ~": "vim:toggle-case",
80 | "g U": "vim:upper-case",
81 | "g u": "vim:lower-case",
82 | "~": "vim:toggle-case-now",
83 |
84 | "m": "vim:mark",
85 | "`": "vim:move-to-mark-literal",
86 | "'": "vim:move-to-mark",
87 |
88 | "f": "vim:find",
89 | "F": "vim:find-backwards",
90 | "t": "vim:till",
91 | "T": "vim:till-backwards",
92 | ";": "vim:repeat-find",
93 | ",": "vim:repeat-find-reverse",
94 |
95 | "/": "vim:search",
96 | "?": "vim:reverse-search",
97 | "*": "vim:search-current-word",
98 | "#": "vim:reverse-search-current-word",
99 | "n": "vim:repeat-search",
100 | "N": "vim:repeat-search-backwards",
101 |
102 | "%": "vim:bracket-matching-motion",
103 |
104 | ":": "vim:ex-command"
105 | },
106 | ".CodeMirror.vim-mode:not(.insert-mode):not(.key-buffering-command) textarea": {
107 | "i": "vim:text-object-manipulation-inner",
108 | "a": "vim:text-object-manipulation"
109 | },
110 | ".CodeMirror.vim-mode.normal-mode.key-buffering-operator textarea": {
111 | "enter": "vim:move-down",
112 | "space": "vim:move-right",
113 | "up": "vim:move-up",
114 | "down": "vim:move-down",
115 | "right": "vim:move-right",
116 | "left": "vim:move-left"
117 | },
118 | ".CodeMirror.vim-mode.normal-mode:not(.key-buffering):not(.visual-mode) textarea": {
119 | "i": "vim:activate-insert-mode",
120 | "I": "vim:insert-at-beginning-of-line",
121 | "insert": "vim:activate-insert-mode",
122 | "R": "vim:activate-replace-mode",
123 | "v": "vim:activate-characterwise-visual-mode",
124 | "V": "vim:activate-linewise-visual-mode",
125 | "ctrl-v": "vim:activate-blockwise-visual-mode",
126 | "ctrl-q": "vim:activate-blockwise-visual-mode",
127 |
128 | "u": "vim:undo",
129 | "ctrl-r": "core:redo",
130 |
131 | "O": "vim:insert-above-with-newline",
132 | "o": "vim:insert-below-with-newline",
133 | "a": "vim:insert-after",
134 | "A": "vim:insert-after-end-of-line",
135 | "x": "vim:delete-right",
136 | "X": "vim:delete-left",
137 | "s": "vim:substitute",
138 | "S": "vim:substitute-line",
139 | ".": "vim:repeat",
140 |
141 | "ctrl-a": "vim:increase",
142 | "ctrl-x": "vim:decrease",
143 |
144 | "\"": "vim:register-prefix"
145 | },
146 | ".CodeMirror.vim-mode.insert-mode textarea": {
147 | "escape": "vim:exit-insert-mode",
148 | "ctrl-w": "vim:delete-to-beginning-of-word"
149 | },
150 | ".CodeMirror.vim-mode.replace-mode textarea": {
151 | "escape": "vim:exit-insert-mode"
152 | },
153 | ".CodeMirror.vim-mode.visual-mode textarea": {
154 | "escape": "vim:exit-visual-mode"
155 | },
156 | ".CodeMirror.vim-mode.visual-mode:not(.key-buffering) textarea": {
157 | "\"": "vim:register-prefix",
158 | "I": "vim:insert-at-start-of-target",
159 | "A": "vim:insert-at-end-of-target",
160 | "v": "vim:activate-characterwise-visual-mode",
161 | "V": "vim:activate-linewise-visual-mode",
162 | "o": "vim:reverse-selections",
163 | "O": "vim:reverse-selections-at-same-line",
164 | "x": "vim:delete-right",
165 | "X": "vim:delete-left",
166 | "s": "vim:substitute-visual",
167 | "S": "vim:substitute-line-visual"
168 | },
169 | ".note-list-bar": {
170 | "k": "core:open-prev-note",
171 | "j": "core:open-next-note"
172 | },
173 | ".mde-preview": {
174 | "g g": "vim:move-to-start-of-file",
175 | "ctrl-u": "vim:scroll-half-screen-up",
176 | "ctrl-b": "vim:scroll-full-screen-up",
177 | "ctrl-d": "vim:scroll-half-screen-down",
178 | "ctrl-f": "vim:scroll-full-screen-down",
179 | "k": "vim:scroll-up",
180 | "j": "vim:scroll-down",
181 | "G": "vim:move-to-line",
182 | "H": "vim:move-to-start-of-file"
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/lib/vim.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var _inkdrop = require("inkdrop");
4 | var _keymap = _interopRequireDefault(require("./keymap"));
5 | var _eventKit = require("event-kit");
6 | var _codemirror = _interopRequireDefault(require("codemirror"));
7 | var _electron = require("electron");
8 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9 | 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; }
10 | function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
11 | 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); }
12 | class Plugin {
13 | constructor() {
14 | _defineProperty(this, "config", {
15 | seamlessJumpToTitle: {
16 | title: 'Seamlessly jump to note title',
17 | type: 'boolean',
18 | description: 'Focus jumps from the editor to the note title bar by `vim:move-up` command',
19 | default: false
20 | }
21 | });
22 | _defineProperty(this, "handleEditorLoad", editor => {
23 | this.activateMode(editor);
24 | });
25 | _defineProperty(this, "handleVimModeChange", (event, _opt) => {
26 | _inkdrop.logger.debug('vim mode changed:', event);
27 | const {
28 | mode
29 | } = event;
30 | const cm = this.getCodeMirror();
31 | cm.getWrapperElement().classList.remove('insert-mode');
32 | cm.getWrapperElement().classList.remove('visual-mode');
33 | cm.getWrapperElement().classList.remove('normal-mode');
34 | cm.getWrapperElement().classList.remove('replace-mode');
35 | switch (mode) {
36 | case 'normal':
37 | cm.getWrapperElement().classList.add('normal-mode');
38 | break;
39 | case 'visual':
40 | cm.getWrapperElement().classList.add('visual-mode');
41 | break;
42 | case 'replace':
43 | cm.getWrapperElement().classList.add('replace-mode');
44 | break;
45 | case 'insert':
46 | cm.getWrapperElement().classList.add('insert-mode');
47 | break;
48 | }
49 | });
50 | _defineProperty(this, "handleEditorTextInput", event => {
51 | // only process if the event is fired via EventTarget.dispatchEvent()
52 | if (this.isInsertMode() && !event.isTrusted) {
53 | _inkdrop.logger.debug('handle text input:', event);
54 | const text = event.data;
55 | const cm = this.getCodeMirror();
56 | cm.replaceSelection(text);
57 | }
58 | });
59 | _defineProperty(this, "handleEditorKeyDown", event => {
60 | const keyName = this.normalizeKeyName(event.key);
61 | const cm = this.getCodeMirror();
62 | const vim = this.vim.maybeInitVimState(cm);
63 | const isNumeric = !event.ctrlKey && !event.altKey && !event.metaKey && !event.shiftKey && keyName.match(/^\d$/);
64 | const target = cm.getInputField();
65 | const currentKeyStroke = [...inkdrop.keymaps.queuedKeystrokes.filter(k => !k.startsWith('^')), keyName];
66 | const {
67 | partialMatchCandidates,
68 | exactMatchCandidates
69 | } = inkdrop.keymaps.findMatchCandidates(currentKeyStroke);
70 | const partialMatches = inkdrop.keymaps.findPartialMatches(partialMatchCandidates, target);
71 | const exactMatches = inkdrop.keymaps.findExactMatches(exactMatchCandidates, target);
72 | _inkdrop.logger.debug('handleEditorKeyDown: currentKeyStroke:', currentKeyStroke);
73 | _inkdrop.logger.debug('handleEditorKeyDown: exactMatches:', exactMatches);
74 | _inkdrop.logger.debug('handleEditorKeyDown: partialMatches:', partialMatches);
75 | if (this.isBufferingKey()) {
76 | _inkdrop.logger.debug('handleEditorKeyDown: handle key buffering:', keyName, event);
77 | const b = cm.getInputField().webkitMatchesSelector('.CodeMirror.vim-mode:not(.insert-mode) textarea');
78 | _inkdrop.logger.debug('handleEditorKeyDown: keybinding check:', exactMatches, b);
79 | if (keyName !== 'Ctrl' && keyName !== 'Alt' && keyName !== 'Shift' && keyName !== 'Meta') {
80 | const {
81 | inputState
82 | } = vim;
83 | const hasOperatorOrMotion = inputState.motion || inputState.operator;
84 | if ((event.key.length === 1 || keyName === 'space') && (!isNumeric || !hasOperatorOrMotion)) {
85 | inputState.selectedCharacter = event.key;
86 | inputState.keyBuffer = '';
87 | if (exactMatches.length === 0 && partialMatches.length === 0) {
88 | const {
89 | pendingCommand
90 | } = this;
91 | this.stopBufferingKey();
92 | if (typeof pendingCommand === 'function') {
93 | if (pendingCommand(event)) {
94 | event.stopPropagation();
95 | event.preventDefault();
96 | }
97 | }
98 | }
99 | } else if (isNumeric) {
100 | vim.inputState.pushRepeatDigit(keyName);
101 | }
102 | }
103 | } else if (!this.isInsertMode()) {
104 | if (isNumeric) {
105 | if (exactMatches.length === 0) {
106 | vim.inputState.pushRepeatDigit(keyName);
107 | }
108 | } else {
109 | // push key buffer to the repeat digit
110 | const keys = vim.inputState.keyBuffer;
111 | vim.inputState.keyBuffer = '';
112 | const keysMatcher = /^(\d*)(.*)$/.exec(keys);
113 | if (keysMatcher[1] && keysMatcher[1] !== '0') {
114 | vim.inputState.pushRepeatDigit(keysMatcher[1]);
115 | }
116 | }
117 | }
118 | });
119 | _defineProperty(this, "handleFocusEditor", _event => {
120 | this.yankClipboard();
121 | });
122 | }
123 | activate() {
124 | this.vim = (0, _keymap.default)(_codemirror.default);
125 | if (inkdrop.isEditorActive()) {
126 | this.activateMode(inkdrop.getActiveEditor());
127 | }
128 | inkdrop.onEditorLoad(this.handleEditorLoad);
129 | }
130 | deactivate() {
131 | if (this.disposables) {
132 | this.disposables.dispose();
133 | }
134 | if (inkdrop.isEditorActive()) {
135 | this.deactivateMode(inkdrop.getActiveEditor());
136 | }
137 | }
138 | activateMode(editor) {
139 | const {
140 | cm
141 | } = editor;
142 | this.originalKeyMap = cm.getOption('keyMap');
143 | cm.setOption('keyMap', 'vim');
144 | cm.on('vim-mode-change', this.handleVimModeChange);
145 | cm.on('focus', this.handleFocusEditor);
146 | const el = cm.getWrapperElement();
147 | el.classList.add('vim-mode', 'normal-mode');
148 | this.registerCommands();
149 | this.registerExCommands();
150 | }
151 | deactivateMode(editor) {
152 | const {
153 | cm
154 | } = editor;
155 | if (cm && this.originalKeyMap) {
156 | cm.setOption('keyMap', this.originalKeyMap);
157 | cm.off('vim-mode-change', this.handleVimModeChange);
158 | const el = cm.getWrapperElement();
159 | el.classList.remove('vim-mode');
160 | }
161 | }
162 | normalizeKeyName(key) {
163 | switch (key) {
164 | case 'Enter':
165 | return 'enter';
166 | case ' ':
167 | return 'space';
168 | case 'ArrowRight':
169 | return 'right';
170 | case 'ArrowLeft':
171 | return 'left';
172 | case 'ArrowUp':
173 | return 'up';
174 | case 'ArrowDown':
175 | return 'down';
176 | default:
177 | if (key.match(/^[A-Z]$/)) {
178 | return `shift-${key}`;
179 | }
180 | return key;
181 | }
182 | }
183 | startBufferingKey(command, customBufferingModeClass) {
184 | const wrapper = this.getCodeMirror().getWrapperElement();
185 | _inkdrop.logger.debug('Start key buffering');
186 | wrapper.classList.add('key-buffering');
187 | if (customBufferingModeClass) {
188 | wrapper.classList.add('key-buffering-' + customBufferingModeClass);
189 | }
190 | this.pendingCommand = command;
191 | }
192 | stopBufferingKey() {
193 | _inkdrop.logger.debug('Stop key buffering');
194 | const wrapper = this.getCodeMirror().getWrapperElement();
195 | const classes = Array.prototype.slice.apply(wrapper.classList);
196 | for (const i of classes) {
197 | if (i.startsWith('key-buffering')) {
198 | wrapper.classList.remove(i);
199 | }
200 | }
201 | this.pendingCommand = undefined;
202 | }
203 | isBufferingKey() {
204 | const wrapper = this.getCodeMirror().getWrapperElement();
205 | return wrapper.classList.contains('key-buffering');
206 | }
207 | bufferKey(key) {
208 | const cm = this.getCodeMirror();
209 | const vim = this.vim.maybeInitVimState(cm);
210 | const vimKey = this.vim.cmKeyToVimKey("'" + key + "'");
211 | vim.inputState.keyBuffer = vim.inputState.keyBuffer + vimKey;
212 | _inkdrop.logger.debug('keyBuffer:', vim.inputState.keyBuffer, vim.inputState);
213 | }
214 | isInsertMode() {
215 | const wrapper = this.getCodeMirror().getWrapperElement();
216 | return wrapper.classList.contains('insert-mode');
217 | }
218 | registerCommands() {
219 | const disposables = new _eventKit.CompositeDisposable();
220 | const editor = inkdrop.getActiveEditor();
221 | const {
222 | cm
223 | } = editor;
224 | const wrapper = cm.getWrapperElement();
225 | const doKeyToKey = async command => {
226 | _inkdrop.logger.debug('doKeyToKey:', command);
227 | let keys = command.toKeys;
228 | while (keys) {
229 | // Pull off one command key, which is either a single character
230 | // or a special sequence wrapped in '<' and '>', e.g. ''.
231 | const match = /<\w+-.+?>|<\w+>|./.exec(keys);
232 | let key = match[0];
233 | _inkdrop.logger.debug('key:', key);
234 | keys = keys.substring(match.index + key.length);
235 | if (this.isBufferingKey()) {
236 | this.handleEditorKeyDown(new KeyboardEvent('keydown', {
237 | key
238 | }));
239 | } else {
240 | if (key.match(/^[A-Z]$/)) {
241 | key = 'shift-' + key;
242 | }
243 | const {
244 | exactMatchCandidates
245 | } = inkdrop.keymaps.findMatchCandidates([key]);
246 | _inkdrop.logger.debug('exactMatchCandidates:', exactMatchCandidates);
247 | const bindings = inkdrop.keymaps.findExactMatches(exactMatchCandidates, document.activeElement);
248 | const b = bindings[0];
249 | if (b) {
250 | inkdrop.commands.dispatch(document.activeElement, b.command);
251 | } else {
252 | _inkdrop.logger.debug('command not found for key:', key);
253 | }
254 | }
255 | }
256 | };
257 |
258 | // bind key to command
259 | const h = command => {
260 | return e => {
261 | _inkdrop.logger.debug('command:', command, 'state:', Object.assign({}, cm.state.vim.inputState));
262 | e.stopPropagation();
263 | const vim = this.vim.maybeInitVimState(cm);
264 | return cm.operation(() => {
265 | cm.curOp.isVimOp = true;
266 | try {
267 | if (command.type === 'keyToKey') {
268 | doKeyToKey(command);
269 | } else {
270 | this.vim.commandDispatcher.processCommand(cm, vim, command);
271 | }
272 | } catch (e) {
273 | // clear VIM state in case it's in a bad state.
274 | cm.state.vim = undefined;
275 | this.vim.maybeInitVimState(cm);
276 | if (!_codemirror.default.Vim.suppressErrorLogging) {
277 | console.error(e);
278 | }
279 | throw e;
280 | }
281 | return true;
282 | });
283 | };
284 | };
285 | // bind keystroke to command
286 | const b = command => {
287 | return e => {
288 | _inkdrop.logger.debug('buffer command:', command, 'state:', Object.assign({}, cm.state.vim.inputState), e.originalEvent);
289 | this.startBufferingKey(h(command), 'command');
290 | this.bufferKey(e.originalEvent.key);
291 | };
292 | };
293 | // bind keystroke to operator
294 | const p = command => {
295 | return e => {
296 | _inkdrop.logger.debug('operator command:', command, 'state:', Object.assign({}, cm.state.vim.inputState), e.originalEvent, e);
297 | const vim = this.vim.maybeInitVimState(cm);
298 | if (!vim.inputState.operator && !this.isBufferingKey() && !vim.visualMode) {
299 | this.startBufferingKey(e => {
300 | const el = cm.getInputField();
301 | const keyName = this.normalizeKeyName(e.key);
302 | const keyBinding = inkdrop.keymaps.findKeyBindings({
303 | keystrokes: keyName,
304 | target: el
305 | });
306 | if (keyBinding.length > 0) {
307 | inkdrop.commands.dispatch(el, keyBinding[0].command);
308 | return true;
309 | } else {
310 | return false;
311 | }
312 | }, 'operator');
313 | if (e.originalEvent) {
314 | this.bufferKey(e.originalEvent.key);
315 | } else {
316 | _inkdrop.logger.debug('buffer key:', command.keys);
317 | this.bufferKey(command.keys);
318 | }
319 | }
320 | return h(command)(e);
321 | };
322 | };
323 | const handlers = {
324 | 'vim:native!': () => {},
325 | 'vim:reset-normal-mode': e => {
326 | _codemirror.default.Vim.clearInputState(cm);
327 | this.stopBufferingKey();
328 | e.stopPropagation();
329 | },
330 | 'vim:exit-visual-mode': e => {
331 | _inkdrop.logger.debug('exit-visual-mode');
332 | _codemirror.default.Vim.clearInputState(cm);
333 | _codemirror.default.Vim.exitVisualMode(cm);
334 | this.stopBufferingKey();
335 | e.stopPropagation();
336 | },
337 | 'vim:exit-insert-mode': e => {
338 | _inkdrop.logger.debug('exit-insert-mode');
339 | _codemirror.default.Vim.clearInputState(cm);
340 | _codemirror.default.Vim.exitInsertMode(cm);
341 | this.stopBufferingKey();
342 | e.stopPropagation();
343 | },
344 | 'vim:move-left': h({
345 | keys: 'h',
346 | type: 'motion',
347 | motion: 'moveByCharacters',
348 | motionArgs: {
349 | forward: false
350 | }
351 | }),
352 | 'vim:move-right': h({
353 | keys: 'l',
354 | type: 'motion',
355 | motion: 'moveByCharacters',
356 | motionArgs: {
357 | forward: true
358 | }
359 | }),
360 | 'vim:move-up': (command => {
361 | return e => {
362 | const seamlessJumpToTitleEnabled = inkdrop.config.get('vim.seamlessJumpToTitle');
363 | const cur = cm.getCursor();
364 | if (cur.line === 0 && cur.ch === 0 && seamlessJumpToTitleEnabled) {
365 | e.stopPropagation();
366 | inkdrop.commands.dispatch(document.body, 'editor:title:focus');
367 | } else {
368 | command(e);
369 | }
370 | };
371 | })(h({
372 | keys: 'k',
373 | type: 'motion',
374 | motion: 'moveByLines',
375 | motionArgs: {
376 | forward: false,
377 | linewise: true
378 | }
379 | })),
380 | 'vim:move-down': h({
381 | keys: 'j',
382 | type: 'motion',
383 | motion: 'moveByLines',
384 | motionArgs: {
385 | forward: true,
386 | linewise: true
387 | }
388 | }),
389 | 'vim:move-up-by-display-lines': h({
390 | keys: 'gk',
391 | type: 'motion',
392 | motion: 'moveByDisplayLines',
393 | motionArgs: {
394 | forward: false
395 | }
396 | }),
397 | 'vim:move-down-by-display-lines': h({
398 | keys: 'gj',
399 | type: 'motion',
400 | motion: 'moveByDisplayLines',
401 | motionArgs: {
402 | forward: true
403 | }
404 | }),
405 | 'vim:move-to-next-word': h({
406 | keys: 'w',
407 | type: 'motion',
408 | motion: 'moveByWords',
409 | motionArgs: {
410 | forward: true,
411 | wordEnd: false
412 | }
413 | }),
414 | 'vim:move-to-next-whole-word': h({
415 | keys: 'W',
416 | type: 'motion',
417 | motion: 'moveByWords',
418 | motionArgs: {
419 | forward: true,
420 | wordEnd: false,
421 | bigWord: true
422 | }
423 | }),
424 | 'vim:move-to-end-of-word': h({
425 | keys: 'e',
426 | type: 'motion',
427 | motion: 'moveByWords',
428 | motionArgs: {
429 | forward: true,
430 | wordEnd: true,
431 | inclusive: true
432 | }
433 | }),
434 | 'vim:move-to-previous-end-of-word': h({
435 | keys: 'ge',
436 | type: 'motion',
437 | motion: 'moveByWords',
438 | motionArgs: {
439 | forward: false,
440 | wordEnd: true,
441 | inclusive: true
442 | }
443 | }),
444 | 'vim:move-to-end-of-whole-word': h({
445 | keys: 'E',
446 | type: 'motion',
447 | motion: 'moveByWords',
448 | motionArgs: {
449 | forward: true,
450 | wordEnd: true,
451 | bigWord: true,
452 | inclusive: true
453 | }
454 | }),
455 | 'vim:move-to-previous-end-of-whole-word': h({
456 | keys: 'gE',
457 | type: 'motion',
458 | motion: 'moveByWords',
459 | motionArgs: {
460 | forward: false,
461 | wordEnd: true,
462 | bigWord: true,
463 | inclusive: true
464 | }
465 | }),
466 | 'vim:move-to-previous-word': h({
467 | keys: 'b',
468 | type: 'motion',
469 | motion: 'moveByWords',
470 | motionArgs: {
471 | forward: false,
472 | wordEnd: false
473 | }
474 | }),
475 | 'vim:move-to-previous-whole-word': h({
476 | keys: 'B',
477 | type: 'motion',
478 | motion: 'moveByWords',
479 | motionArgs: {
480 | forward: false,
481 | wordEnd: false,
482 | bigWord: true
483 | }
484 | }),
485 | 'vim:move-to-next-paragraph': h({
486 | keys: '}',
487 | type: 'motion',
488 | motion: 'moveByParagraph',
489 | motionArgs: {
490 | forward: true,
491 | toJumplist: true
492 | }
493 | }),
494 | 'vim:move-to-previous-paragraph': h({
495 | keys: '{',
496 | type: 'motion',
497 | motion: 'moveByParagraph',
498 | motionArgs: {
499 | forward: false,
500 | toJumplist: true
501 | }
502 | }),
503 | 'vim:move-to-beginning-of-line-with-zero': (() => {
504 | const handler = h({
505 | keys: '0',
506 | type: 'motion',
507 | motion: 'moveToStartOfLine'
508 | });
509 | return e => {
510 | const vim = this.vim.maybeInitVimState(cm);
511 | if (vim.inputState.getRepeat() > 0) {
512 | vim.inputState.pushRepeatDigit('0');
513 | } else {
514 | return handler(e);
515 | }
516 | };
517 | })(),
518 | 'vim:move-to-beginning-of-line': h({
519 | keys: '0',
520 | type: 'motion',
521 | motion: 'moveToStartOfLine'
522 | }),
523 | 'vim:move-to-first-character-of-line': h({
524 | keys: '^',
525 | type: 'motion',
526 | motion: 'moveToFirstNonWhiteSpaceCharacter'
527 | }),
528 | 'vim:move-to-first-character-of-line-and-down': h({
529 | keys: '_',
530 | type: 'motion',
531 | motion: 'moveByLines',
532 | motionArgs: {
533 | forward: true,
534 | toFirstChar: true,
535 | repeatOffset: -1
536 | }
537 | }),
538 | 'vim:move-to-last-character-of-line': h({
539 | keys: '$',
540 | type: 'motion',
541 | motion: 'moveToEol',
542 | motionArgs: {
543 | inclusive: true
544 | }
545 | }),
546 | 'vim:move-to-last-nonblank-character-of-line-and-down': () => {
547 | '???';
548 | },
549 | 'vim:move-to-first-character-of-line-up': h({
550 | keys: '-',
551 | type: 'motion',
552 | motion: 'moveByLines',
553 | motionArgs: {
554 | forward: false,
555 | toFirstChar: true
556 | }
557 | }),
558 | 'vim:move-to-first-character-of-line-down': h({
559 | keys: '+',
560 | type: 'motion',
561 | motion: 'moveByLines',
562 | motionArgs: {
563 | forward: true,
564 | toFirstChar: true
565 | }
566 | }),
567 | 'vim:move-to-start-of-file': h({
568 | keys: 'gg',
569 | type: 'motion',
570 | motion: 'moveToLineOrEdgeOfDocument',
571 | motionArgs: {
572 | forward: false,
573 | explicitRepeat: true,
574 | linewise: true,
575 | toJumplist: true
576 | }
577 | }),
578 | 'vim:scroll-half-screen-up': h({
579 | keys: '',
580 | type: 'motion',
581 | motion: 'moveByScroll',
582 | motionArgs: {
583 | forward: false,
584 | explicitRepeat: true
585 | }
586 | }),
587 | 'vim:scroll-full-screen-up': h({
588 | keys: '',
589 | type: 'motion',
590 | motion: 'moveByPage',
591 | motionArgs: {
592 | forward: false
593 | }
594 | }),
595 | 'vim:scroll-half-screen-down': h({
596 | keys: '',
597 | type: 'motion',
598 | motion: 'moveByScroll',
599 | motionArgs: {
600 | forward: true,
601 | explicitRepeat: true
602 | }
603 | }),
604 | 'vim:scroll-full-screen-down': h({
605 | keys: '',
606 | type: 'motion',
607 | motion: 'moveByPage',
608 | motionArgs: {
609 | forward: true
610 | }
611 | }),
612 | 'vim:scroll-down': h({
613 | keys: '',
614 | type: 'action',
615 | action: 'scroll',
616 | actionArgs: {
617 | forward: true,
618 | linewise: true
619 | }
620 | }),
621 | 'vim:scroll-up': h({
622 | keys: '',
623 | type: 'action',
624 | action: 'scroll',
625 | actionArgs: {
626 | forward: false,
627 | linewise: true
628 | }
629 | }),
630 | 'vim:scroll-cursor-to-top': h({
631 | keys: 'z',
632 | type: 'action',
633 | action: 'scrollToCursor',
634 | actionArgs: {
635 | position: 'top'
636 | },
637 | motion: 'moveToFirstNonWhiteSpaceCharacter'
638 | }),
639 | 'vim:scroll-cursor-to-top-leave': h({
640 | keys: 'zt',
641 | type: 'action',
642 | action: 'scrollToCursor',
643 | actionArgs: {
644 | position: 'top'
645 | }
646 | }),
647 | 'vim:scroll-cursor-to-middle': h({
648 | keys: 'z.',
649 | type: 'action',
650 | action: 'scrollToCursor',
651 | actionArgs: {
652 | position: 'center'
653 | },
654 | motion: 'moveToFirstNonWhiteSpaceCharacter'
655 | }),
656 | 'vim:scroll-cursor-to-middle-leave': h({
657 | keys: 'zz',
658 | type: 'action',
659 | action: 'scrollToCursor',
660 | actionArgs: {
661 | position: 'center'
662 | }
663 | }),
664 | 'vim:scroll-cursor-to-bottom': h({
665 | keys: 'z-',
666 | type: 'action',
667 | action: 'scrollToCursor',
668 | actionArgs: {
669 | position: 'bottom'
670 | }
671 | }),
672 | 'vim:scroll-cursor-to-bottom-leave': h({
673 | keys: 'zb',
674 | type: 'action',
675 | action: 'scrollToCursor',
676 | actionArgs: {
677 | position: 'bottom'
678 | },
679 | motion: 'moveToFirstNonWhiteSpaceCharacter'
680 | }),
681 | 'vim:move-to-line': h({
682 | keys: 'G',
683 | type: 'motion',
684 | motion: 'moveToLineOrEdgeOfDocument',
685 | motionArgs: {
686 | forward: true,
687 | explicitRepeat: true,
688 | linewise: true,
689 | toJumplist: true
690 | }
691 | }),
692 | 'vim:move-to-top-of-screen': h({
693 | keys: 'H',
694 | type: 'motion',
695 | motion: 'moveToTopLine',
696 | motionArgs: {
697 | linewise: true,
698 | toJumplist: true
699 | }
700 | }),
701 | 'vim:move-to-bottom-of-screen': h({
702 | keys: 'L',
703 | type: 'motion',
704 | motion: 'moveToBottomLine',
705 | motionArgs: {
706 | linewise: true,
707 | toJumplist: true
708 | }
709 | }),
710 | 'vim:move-to-middle-of-screen': h({
711 | keys: 'M',
712 | type: 'motion',
713 | motion: 'moveToMiddleLine',
714 | motionArgs: {
715 | linewise: true,
716 | toJumplist: true
717 | }
718 | }),
719 | 'vim:delete': p({
720 | keys: 'd',
721 | type: 'operator',
722 | operator: 'delete'
723 | }),
724 | 'vim:delete-to-last-character-of-line': h({
725 | keys: 'D',
726 | type: 'operatorMotion',
727 | operator: 'delete',
728 | motion: 'moveToEol',
729 | motionArgs: {
730 | inclusive: true
731 | },
732 | context: 'normal'
733 | }),
734 | 'vim:change': p({
735 | keys: 'c',
736 | type: 'operator',
737 | operator: 'change'
738 | }),
739 | 'vim:change-to-last-character-of-line': h({
740 | keys: 'C',
741 | type: 'operatorMotion',
742 | operator: 'change',
743 | motion: 'moveToEol',
744 | motionArgs: {
745 | inclusive: true
746 | },
747 | context: 'normal'
748 | }),
749 | 'vim:substitute-line': h({
750 | keys: 'S',
751 | type: 'keyToKey',
752 | toKeys: 'cc',
753 | context: 'normal'
754 | }),
755 | 'vim:substitute-line-visual': h({
756 | keys: 'S',
757 | type: 'keyToKey',
758 | toKeys: 'VdO',
759 | context: 'visual'
760 | }),
761 | 'vim:replace': b({
762 | keys: 'r',
763 | type: 'action',
764 | action: 'replace',
765 | isEdit: true
766 | }),
767 | 'vim:insert-at-beginning-of-line': h({
768 | keys: 'I',
769 | type: 'action',
770 | action: 'enterInsertMode',
771 | isEdit: true,
772 | actionArgs: {
773 | insertAt: 'firstNonBlank'
774 | },
775 | context: 'normal'
776 | }),
777 | 'vim:text-object-manipulation-inner': b({
778 | keys: 'i',
779 | type: 'motion',
780 | motion: 'textObjectManipulation',
781 | motionArgs: {
782 | textObjectInner: true
783 | }
784 | }),
785 | 'vim:text-object-manipulation': b({
786 | keys: 'a',
787 | type: 'motion',
788 | motion: 'textObjectManipulation'
789 | }),
790 | 'vim:indent': p({
791 | keys: '>',
792 | type: 'operator',
793 | operator: 'indent',
794 | operatorArgs: {
795 | indentRight: true
796 | }
797 | }),
798 | 'vim:outdent': p({
799 | keys: '<',
800 | type: 'operator',
801 | operator: 'indent',
802 | operatorArgs: {
803 | indentRight: false
804 | }
805 | }),
806 | 'vim:auto-indent': () => {
807 | 'not supported';
808 | },
809 | 'vim:reselect-last-selection': h({
810 | keys: 'gv',
811 | type: 'action',
812 | action: 'reselectLastSelection'
813 | }),
814 | 'vim:join': h({
815 | keys: 'J',
816 | type: 'action',
817 | action: 'joinLines',
818 | isEdit: true
819 | }),
820 | 'vim:yank': p({
821 | keys: 'y',
822 | type: 'operator',
823 | operator: 'yank'
824 | }),
825 | 'vim:yank-line': h({
826 | keys: 'Y',
827 | type: 'operatorMotion',
828 | operator: 'yank',
829 | motion: 'expandToLine',
830 | motionArgs: {
831 | linewise: true
832 | },
833 | context: 'normal'
834 | }),
835 | 'vim:put-before': h({
836 | keys: 'P',
837 | type: 'action',
838 | action: 'paste',
839 | isEdit: true,
840 | actionArgs: {
841 | after: false,
842 | isEdit: true
843 | }
844 | }),
845 | 'vim:put-after': h({
846 | keys: 'p',
847 | type: 'action',
848 | action: 'paste',
849 | isEdit: true,
850 | actionArgs: {
851 | after: true,
852 | isEdit: true
853 | }
854 | }),
855 | 'vim:toggle-case': h({
856 | keys: 'g~',
857 | type: 'operator',
858 | operator: 'changeCase'
859 | }),
860 | 'vim:upper-case': h({
861 | keys: 'gU',
862 | type: 'operator',
863 | operator: 'changeCase',
864 | operatorArgs: {
865 | toLower: false
866 | },
867 | isEdit: true
868 | }),
869 | 'vim:lower-case': h({
870 | keys: 'gu',
871 | type: 'operator',
872 | operator: 'changeCase',
873 | operatorArgs: {
874 | toLower: true
875 | },
876 | isEdit: true
877 | }),
878 | 'vim:toggle-case-now': h({
879 | keys: '~',
880 | type: 'operatorMotion',
881 | operator: 'changeCase',
882 | motion: 'moveByCharacters',
883 | motionArgs: {
884 | forward: true
885 | },
886 | operatorArgs: {
887 | shouldMoveCursor: true
888 | },
889 | context: 'normal'
890 | }),
891 | 'vim:mark': b({
892 | keys: 'm',
893 | type: 'action',
894 | action: 'setMark'
895 | }),
896 | 'vim:move-to-mark-literal': b({
897 | keys: '`',
898 | type: 'motion',
899 | motion: 'goToMark',
900 | motionArgs: {
901 | toJumplist: true
902 | }
903 | }),
904 | 'vim:move-to-mark': b({
905 | keys: "'",
906 | type: 'motion',
907 | motion: 'goToMark',
908 | motionArgs: {
909 | toJumplist: true,
910 | linewise: true
911 | }
912 | }),
913 | 'vim:find': b({
914 | keys: 'f',
915 | type: 'motion',
916 | motion: 'moveToCharacter',
917 | motionArgs: {
918 | forward: true,
919 | inclusive: true
920 | }
921 | }),
922 | 'vim:find-backwards': b({
923 | keys: 'F',
924 | type: 'motion',
925 | motion: 'moveToCharacter',
926 | motionArgs: {
927 | forward: false
928 | }
929 | }),
930 | 'vim:till': b({
931 | keys: 't',
932 | type: 'motion',
933 | motion: 'moveTillCharacter',
934 | motionArgs: {
935 | forward: true,
936 | inclusive: true
937 | }
938 | }),
939 | 'vim:till-backwards': b({
940 | keys: 'T',
941 | type: 'motion',
942 | motion: 'moveTillCharacter',
943 | motionArgs: {
944 | forward: false
945 | }
946 | }),
947 | 'vim:repeat-find': h({
948 | keys: ';',
949 | type: 'motion',
950 | motion: 'repeatLastCharacterSearch',
951 | motionArgs: {
952 | forward: true
953 | }
954 | }),
955 | 'vim:repeat-find-reverse': h({
956 | keys: ',',
957 | type: 'motion',
958 | motion: 'repeatLastCharacterSearch',
959 | motionArgs: {
960 | forward: false
961 | }
962 | }),
963 | 'vim:search': h({
964 | keys: '/',
965 | type: 'search',
966 | searchArgs: {
967 | forward: true,
968 | querySrc: 'prompt',
969 | toJumplist: true
970 | }
971 | }),
972 | 'vim:reverse-search': h({
973 | keys: '?',
974 | type: 'search',
975 | searchArgs: {
976 | forward: false,
977 | querySrc: 'prompt',
978 | toJumplist: true
979 | }
980 | }),
981 | 'vim:search-current-word': h({
982 | keys: '*',
983 | type: 'search',
984 | searchArgs: {
985 | forward: true,
986 | querySrc: 'wordUnderCursor',
987 | wholeWordOnly: true,
988 | toJumplist: true
989 | }
990 | }),
991 | 'vim:reverse-search-current-word': h({
992 | keys: '#',
993 | type: 'search',
994 | searchArgs: {
995 | forward: false,
996 | querySrc: 'wordUnderCursor',
997 | wholeWordOnly: true,
998 | toJumplist: true
999 | }
1000 | }),
1001 | 'vim:repeat-search': h({
1002 | keys: 'n',
1003 | type: 'motion',
1004 | motion: 'findNext',
1005 | motionArgs: {
1006 | forward: true,
1007 | toJumplist: true
1008 | }
1009 | }),
1010 | 'vim:repeat-search-backwards': h({
1011 | keys: 'N',
1012 | type: 'motion',
1013 | motion: 'findNext',
1014 | motionArgs: {
1015 | forward: false,
1016 | toJumplist: true
1017 | }
1018 | }),
1019 | 'vim:bracket-matching-motion': h({
1020 | keys: '%',
1021 | type: 'motion',
1022 | motion: 'moveToMatchedSymbol',
1023 | motionArgs: {
1024 | inclusive: true,
1025 | toJumplist: true
1026 | }
1027 | }),
1028 | 'vim:ex-command': h({
1029 | keys: ':',
1030 | type: 'ex'
1031 | }),
1032 | // normal mode
1033 | 'vim:activate-insert-mode': h({
1034 | keys: 'i',
1035 | type: 'action',
1036 | action: 'enterInsertMode',
1037 | isEdit: true,
1038 | actionArgs: {
1039 | insertAt: 'inplace'
1040 | },
1041 | context: 'normal'
1042 | }),
1043 | 'vim:activate-replace-mode': h({
1044 | keys: 'R',
1045 | type: 'action',
1046 | action: 'enterInsertMode',
1047 | isEdit: true,
1048 | actionArgs: {
1049 | replace: true
1050 | }
1051 | }),
1052 | 'vim:activate-characterwise-visual-mode': h({
1053 | keys: 'v',
1054 | type: 'action',
1055 | action: 'toggleVisualMode'
1056 | }),
1057 | 'vim:activate-linewise-visual-mode': h({
1058 | keys: 'V',
1059 | type: 'action',
1060 | action: 'toggleVisualMode',
1061 | actionArgs: {
1062 | linewise: true
1063 | }
1064 | }),
1065 | 'vim:activate-blockwise-visual-mode': h({
1066 | keys: '',
1067 | type: 'action',
1068 | action: 'toggleVisualMode',
1069 | actionArgs: {
1070 | blockwise: true
1071 | }
1072 | }),
1073 | 'vim:undo': h({
1074 | keys: 'u',
1075 | type: 'action',
1076 | action: 'undo',
1077 | context: 'normal'
1078 | }),
1079 | 'vim:insert-above-with-newline': h({
1080 | keys: 'O',
1081 | type: 'action',
1082 | action: 'newLineAndEnterInsertMode',
1083 | isEdit: true,
1084 | interlaceInsertRepeat: true,
1085 | actionArgs: {
1086 | after: false
1087 | },
1088 | context: 'normal'
1089 | }),
1090 | 'vim:insert-below-with-newline': h({
1091 | keys: 'o',
1092 | type: 'action',
1093 | action: 'newLineAndEnterInsertMode',
1094 | isEdit: true,
1095 | interlaceInsertRepeat: true,
1096 | actionArgs: {
1097 | after: true
1098 | },
1099 | context: 'normal'
1100 | }),
1101 | 'vim:insert-after': h({
1102 | keys: 'a',
1103 | type: 'action',
1104 | action: 'enterInsertMode',
1105 | isEdit: true,
1106 | actionArgs: {
1107 | insertAt: 'charAfter'
1108 | },
1109 | context: 'normal'
1110 | }),
1111 | 'vim:insert-after-end-of-line': h({
1112 | keys: 'A',
1113 | type: 'action',
1114 | action: 'enterInsertMode',
1115 | isEdit: true,
1116 | actionArgs: {
1117 | insertAt: 'eol'
1118 | },
1119 | context: 'normal'
1120 | }),
1121 | 'vim:delete-right': h({
1122 | keys: 'x',
1123 | type: 'operatorMotion',
1124 | operator: 'delete',
1125 | motion: 'moveByCharacters',
1126 | motionArgs: {
1127 | forward: true
1128 | },
1129 | operatorMotionArgs: {
1130 | visualLine: false
1131 | }
1132 | }),
1133 | 'vim:delete-left': h({
1134 | keys: 'X',
1135 | type: 'operatorMotion',
1136 | operator: 'delete',
1137 | motion: 'moveByCharacters',
1138 | motionArgs: {
1139 | forward: false
1140 | },
1141 | operatorMotionArgs: {
1142 | visualLine: true
1143 | }
1144 | }),
1145 | 'vim:substitute': h({
1146 | keys: 's',
1147 | type: 'keyToKey',
1148 | toKeys: 'cl',
1149 | context: 'normal'
1150 | }),
1151 | 'vim:substitute-visual': h({
1152 | keys: 's',
1153 | type: 'keyToKey',
1154 | toKeys: 'c',
1155 | context: 'visual'
1156 | }),
1157 | 'vim:repeat': h({
1158 | keys: '.',
1159 | type: 'action',
1160 | action: 'repeatLastEdit'
1161 | }),
1162 | 'vim:increase': h({
1163 | keys: '',
1164 | type: 'action',
1165 | action: 'incrementNumberToken',
1166 | isEdit: true,
1167 | actionArgs: {
1168 | increase: true,
1169 | backtrack: false
1170 | }
1171 | }),
1172 | 'vim:decrease': h({
1173 | keys: '',
1174 | type: 'action',
1175 | action: 'incrementNumberToken',
1176 | isEdit: true,
1177 | actionArgs: {
1178 | increase: false,
1179 | backtrack: false
1180 | }
1181 | }),
1182 | 'vim:register-prefix': b({
1183 | keys: '"',
1184 | type: 'action',
1185 | action: 'setRegister'
1186 | }),
1187 | // insert mode
1188 | 'vim:delete-to-beginning-of-word': h({
1189 | keys: '',
1190 | type: 'operatorMotion',
1191 | operator: 'delete',
1192 | motion: 'moveByWords',
1193 | motionArgs: {
1194 | forward: false,
1195 | wordEnd: false
1196 | },
1197 | context: 'insert'
1198 | }),
1199 | // visual mode
1200 | 'vim:insert-at-start-of-target': h({
1201 | keys: 'I',
1202 | type: 'action',
1203 | action: 'enterInsertMode',
1204 | isEdit: true,
1205 | actionArgs: {
1206 | insertAt: 'startOfSelectedArea'
1207 | },
1208 | context: 'visual'
1209 | }),
1210 | 'vim:insert-at-end-of-target': h({
1211 | keys: 'A',
1212 | type: 'action',
1213 | action: 'enterInsertMode',
1214 | isEdit: true,
1215 | actionArgs: {
1216 | insertAt: 'endOfSelectedArea'
1217 | },
1218 | context: 'visual'
1219 | }),
1220 | 'vim:reverse-selections': h({
1221 | keys: 'o',
1222 | type: 'motion',
1223 | motion: 'moveToOtherHighlightedEnd',
1224 | context: 'visual'
1225 | }),
1226 | 'vim:reverse-selections-at-same-line': h({
1227 | keys: 'O',
1228 | type: 'motion',
1229 | motion: 'moveToOtherHighlightedEnd',
1230 | motionArgs: {
1231 | sameLine: true
1232 | },
1233 | context: 'visual'
1234 | })
1235 | };
1236 | disposables.add(inkdrop.commands.add(wrapper, handlers));
1237 | disposables.add(inkdrop.commands.add(document.querySelector('.mde-preview'), {
1238 | 'vim:move-to-start-of-file': ({
1239 | target
1240 | }) => {
1241 | target.scrollTop = 0;
1242 | },
1243 | 'vim:scroll-up': ({
1244 | target
1245 | }) => {
1246 | target.scrollTop -= 30;
1247 | },
1248 | 'vim:scroll-down': ({
1249 | target
1250 | }) => {
1251 | target.scrollTop += 30;
1252 | },
1253 | 'vim:scroll-half-screen-up': ({
1254 | target
1255 | }) => {
1256 | target.scrollTop -= target.clientHeight / 2;
1257 | },
1258 | 'vim:scroll-half-screen-down': ({
1259 | target
1260 | }) => {
1261 | target.scrollTop += target.clientHeight / 2;
1262 | },
1263 | 'vim:scroll-full-screen-up': ({
1264 | target
1265 | }) => {
1266 | target.scrollTop -= target.clientHeight;
1267 | },
1268 | 'vim:scroll-full-screen-down': ({
1269 | target
1270 | }) => {
1271 | target.scrollTop += target.clientHeight;
1272 | },
1273 | 'vim:move-to-line': ({
1274 | target
1275 | }) => {
1276 | target.scrollTop = target.scrollHeight;
1277 | }
1278 | }));
1279 | wrapper.addEventListener('textInput', this.handleEditorTextInput);
1280 | wrapper.addEventListener('keydown', this.handleEditorKeyDown);
1281 | disposables.add(new _eventKit.Disposable(() => wrapper.removeEventListener('keydown', this.handleEditorKeyDown)));
1282 | this.disposables = disposables;
1283 | }
1284 | registerExCommands() {
1285 | const el = this.getCodeMirror().getWrapperElement();
1286 | this.vim.defineEx('write', 'w', () => {
1287 | inkdrop.commands.dispatch(el, 'core:save-note');
1288 | });
1289 | this.vim.defineEx('next', 'n', () => {
1290 | inkdrop.commands.dispatch(el, 'core:open-next-note');
1291 | });
1292 | this.vim.defineEx('prev', '', () => {
1293 | inkdrop.commands.dispatch(el, 'core:open-prev-note');
1294 | });
1295 | this.vim.defineEx('preview', 'p', () => {
1296 | inkdrop.commands.dispatch(el, 'view:toggle-preview');
1297 | });
1298 | this.vim.defineEx('side-by-side', 'side', () => {
1299 | inkdrop.commands.dispatch(el, 'view:toggle-side-by-side');
1300 | });
1301 | }
1302 | getCodeMirror() {
1303 | return inkdrop.getActiveEditor().cm;
1304 | }
1305 | yankClipboard() {
1306 | const state = this.vim.getVimGlobalState();
1307 | const text = _electron.clipboard.readText();
1308 | const linewise = text.indexOf('\n') >= 0;
1309 | state.registerController.pushText('0', 'yank', text, linewise, true);
1310 | }
1311 | }
1312 | module.exports = new Plugin();
--------------------------------------------------------------------------------
/lib/vim.js.map:
--------------------------------------------------------------------------------
1 | {"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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"}
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vim",
3 | "main": "./lib/vim",
4 | "version": "2.2.2",
5 | "description": "vim keybindings",
6 | "keywords": [],
7 | "repository": "https://github.com/inkdropapp/inkdrop-vim",
8 | "license": "MIT",
9 | "scripts": {
10 | "build": "babel src/ -d lib/",
11 | "dev": "babel src/ -s -d lib/ --watch"
12 | },
13 | "engines": {
14 | "inkdrop": "^5.x"
15 | },
16 | "devDependencies": {
17 | "@babel/cli": "^7.16.0",
18 | "@babel/core": "^7.16.0",
19 | "@babel/eslint-parser": "^7.16.3",
20 | "@babel/plugin-proposal-class-properties": "^7.16.0",
21 | "@babel/preset-env": "^7.16.4",
22 | "@babel/preset-react": "^7.16.0",
23 | "eslint": "^8.3.0",
24 | "eslint-config-prettier": "^8.3.0",
25 | "prettier": "^2.5.0"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | const options = {
2 | arrowParens: 'avoid',
3 | singleQuote: true,
4 | bracketSpacing: true,
5 | endOfLine: 'lf',
6 | semi: false,
7 | tabWidth: 2,
8 | trailingComma: 'none'
9 | }
10 |
11 | module.exports = options
12 |
--------------------------------------------------------------------------------
/src/vim.js:
--------------------------------------------------------------------------------
1 | import { logger } from 'inkdrop'
2 | import vimKeymap from './keymap'
3 | import { CompositeDisposable, Disposable } from 'event-kit'
4 | import CodeMirror from 'codemirror'
5 | import { clipboard } from 'electron'
6 |
7 | class Plugin {
8 | config = {
9 | seamlessJumpToTitle: {
10 | title: 'Seamlessly jump to note title',
11 | type: 'boolean',
12 | description:
13 | 'Focus jumps from the editor to the note title bar by `vim:move-up` command',
14 | default: false
15 | }
16 | }
17 |
18 | activate() {
19 | this.vim = vimKeymap(CodeMirror)
20 | if (inkdrop.isEditorActive()) {
21 | this.activateMode(inkdrop.getActiveEditor())
22 | }
23 | inkdrop.onEditorLoad(this.handleEditorLoad)
24 | }
25 |
26 | deactivate() {
27 | if (this.disposables) {
28 | this.disposables.dispose()
29 | }
30 | if (inkdrop.isEditorActive()) {
31 | this.deactivateMode(inkdrop.getActiveEditor())
32 | }
33 | }
34 |
35 | activateMode(editor) {
36 | const { cm } = editor
37 | this.originalKeyMap = cm.getOption('keyMap')
38 | cm.setOption('keyMap', 'vim')
39 | cm.on('vim-mode-change', this.handleVimModeChange)
40 | cm.on('focus', this.handleFocusEditor)
41 |
42 | const el = cm.getWrapperElement()
43 | el.classList.add('vim-mode', 'normal-mode')
44 |
45 | this.registerCommands()
46 | this.registerExCommands()
47 | }
48 |
49 | deactivateMode(editor) {
50 | const { cm } = editor
51 | if (cm && this.originalKeyMap) {
52 | cm.setOption('keyMap', this.originalKeyMap)
53 | cm.off('vim-mode-change', this.handleVimModeChange)
54 | const el = cm.getWrapperElement()
55 | el.classList.remove('vim-mode')
56 | }
57 | }
58 |
59 | normalizeKeyName(key) {
60 | switch (key) {
61 | case 'Enter':
62 | return 'enter'
63 | case ' ':
64 | return 'space'
65 | case 'ArrowRight':
66 | return 'right'
67 | case 'ArrowLeft':
68 | return 'left'
69 | case 'ArrowUp':
70 | return 'up'
71 | case 'ArrowDown':
72 | return 'down'
73 | default:
74 | if (key.match(/^[A-Z]$/)) {
75 | return `shift-${key}`
76 | }
77 | return key
78 | }
79 | }
80 |
81 | startBufferingKey(command, customBufferingModeClass) {
82 | const wrapper = this.getCodeMirror().getWrapperElement()
83 | logger.debug('Start key buffering')
84 | wrapper.classList.add('key-buffering')
85 | if (customBufferingModeClass) {
86 | wrapper.classList.add('key-buffering-' + customBufferingModeClass)
87 | }
88 | this.pendingCommand = command
89 | }
90 |
91 | stopBufferingKey() {
92 | logger.debug('Stop key buffering')
93 | const wrapper = this.getCodeMirror().getWrapperElement()
94 | const classes = Array.prototype.slice.apply(wrapper.classList)
95 | for (const i of classes) {
96 | if (i.startsWith('key-buffering')) {
97 | wrapper.classList.remove(i)
98 | }
99 | }
100 | this.pendingCommand = undefined
101 | }
102 |
103 | isBufferingKey() {
104 | const wrapper = this.getCodeMirror().getWrapperElement()
105 | return wrapper.classList.contains('key-buffering')
106 | }
107 |
108 | bufferKey(key) {
109 | const cm = this.getCodeMirror()
110 | const vim = this.vim.maybeInitVimState(cm)
111 | const vimKey = this.vim.cmKeyToVimKey("'" + key + "'")
112 | vim.inputState.keyBuffer = vim.inputState.keyBuffer + vimKey
113 | logger.debug('keyBuffer:', vim.inputState.keyBuffer, vim.inputState)
114 | }
115 |
116 | isInsertMode() {
117 | const wrapper = this.getCodeMirror().getWrapperElement()
118 | return wrapper.classList.contains('insert-mode')
119 | }
120 |
121 | registerCommands() {
122 | const disposables = new CompositeDisposable()
123 | const editor = inkdrop.getActiveEditor()
124 | const { cm } = editor
125 | const wrapper = cm.getWrapperElement()
126 |
127 | const doKeyToKey = async command => {
128 | logger.debug('doKeyToKey:', command)
129 | let keys = command.toKeys
130 | while (keys) {
131 | // Pull off one command key, which is either a single character
132 | // or a special sequence wrapped in '<' and '>', e.g. ''.
133 | const match = /<\w+-.+?>|<\w+>|./.exec(keys)
134 | let key = match[0]
135 | logger.debug('key:', key)
136 | keys = keys.substring(match.index + key.length)
137 |
138 | if (this.isBufferingKey()) {
139 | this.handleEditorKeyDown(new KeyboardEvent('keydown', { key }))
140 | } else {
141 | if (key.match(/^[A-Z]$/)) {
142 | key = 'shift-' + key
143 | }
144 | const { exactMatchCandidates } = inkdrop.keymaps.findMatchCandidates([
145 | key
146 | ])
147 | logger.debug('exactMatchCandidates:', exactMatchCandidates)
148 | const bindings = inkdrop.keymaps.findExactMatches(
149 | exactMatchCandidates,
150 | document.activeElement
151 | )
152 | const b = bindings[0]
153 | if (b) {
154 | inkdrop.commands.dispatch(document.activeElement, b.command)
155 | } else {
156 | logger.debug('command not found for key:', key)
157 | }
158 | }
159 | }
160 | }
161 |
162 | // bind key to command
163 | const h = command => {
164 | return e => {
165 | logger.debug(
166 | 'command:',
167 | command,
168 | 'state:',
169 | Object.assign({}, cm.state.vim.inputState)
170 | )
171 | e.stopPropagation()
172 | const vim = this.vim.maybeInitVimState(cm)
173 | return cm.operation(() => {
174 | cm.curOp.isVimOp = true
175 | try {
176 | if (command.type === 'keyToKey') {
177 | doKeyToKey(command)
178 | } else {
179 | this.vim.commandDispatcher.processCommand(cm, vim, command)
180 | }
181 | } catch (e) {
182 | // clear VIM state in case it's in a bad state.
183 | cm.state.vim = undefined
184 | this.vim.maybeInitVimState(cm)
185 | if (!CodeMirror.Vim.suppressErrorLogging) {
186 | console.error(e)
187 | }
188 | throw e
189 | }
190 | return true
191 | })
192 | }
193 | }
194 | // bind keystroke to command
195 | const b = command => {
196 | return e => {
197 | logger.debug(
198 | 'buffer command:',
199 | command,
200 | 'state:',
201 | Object.assign({}, cm.state.vim.inputState),
202 | e.originalEvent
203 | )
204 | this.startBufferingKey(h(command), 'command')
205 | this.bufferKey(e.originalEvent.key)
206 | }
207 | }
208 | // bind keystroke to operator
209 | const p = command => {
210 | return e => {
211 | logger.debug(
212 | 'operator command:',
213 | command,
214 | 'state:',
215 | Object.assign({}, cm.state.vim.inputState),
216 | e.originalEvent,
217 | e
218 | )
219 | const vim = this.vim.maybeInitVimState(cm)
220 | if (
221 | !vim.inputState.operator &&
222 | !this.isBufferingKey() &&
223 | !vim.visualMode
224 | ) {
225 | this.startBufferingKey(e => {
226 | const el = cm.getInputField()
227 | const keyName = this.normalizeKeyName(e.key)
228 | const keyBinding = inkdrop.keymaps.findKeyBindings({
229 | keystrokes: keyName,
230 | target: el
231 | })
232 | if (keyBinding.length > 0) {
233 | inkdrop.commands.dispatch(el, keyBinding[0].command)
234 | return true
235 | } else {
236 | return false
237 | }
238 | }, 'operator')
239 | if (e.originalEvent) {
240 | this.bufferKey(e.originalEvent.key)
241 | } else {
242 | logger.debug('buffer key:', command.keys)
243 | this.bufferKey(command.keys)
244 | }
245 | }
246 | return h(command)(e)
247 | }
248 | }
249 | const handlers = {
250 | 'vim:native!': () => {},
251 | 'vim:reset-normal-mode': e => {
252 | CodeMirror.Vim.clearInputState(cm)
253 | this.stopBufferingKey()
254 | e.stopPropagation()
255 | },
256 | 'vim:exit-visual-mode': e => {
257 | logger.debug('exit-visual-mode')
258 | CodeMirror.Vim.clearInputState(cm)
259 | CodeMirror.Vim.exitVisualMode(cm)
260 | this.stopBufferingKey()
261 | e.stopPropagation()
262 | },
263 | 'vim:exit-insert-mode': e => {
264 | logger.debug('exit-insert-mode')
265 | CodeMirror.Vim.clearInputState(cm)
266 | CodeMirror.Vim.exitInsertMode(cm)
267 | this.stopBufferingKey()
268 | e.stopPropagation()
269 | },
270 | 'vim:move-left': h({
271 | keys: 'h',
272 | type: 'motion',
273 | motion: 'moveByCharacters',
274 | motionArgs: { forward: false }
275 | }),
276 | 'vim:move-right': h({
277 | keys: 'l',
278 | type: 'motion',
279 | motion: 'moveByCharacters',
280 | motionArgs: { forward: true }
281 | }),
282 | 'vim:move-up': (command => {
283 | return e => {
284 | const seamlessJumpToTitleEnabled = inkdrop.config.get('vim.seamlessJumpToTitle')
285 | const cur = cm.getCursor()
286 | if (cur.line === 0 && cur.ch === 0 && seamlessJumpToTitleEnabled) {
287 | e.stopPropagation()
288 | inkdrop.commands.dispatch(document.body, 'editor:title:focus')
289 | } else {
290 | command(e)
291 | }
292 | }
293 | })(
294 | h({
295 | keys: 'k',
296 | type: 'motion',
297 | motion: 'moveByLines',
298 | motionArgs: { forward: false, linewise: true }
299 | })
300 | ),
301 | 'vim:move-down': h({
302 | keys: 'j',
303 | type: 'motion',
304 | motion: 'moveByLines',
305 | motionArgs: { forward: true, linewise: true }
306 | }),
307 | 'vim:move-up-by-display-lines': h({
308 | keys: 'gk',
309 | type: 'motion',
310 | motion: 'moveByDisplayLines',
311 | motionArgs: { forward: false }
312 | }),
313 | 'vim:move-down-by-display-lines': h({
314 | keys: 'gj',
315 | type: 'motion',
316 | motion: 'moveByDisplayLines',
317 | motionArgs: { forward: true }
318 | }),
319 |
320 | 'vim:move-to-next-word': h({
321 | keys: 'w',
322 | type: 'motion',
323 | motion: 'moveByWords',
324 | motionArgs: { forward: true, wordEnd: false }
325 | }),
326 | 'vim:move-to-next-whole-word': h({
327 | keys: 'W',
328 | type: 'motion',
329 | motion: 'moveByWords',
330 | motionArgs: { forward: true, wordEnd: false, bigWord: true }
331 | }),
332 | 'vim:move-to-end-of-word': h({
333 | keys: 'e',
334 | type: 'motion',
335 | motion: 'moveByWords',
336 | motionArgs: { forward: true, wordEnd: true, inclusive: true }
337 | }),
338 | 'vim:move-to-previous-end-of-word': h({
339 | keys: 'ge',
340 | type: 'motion',
341 | motion: 'moveByWords',
342 | motionArgs: { forward: false, wordEnd: true, inclusive: true }
343 | }),
344 | 'vim:move-to-end-of-whole-word': h({
345 | keys: 'E',
346 | type: 'motion',
347 | motion: 'moveByWords',
348 | motionArgs: {
349 | forward: true,
350 | wordEnd: true,
351 | bigWord: true,
352 | inclusive: true
353 | }
354 | }),
355 | 'vim:move-to-previous-end-of-whole-word': h({
356 | keys: 'gE',
357 | type: 'motion',
358 | motion: 'moveByWords',
359 | motionArgs: {
360 | forward: false,
361 | wordEnd: true,
362 | bigWord: true,
363 | inclusive: true
364 | }
365 | }),
366 | 'vim:move-to-previous-word': h({
367 | keys: 'b',
368 | type: 'motion',
369 | motion: 'moveByWords',
370 | motionArgs: { forward: false, wordEnd: false }
371 | }),
372 | 'vim:move-to-previous-whole-word': h({
373 | keys: 'B',
374 | type: 'motion',
375 | motion: 'moveByWords',
376 | motionArgs: { forward: false, wordEnd: false, bigWord: true }
377 | }),
378 | 'vim:move-to-next-paragraph': h({
379 | keys: '}',
380 | type: 'motion',
381 | motion: 'moveByParagraph',
382 | motionArgs: { forward: true, toJumplist: true }
383 | }),
384 | 'vim:move-to-previous-paragraph': h({
385 | keys: '{',
386 | type: 'motion',
387 | motion: 'moveByParagraph',
388 | motionArgs: { forward: false, toJumplist: true }
389 | }),
390 | 'vim:move-to-beginning-of-line-with-zero': (() => {
391 | const handler = h({
392 | keys: '0',
393 | type: 'motion',
394 | motion: 'moveToStartOfLine'
395 | })
396 | return e => {
397 | const vim = this.vim.maybeInitVimState(cm)
398 | if (vim.inputState.getRepeat() > 0) {
399 | vim.inputState.pushRepeatDigit('0')
400 | } else {
401 | return handler(e)
402 | }
403 | }
404 | })(),
405 | 'vim:move-to-beginning-of-line': h({
406 | keys: '0',
407 | type: 'motion',
408 | motion: 'moveToStartOfLine'
409 | }),
410 | 'vim:move-to-first-character-of-line': h({
411 | keys: '^',
412 | type: 'motion',
413 | motion: 'moveToFirstNonWhiteSpaceCharacter'
414 | }),
415 | 'vim:move-to-first-character-of-line-and-down': h({
416 | keys: '_',
417 | type: 'motion',
418 | motion: 'moveByLines',
419 | motionArgs: { forward: true, toFirstChar: true, repeatOffset: -1 }
420 | }),
421 | 'vim:move-to-last-character-of-line': h({
422 | keys: '$',
423 | type: 'motion',
424 | motion: 'moveToEol',
425 | motionArgs: { inclusive: true }
426 | }),
427 | 'vim:move-to-last-nonblank-character-of-line-and-down': () => {
428 | '???'
429 | },
430 | 'vim:move-to-first-character-of-line-up': h({
431 | keys: '-',
432 | type: 'motion',
433 | motion: 'moveByLines',
434 | motionArgs: { forward: false, toFirstChar: true }
435 | }),
436 | 'vim:move-to-first-character-of-line-down': h({
437 | keys: '+',
438 | type: 'motion',
439 | motion: 'moveByLines',
440 | motionArgs: { forward: true, toFirstChar: true }
441 | }),
442 |
443 | 'vim:move-to-start-of-file': h({
444 | keys: 'gg',
445 | type: 'motion',
446 | motion: 'moveToLineOrEdgeOfDocument',
447 | motionArgs: {
448 | forward: false,
449 | explicitRepeat: true,
450 | linewise: true,
451 | toJumplist: true
452 | }
453 | }),
454 | 'vim:scroll-half-screen-up': h({
455 | keys: '',
456 | type: 'motion',
457 | motion: 'moveByScroll',
458 | motionArgs: { forward: false, explicitRepeat: true }
459 | }),
460 | 'vim:scroll-full-screen-up': h({
461 | keys: '',
462 | type: 'motion',
463 | motion: 'moveByPage',
464 | motionArgs: { forward: false }
465 | }),
466 | 'vim:scroll-half-screen-down': h({
467 | keys: '',
468 | type: 'motion',
469 | motion: 'moveByScroll',
470 | motionArgs: { forward: true, explicitRepeat: true }
471 | }),
472 | 'vim:scroll-full-screen-down': h({
473 | keys: '',
474 | type: 'motion',
475 | motion: 'moveByPage',
476 | motionArgs: { forward: true }
477 | }),
478 | 'vim:scroll-down': h({
479 | keys: '',
480 | type: 'action',
481 | action: 'scroll',
482 | actionArgs: { forward: true, linewise: true }
483 | }),
484 | 'vim:scroll-up': h({
485 | keys: '',
486 | type: 'action',
487 | action: 'scroll',
488 | actionArgs: { forward: false, linewise: true }
489 | }),
490 | 'vim:scroll-cursor-to-top': h({
491 | keys: 'z',
492 | type: 'action',
493 | action: 'scrollToCursor',
494 | actionArgs: { position: 'top' },
495 | motion: 'moveToFirstNonWhiteSpaceCharacter'
496 | }),
497 | 'vim:scroll-cursor-to-top-leave': h({
498 | keys: 'zt',
499 | type: 'action',
500 | action: 'scrollToCursor',
501 | actionArgs: { position: 'top' }
502 | }),
503 | 'vim:scroll-cursor-to-middle': h({
504 | keys: 'z.',
505 | type: 'action',
506 | action: 'scrollToCursor',
507 | actionArgs: { position: 'center' },
508 | motion: 'moveToFirstNonWhiteSpaceCharacter'
509 | }),
510 | 'vim:scroll-cursor-to-middle-leave': h({
511 | keys: 'zz',
512 | type: 'action',
513 | action: 'scrollToCursor',
514 | actionArgs: { position: 'center' }
515 | }),
516 | 'vim:scroll-cursor-to-bottom': h({
517 | keys: 'z-',
518 | type: 'action',
519 | action: 'scrollToCursor',
520 | actionArgs: { position: 'bottom' }
521 | }),
522 | 'vim:scroll-cursor-to-bottom-leave': h({
523 | keys: 'zb',
524 | type: 'action',
525 | action: 'scrollToCursor',
526 | actionArgs: { position: 'bottom' },
527 | motion: 'moveToFirstNonWhiteSpaceCharacter'
528 | }),
529 | 'vim:move-to-line': h({
530 | keys: 'G',
531 | type: 'motion',
532 | motion: 'moveToLineOrEdgeOfDocument',
533 | motionArgs: {
534 | forward: true,
535 | explicitRepeat: true,
536 | linewise: true,
537 | toJumplist: true
538 | }
539 | }),
540 | 'vim:move-to-top-of-screen': h({
541 | keys: 'H',
542 | type: 'motion',
543 | motion: 'moveToTopLine',
544 | motionArgs: { linewise: true, toJumplist: true }
545 | }),
546 | 'vim:move-to-bottom-of-screen': h({
547 | keys: 'L',
548 | type: 'motion',
549 | motion: 'moveToBottomLine',
550 | motionArgs: { linewise: true, toJumplist: true }
551 | }),
552 | 'vim:move-to-middle-of-screen': h({
553 | keys: 'M',
554 | type: 'motion',
555 | motion: 'moveToMiddleLine',
556 | motionArgs: { linewise: true, toJumplist: true }
557 | }),
558 |
559 | 'vim:delete': p({ keys: 'd', type: 'operator', operator: 'delete' }),
560 | 'vim:delete-to-last-character-of-line': h({
561 | keys: 'D',
562 | type: 'operatorMotion',
563 | operator: 'delete',
564 | motion: 'moveToEol',
565 | motionArgs: { inclusive: true },
566 | context: 'normal'
567 | }),
568 | 'vim:change': p({ keys: 'c', type: 'operator', operator: 'change' }),
569 | 'vim:change-to-last-character-of-line': h({
570 | keys: 'C',
571 | type: 'operatorMotion',
572 | operator: 'change',
573 | motion: 'moveToEol',
574 | motionArgs: { inclusive: true },
575 | context: 'normal'
576 | }),
577 | 'vim:substitute-line': h({
578 | keys: 'S',
579 | type: 'keyToKey',
580 | toKeys: 'cc',
581 | context: 'normal'
582 | }),
583 | 'vim:substitute-line-visual': h({
584 | keys: 'S',
585 | type: 'keyToKey',
586 | toKeys: 'VdO',
587 | context: 'visual'
588 | }),
589 | 'vim:replace': b({
590 | keys: 'r',
591 | type: 'action',
592 | action: 'replace',
593 | isEdit: true
594 | }),
595 | 'vim:insert-at-beginning-of-line': h({
596 | keys: 'I',
597 | type: 'action',
598 | action: 'enterInsertMode',
599 | isEdit: true,
600 | actionArgs: { insertAt: 'firstNonBlank' },
601 | context: 'normal'
602 | }),
603 | 'vim:text-object-manipulation-inner': b({
604 | keys: 'i',
605 | type: 'motion',
606 | motion: 'textObjectManipulation',
607 | motionArgs: { textObjectInner: true }
608 | }),
609 | 'vim:text-object-manipulation': b({
610 | keys: 'a',
611 | type: 'motion',
612 | motion: 'textObjectManipulation'
613 | }),
614 | 'vim:indent': p({
615 | keys: '>',
616 | type: 'operator',
617 | operator: 'indent',
618 | operatorArgs: { indentRight: true }
619 | }),
620 | 'vim:outdent': p({
621 | keys: '<',
622 | type: 'operator',
623 | operator: 'indent',
624 | operatorArgs: { indentRight: false }
625 | }),
626 | 'vim:auto-indent': () => {
627 | 'not supported'
628 | },
629 | 'vim:reselect-last-selection': h({
630 | keys: 'gv',
631 | type: 'action',
632 | action: 'reselectLastSelection'
633 | }),
634 | 'vim:join': h({
635 | keys: 'J',
636 | type: 'action',
637 | action: 'joinLines',
638 | isEdit: true
639 | }),
640 |
641 | 'vim:yank': p({ keys: 'y', type: 'operator', operator: 'yank' }),
642 | 'vim:yank-line': h({
643 | keys: 'Y',
644 | type: 'operatorMotion',
645 | operator: 'yank',
646 | motion: 'expandToLine',
647 | motionArgs: { linewise: true },
648 | context: 'normal'
649 | }),
650 | 'vim:put-before': h({
651 | keys: 'P',
652 | type: 'action',
653 | action: 'paste',
654 | isEdit: true,
655 | actionArgs: { after: false, isEdit: true }
656 | }),
657 | 'vim:put-after': h({
658 | keys: 'p',
659 | type: 'action',
660 | action: 'paste',
661 | isEdit: true,
662 | actionArgs: { after: true, isEdit: true }
663 | }),
664 |
665 | 'vim:toggle-case': h({
666 | keys: 'g~',
667 | type: 'operator',
668 | operator: 'changeCase'
669 | }),
670 | 'vim:upper-case': h({
671 | keys: 'gU',
672 | type: 'operator',
673 | operator: 'changeCase',
674 | operatorArgs: { toLower: false },
675 | isEdit: true
676 | }),
677 | 'vim:lower-case': h({
678 | keys: 'gu',
679 | type: 'operator',
680 | operator: 'changeCase',
681 | operatorArgs: { toLower: true },
682 | isEdit: true
683 | }),
684 | 'vim:toggle-case-now': h({
685 | keys: '~',
686 | type: 'operatorMotion',
687 | operator: 'changeCase',
688 | motion: 'moveByCharacters',
689 | motionArgs: { forward: true },
690 | operatorArgs: { shouldMoveCursor: true },
691 | context: 'normal'
692 | }),
693 |
694 | 'vim:mark': b({
695 | keys: 'm',
696 | type: 'action',
697 | action: 'setMark'
698 | }),
699 | 'vim:move-to-mark-literal': b({
700 | keys: '`',
701 | type: 'motion',
702 | motion: 'goToMark',
703 | motionArgs: { toJumplist: true }
704 | }),
705 | 'vim:move-to-mark': b({
706 | keys: "'",
707 | type: 'motion',
708 | motion: 'goToMark',
709 | motionArgs: { toJumplist: true, linewise: true }
710 | }),
711 |
712 | 'vim:find': b({
713 | keys: 'f',
714 | type: 'motion',
715 | motion: 'moveToCharacter',
716 | motionArgs: { forward: true, inclusive: true }
717 | }),
718 | 'vim:find-backwards': b({
719 | keys: 'F',
720 | type: 'motion',
721 | motion: 'moveToCharacter',
722 | motionArgs: { forward: false }
723 | }),
724 | 'vim:till': b({
725 | keys: 't',
726 | type: 'motion',
727 | motion: 'moveTillCharacter',
728 | motionArgs: { forward: true, inclusive: true }
729 | }),
730 | 'vim:till-backwards': b({
731 | keys: 'T',
732 | type: 'motion',
733 | motion: 'moveTillCharacter',
734 | motionArgs: { forward: false }
735 | }),
736 | 'vim:repeat-find': h({
737 | keys: ';',
738 | type: 'motion',
739 | motion: 'repeatLastCharacterSearch',
740 | motionArgs: { forward: true }
741 | }),
742 | 'vim:repeat-find-reverse': h({
743 | keys: ',',
744 | type: 'motion',
745 | motion: 'repeatLastCharacterSearch',
746 | motionArgs: { forward: false }
747 | }),
748 |
749 | 'vim:search': h({
750 | keys: '/',
751 | type: 'search',
752 | searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }
753 | }),
754 | 'vim:reverse-search': h({
755 | keys: '?',
756 | type: 'search',
757 | searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }
758 | }),
759 | 'vim:search-current-word': h({
760 | keys: '*',
761 | type: 'search',
762 | searchArgs: {
763 | forward: true,
764 | querySrc: 'wordUnderCursor',
765 | wholeWordOnly: true,
766 | toJumplist: true
767 | }
768 | }),
769 | 'vim:reverse-search-current-word': h({
770 | keys: '#',
771 | type: 'search',
772 | searchArgs: {
773 | forward: false,
774 | querySrc: 'wordUnderCursor',
775 | wholeWordOnly: true,
776 | toJumplist: true
777 | }
778 | }),
779 | 'vim:repeat-search': h({
780 | keys: 'n',
781 | type: 'motion',
782 | motion: 'findNext',
783 | motionArgs: { forward: true, toJumplist: true }
784 | }),
785 | 'vim:repeat-search-backwards': h({
786 | keys: 'N',
787 | type: 'motion',
788 | motion: 'findNext',
789 | motionArgs: { forward: false, toJumplist: true }
790 | }),
791 |
792 | 'vim:bracket-matching-motion': h({
793 | keys: '%',
794 | type: 'motion',
795 | motion: 'moveToMatchedSymbol',
796 | motionArgs: { inclusive: true, toJumplist: true }
797 | }),
798 |
799 | 'vim:ex-command': h({ keys: ':', type: 'ex' }),
800 |
801 | // normal mode
802 | 'vim:activate-insert-mode': h({
803 | keys: 'i',
804 | type: 'action',
805 | action: 'enterInsertMode',
806 | isEdit: true,
807 | actionArgs: { insertAt: 'inplace' },
808 | context: 'normal'
809 | }),
810 | 'vim:activate-replace-mode': h({
811 | keys: 'R',
812 | type: 'action',
813 | action: 'enterInsertMode',
814 | isEdit: true,
815 | actionArgs: { replace: true }
816 | }),
817 | 'vim:activate-characterwise-visual-mode': h({
818 | keys: 'v',
819 | type: 'action',
820 | action: 'toggleVisualMode'
821 | }),
822 | 'vim:activate-linewise-visual-mode': h({
823 | keys: 'V',
824 | type: 'action',
825 | action: 'toggleVisualMode',
826 | actionArgs: { linewise: true }
827 | }),
828 | 'vim:activate-blockwise-visual-mode': h({
829 | keys: '',
830 | type: 'action',
831 | action: 'toggleVisualMode',
832 | actionArgs: { blockwise: true }
833 | }),
834 |
835 | 'vim:undo': h({
836 | keys: 'u',
837 | type: 'action',
838 | action: 'undo',
839 | context: 'normal'
840 | }),
841 |
842 | 'vim:insert-above-with-newline': h({
843 | keys: 'O',
844 | type: 'action',
845 | action: 'newLineAndEnterInsertMode',
846 | isEdit: true,
847 | interlaceInsertRepeat: true,
848 | actionArgs: { after: false },
849 | context: 'normal'
850 | }),
851 | 'vim:insert-below-with-newline': h({
852 | keys: 'o',
853 | type: 'action',
854 | action: 'newLineAndEnterInsertMode',
855 | isEdit: true,
856 | interlaceInsertRepeat: true,
857 | actionArgs: { after: true },
858 | context: 'normal'
859 | }),
860 | 'vim:insert-after': h({
861 | keys: 'a',
862 | type: 'action',
863 | action: 'enterInsertMode',
864 | isEdit: true,
865 | actionArgs: { insertAt: 'charAfter' },
866 | context: 'normal'
867 | }),
868 | 'vim:insert-after-end-of-line': h({
869 | keys: 'A',
870 | type: 'action',
871 | action: 'enterInsertMode',
872 | isEdit: true,
873 | actionArgs: { insertAt: 'eol' },
874 | context: 'normal'
875 | }),
876 | 'vim:delete-right': h({
877 | keys: 'x',
878 | type: 'operatorMotion',
879 | operator: 'delete',
880 | motion: 'moveByCharacters',
881 | motionArgs: { forward: true },
882 | operatorMotionArgs: { visualLine: false }
883 | }),
884 | 'vim:delete-left': h({
885 | keys: 'X',
886 | type: 'operatorMotion',
887 | operator: 'delete',
888 | motion: 'moveByCharacters',
889 | motionArgs: { forward: false },
890 | operatorMotionArgs: { visualLine: true }
891 | }),
892 | 'vim:substitute': h({
893 | keys: 's',
894 | type: 'keyToKey',
895 | toKeys: 'cl',
896 | context: 'normal'
897 | }),
898 | 'vim:substitute-visual': h({
899 | keys: 's',
900 | type: 'keyToKey',
901 | toKeys: 'c',
902 | context: 'visual'
903 | }),
904 | 'vim:repeat': h({
905 | keys: '.',
906 | type: 'action',
907 | action: 'repeatLastEdit'
908 | }),
909 |
910 | 'vim:increase': h({
911 | keys: '',
912 | type: 'action',
913 | action: 'incrementNumberToken',
914 | isEdit: true,
915 | actionArgs: { increase: true, backtrack: false }
916 | }),
917 | 'vim:decrease': h({
918 | keys: '',
919 | type: 'action',
920 | action: 'incrementNumberToken',
921 | isEdit: true,
922 | actionArgs: { increase: false, backtrack: false }
923 | }),
924 |
925 | 'vim:register-prefix': b({
926 | keys: '"',
927 | type: 'action',
928 | action: 'setRegister'
929 | }),
930 |
931 | // insert mode
932 | 'vim:delete-to-beginning-of-word': h({
933 | keys: '',
934 | type: 'operatorMotion',
935 | operator: 'delete',
936 | motion: 'moveByWords',
937 | motionArgs: { forward: false, wordEnd: false },
938 | context: 'insert'
939 | }),
940 |
941 | // visual mode
942 | 'vim:insert-at-start-of-target': h({
943 | keys: 'I',
944 | type: 'action',
945 | action: 'enterInsertMode',
946 | isEdit: true,
947 | actionArgs: { insertAt: 'startOfSelectedArea' },
948 | context: 'visual'
949 | }),
950 | 'vim:insert-at-end-of-target': h({
951 | keys: 'A',
952 | type: 'action',
953 | action: 'enterInsertMode',
954 | isEdit: true,
955 | actionArgs: { insertAt: 'endOfSelectedArea' },
956 | context: 'visual'
957 | }),
958 | 'vim:reverse-selections': h({
959 | keys: 'o',
960 | type: 'motion',
961 | motion: 'moveToOtherHighlightedEnd',
962 | context: 'visual'
963 | }),
964 | 'vim:reverse-selections-at-same-line': h({
965 | keys: 'O',
966 | type: 'motion',
967 | motion: 'moveToOtherHighlightedEnd',
968 | motionArgs: { sameLine: true },
969 | context: 'visual'
970 | })
971 | }
972 | disposables.add(inkdrop.commands.add(wrapper, handlers))
973 | disposables.add(
974 | inkdrop.commands.add(document.querySelector('.mde-preview'), {
975 | 'vim:move-to-start-of-file': ({ target }) => {
976 | target.scrollTop = 0
977 | },
978 | 'vim:scroll-up': ({ target }) => {
979 | target.scrollTop -= 30
980 | },
981 | 'vim:scroll-down': ({ target }) => {
982 | target.scrollTop += 30
983 | },
984 | 'vim:scroll-half-screen-up': ({ target }) => {
985 | target.scrollTop -= target.clientHeight / 2
986 | },
987 | 'vim:scroll-half-screen-down': ({ target }) => {
988 | target.scrollTop += target.clientHeight / 2
989 | },
990 | 'vim:scroll-full-screen-up': ({ target }) => {
991 | target.scrollTop -= target.clientHeight
992 | },
993 | 'vim:scroll-full-screen-down': ({ target }) => {
994 | target.scrollTop += target.clientHeight
995 | },
996 | 'vim:move-to-line': ({ target }) => {
997 | target.scrollTop = target.scrollHeight
998 | }
999 | })
1000 | )
1001 | wrapper.addEventListener('textInput', this.handleEditorTextInput)
1002 | wrapper.addEventListener('keydown', this.handleEditorKeyDown)
1003 | disposables.add(
1004 | new Disposable(() =>
1005 | wrapper.removeEventListener('keydown', this.handleEditorKeyDown)
1006 | )
1007 | )
1008 |
1009 | this.disposables = disposables
1010 | }
1011 |
1012 | registerExCommands() {
1013 | const el = this.getCodeMirror().getWrapperElement()
1014 | this.vim.defineEx('write', 'w', () => {
1015 | inkdrop.commands.dispatch(el, 'core:save-note')
1016 | })
1017 | this.vim.defineEx('next', 'n', () => {
1018 | inkdrop.commands.dispatch(el, 'core:open-next-note')
1019 | })
1020 | this.vim.defineEx('prev', '', () => {
1021 | inkdrop.commands.dispatch(el, 'core:open-prev-note')
1022 | })
1023 | this.vim.defineEx('preview', 'p', () => {
1024 | inkdrop.commands.dispatch(el, 'view:toggle-preview')
1025 | })
1026 | this.vim.defineEx('side-by-side', 'side', () => {
1027 | inkdrop.commands.dispatch(el, 'view:toggle-side-by-side')
1028 | })
1029 | }
1030 |
1031 | getCodeMirror() {
1032 | return inkdrop.getActiveEditor().cm
1033 | }
1034 |
1035 | yankClipboard() {
1036 | const state = this.vim.getVimGlobalState()
1037 | const text = clipboard.readText()
1038 | const linewise = text.indexOf('\n') >= 0
1039 | state.registerController.pushText('0', 'yank', text, linewise, true)
1040 | }
1041 |
1042 | handleEditorLoad = editor => {
1043 | this.activateMode(editor)
1044 | }
1045 |
1046 | handleVimModeChange = (event, _opt) => {
1047 | logger.debug('vim mode changed:', event)
1048 | const { mode } = event
1049 | const cm = this.getCodeMirror()
1050 | cm.getWrapperElement().classList.remove('insert-mode')
1051 | cm.getWrapperElement().classList.remove('visual-mode')
1052 | cm.getWrapperElement().classList.remove('normal-mode')
1053 | cm.getWrapperElement().classList.remove('replace-mode')
1054 | switch (mode) {
1055 | case 'normal':
1056 | cm.getWrapperElement().classList.add('normal-mode')
1057 | break
1058 | case 'visual':
1059 | cm.getWrapperElement().classList.add('visual-mode')
1060 | break
1061 | case 'replace':
1062 | cm.getWrapperElement().classList.add('replace-mode')
1063 | break
1064 | case 'insert':
1065 | cm.getWrapperElement().classList.add('insert-mode')
1066 | break
1067 | }
1068 | }
1069 |
1070 | handleEditorTextInput = event => {
1071 | // only process if the event is fired via EventTarget.dispatchEvent()
1072 | if (this.isInsertMode() && !event.isTrusted) {
1073 | logger.debug('handle text input:', event)
1074 | const text = event.data
1075 | const cm = this.getCodeMirror()
1076 | cm.replaceSelection(text)
1077 | }
1078 | }
1079 |
1080 | handleEditorKeyDown = event => {
1081 | const keyName = this.normalizeKeyName(event.key)
1082 | const cm = this.getCodeMirror()
1083 | const vim = this.vim.maybeInitVimState(cm)
1084 | const isNumeric =
1085 | !event.ctrlKey &&
1086 | !event.altKey &&
1087 | !event.metaKey &&
1088 | !event.shiftKey &&
1089 | keyName.match(/^\d$/)
1090 |
1091 | const target = cm.getInputField()
1092 | const currentKeyStroke = [
1093 | ...inkdrop.keymaps.queuedKeystrokes.filter(k => !k.startsWith('^')),
1094 | keyName
1095 | ]
1096 | const { partialMatchCandidates, exactMatchCandidates } =
1097 | inkdrop.keymaps.findMatchCandidates(currentKeyStroke)
1098 | const partialMatches = inkdrop.keymaps.findPartialMatches(
1099 | partialMatchCandidates,
1100 | target
1101 | )
1102 | const exactMatches = inkdrop.keymaps.findExactMatches(
1103 | exactMatchCandidates,
1104 | target
1105 | )
1106 | logger.debug('handleEditorKeyDown: currentKeyStroke:', currentKeyStroke)
1107 | logger.debug('handleEditorKeyDown: exactMatches:', exactMatches)
1108 | logger.debug('handleEditorKeyDown: partialMatches:', partialMatches)
1109 |
1110 | if (this.isBufferingKey()) {
1111 | logger.debug('handleEditorKeyDown: handle key buffering:', keyName, event)
1112 | const b = cm
1113 | .getInputField()
1114 | .webkitMatchesSelector(
1115 | '.CodeMirror.vim-mode:not(.insert-mode) textarea'
1116 | )
1117 | logger.debug('handleEditorKeyDown: keybinding check:', exactMatches, b)
1118 |
1119 | if (
1120 | keyName !== 'Ctrl' &&
1121 | keyName !== 'Alt' &&
1122 | keyName !== 'Shift' &&
1123 | keyName !== 'Meta'
1124 | ) {
1125 | const { inputState } = vim
1126 | const hasOperatorOrMotion = inputState.motion || inputState.operator
1127 | if (
1128 | (event.key.length === 1 || keyName === 'space') &&
1129 | (!isNumeric || !hasOperatorOrMotion)
1130 | ) {
1131 | inputState.selectedCharacter = event.key
1132 | inputState.keyBuffer = ''
1133 |
1134 | if (exactMatches.length === 0 && partialMatches.length === 0) {
1135 | const { pendingCommand } = this
1136 | this.stopBufferingKey()
1137 |
1138 | if (typeof pendingCommand === 'function') {
1139 | if (pendingCommand(event)) {
1140 | event.stopPropagation()
1141 | event.preventDefault()
1142 | }
1143 | }
1144 | }
1145 | } else if (isNumeric) {
1146 | vim.inputState.pushRepeatDigit(keyName)
1147 | }
1148 | }
1149 | } else if (!this.isInsertMode()) {
1150 | if (isNumeric) {
1151 | if (exactMatches.length === 0) {
1152 | vim.inputState.pushRepeatDigit(keyName)
1153 | }
1154 | } else {
1155 | // push key buffer to the repeat digit
1156 | const keys = vim.inputState.keyBuffer
1157 | vim.inputState.keyBuffer = ''
1158 | const keysMatcher = /^(\d*)(.*)$/.exec(keys)
1159 | if (keysMatcher[1] && keysMatcher[1] !== '0') {
1160 | vim.inputState.pushRepeatDigit(keysMatcher[1])
1161 | }
1162 | }
1163 | }
1164 | }
1165 |
1166 | handleFocusEditor = _event => {
1167 | this.yankClipboard()
1168 | }
1169 | }
1170 |
1171 | module.exports = new Plugin()
1172 |
--------------------------------------------------------------------------------
/styles/vim.less:
--------------------------------------------------------------------------------
1 | .vim {
2 | }
3 |
--------------------------------------------------------------------------------