├── .gitignore
├── .travis.yml
├── Gemfile
├── Rakefile
├── autoload
└── submode.vim
├── doc
└── submode.txt
└── t
├── current.vim
├── expr.vim
└── keep-leaving-key.vim
/.gitignore:
--------------------------------------------------------------------------------
1 | .vim-flavor
2 | Gemfile.lock
3 | VimFlavor.lock
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | rvm:
3 | - 2.0.0
4 | script: rake ci
5 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'vim-flavor', '~> 1.1'
4 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env rake
2 |
3 | task :ci => [:dump, :test]
4 |
5 | task :dump do
6 | sh 'vim --version'
7 | end
8 |
9 | task :test do
10 | sh 'bundle exec vim-flavor test'
11 | end
12 |
--------------------------------------------------------------------------------
/autoload/submode.vim:
--------------------------------------------------------------------------------
1 | " submode - Create your own submodes
2 | " Version: 0.3.1
3 | " Copyright (C) 2008-2014 kana
4 | " License: MIT license {{{
5 | " Permission is hereby granted, free of charge, to any person obtaining
6 | " a copy of this software and associated documentation files (the
7 | " "Software"), to deal in the Software without restriction, including
8 | " without limitation the rights to use, copy, modify, merge, publish,
9 | " distribute, sublicense, and/or sell copies of the Software, and to
10 | " permit persons to whom the Software is furnished to do so, subject to
11 | " the following conditions:
12 | "
13 | " The above copyright notice and this permission notice shall be included
14 | " in all copies or substantial portions of the Software.
15 | "
16 | " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | " OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | " IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 | " CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 | " TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 | " SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | " }}}
24 | " Concept "{{{1
25 | "
26 | " In the following pseudo code, :MAP means :map or :noremap, and it depends on
27 | " user's specification.
28 | "
29 | " map {key-to-enter}
30 | " \ (submode-before-entering:{submode}:with:{key-to-enter})
31 | " \(submode-before-entering:{submode})
32 | " \(submode-enter:{submode})
33 | "
34 | " MAP (submode-before-entering:{submode}:with:{key-to-enter})
35 | " \ {anything}
36 | " noremap (submode-before-entering:{submode})
37 | " \ {tweaking 'timeout' and others}
38 | " map (submode-enter:{submode})
39 | " \ (submode-before-action:{submode})
40 | " \(submode-prefix:{submode})
41 | "
42 | " map (submode-prefix:{submode})
43 | " \ (submode-leave:{submode})
44 | " map (submode-prefix:{submode}){the first N keys in {lhs}}
45 | " \ (submode-leave:{submode})
46 | " map (submode-prefix:{submode}){lhs}
47 | " \ (submode-rhs:{submode}:for:{lhs})
48 | " \(submode-enter:{submode})
49 | " MAP (submode-rhs:{submode}:for:{lhs})
50 | " \ {rhs}
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | " Variables "{{{1
60 |
61 | if !exists('g:submode_always_show_submode')
62 | let g:submode_always_show_submode = 0
63 | endif
64 |
65 | if !exists('g:submode_keep_leaving_key')
66 | let g:submode_keep_leaving_key = 0
67 | endif
68 |
69 | if !exists('g:submode_keyseqs_to_leave')
70 | let g:submode_keyseqs_to_leave = ['']
71 | endif
72 |
73 | if !exists('g:submode_timeout')
74 | let g:submode_timeout = &timeout
75 | endif
76 |
77 | if !exists('g:submode_timeoutlen')
78 | let g:submode_timeoutlen = &timeoutlen
79 | endif
80 |
81 |
82 |
83 |
84 | "" See s:set_up_options() and s:restore_options().
85 | "
86 | " let s:original_showcmd = &showcmd
87 | " let s:original_showmode = &showmode
88 | " let s:original_timeout = &timeout
89 | " let s:original_timeoutlen = &timeoutlen
90 | " let s:original_ttimeout = &ttimeout
91 | " let s:original_ttimeoutlen = &ttimeoutlen
92 |
93 | if !exists('s:options_overridden_p')
94 | let s:options_overridden_p = 0
95 | endif
96 |
97 | " A padding string to wipe out internal key mappings in 'showcmd' area. (gh-3)
98 | "
99 | " We use no-break spaces (U+00A0) or dots, depending of the current 'encoding'.
100 | " Because
101 | "
102 | " * A normal space (U+0020) is rendered as "<20>" since Vim 7.4.116.
103 | " * U+00A0 is rendered as an invisible glyph if 'encoding' is set to one of
104 | " Unicode encodings. Otherwise "| " is rendered instead.
105 | let s:STEALTH_TYPEAHEAD =
106 | \ &g:encoding =~# '^u'
107 | \ ? repeat("\", 5)
108 | \ : repeat('.', 10)
109 |
110 | let s:current_submode = ''
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | " Interface "{{{1
120 | " :SubmodeRestoreOptions "{{{2
121 |
122 | command! -bar -nargs=0 SubmodeRestoreOptions call submode#restore_options()
123 |
124 |
125 |
126 |
127 | function! submode#current() "{{{2
128 | return s:current_submode
129 | endfunction
130 |
131 |
132 |
133 |
134 | function! submode#enter_with(submode, modes, options, lhs, ...) "{{{2
135 | let rhs = 0 < a:0 ? a:1 : ''
136 | for mode in s:each_char(a:modes)
137 | call s:define_entering_mapping(a:submode, mode, a:options, a:lhs, rhs)
138 | endfor
139 | return
140 | endfunction
141 |
142 |
143 |
144 |
145 | function! submode#leave_with(submode, modes, options, lhs) "{{{2
146 | let options = substitute(a:modes, 'e', '', 'g') " is not expression.
147 | return submode#map(a:submode, a:modes, options . 'x', a:lhs, '')
148 | endfunction
149 |
150 |
151 |
152 |
153 | function! submode#map(submode, modes, options, lhs, rhs) "{{{2
154 | for mode in s:each_char(a:modes)
155 | call s:define_submode_mapping(a:submode, mode, a:options, a:lhs, a:rhs)
156 | endfor
157 | return
158 | endfunction
159 |
160 |
161 |
162 |
163 | function! submode#restore_options() "{{{2
164 | call s:restore_options()
165 | return
166 | endfunction
167 |
168 |
169 |
170 |
171 | function! submode#unmap(submode, modes, options, lhs) "{{{2
172 | for mode in s:each_char(a:modes)
173 | call s:undefine_submode_mapping(a:submode, mode, a:options, a:lhs)
174 | endfor
175 | return
176 | endfunction
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 | " Core "{{{1
186 | function! s:define_entering_mapping(submode, mode, options, lhs, rhs) "{{{2
187 | execute s:map_command(a:mode, 'r')
188 | \ s:map_options(s:filter_flags(a:options, 'bu'))
189 | \ (a:lhs)
190 | \ (s:named_key_before_entering_with(a:submode, a:lhs)
191 | \ . s:named_key_before_entering(a:submode)
192 | \ . s:named_key_enter(a:submode))
193 |
194 | if !s:mapping_exists_p(s:named_key_enter(a:submode), a:mode)
195 | " When the given submode is not defined yet - define the default key
196 | " mappings to leave the submode.
197 | for keyseq in g:submode_keyseqs_to_leave
198 | call submode#leave_with(a:submode, a:mode, a:options, keyseq)
199 | endfor
200 | endif
201 |
202 | execute s:map_command(a:mode, s:filter_flags(a:options, 'r'))
203 | \ s:map_options(s:filter_flags(a:options, 'besu'))
204 | \ s:named_key_before_entering_with(a:submode, a:lhs)
205 | \ a:rhs
206 | execute s:map_command(a:mode, '')
207 | \ s:map_options('e')
208 | \ s:named_key_before_entering(a:submode)
209 | \ printf('on_entering_submode(%s)', string(a:submode))
210 | execute s:map_command(a:mode, 'r')
211 | \ s:map_options('')
212 | \ s:named_key_enter(a:submode)
213 | \ (s:named_key_before_action(a:submode)
214 | \ . s:named_key_prefix(a:submode))
215 |
216 | execute s:map_command(a:mode, '')
217 | \ s:map_options('e')
218 | \ s:named_key_before_action(a:submode)
219 | \ printf('on_executing_action(%s)', string(a:submode))
220 | execute s:map_command(a:mode, 'r')
221 | \ s:map_options('')
222 | \ s:named_key_prefix(a:submode)
223 | \ s:named_key_leave(a:submode)
224 | " NB: :map- cannot be used for s:on_leaving_submode(),
225 | " because it uses some commands not allowed in :map-.
226 | execute s:map_command(a:mode, '')
227 | \ s:map_options('s')
228 | \ s:named_key_leave(a:submode)
229 | \ printf('%son_leaving_submode(%s)',
230 | \ a:mode =~# '[ic]' ? '=' : '@=',
231 | \ string(a:submode))
232 |
233 | return
234 | endfunction
235 |
236 |
237 |
238 |
239 | function! s:define_submode_mapping(submode, mode, options, lhs, rhs) "{{{2
240 | execute s:map_command(a:mode, 'r')
241 | \ s:map_options(s:filter_flags(a:options, 'bu'))
242 | \ (s:named_key_prefix(a:submode) . a:lhs)
243 | \ (s:named_key_rhs(a:submode, a:lhs)
244 | \ . (s:has_flag_p(a:options, 'x')
245 | \ ? s:named_key_leave(a:submode)
246 | \ : s:named_key_enter(a:submode)))
247 | execute s:map_command(a:mode, s:filter_flags(a:options, 'r'))
248 | \ s:map_options(s:filter_flags(a:options, 'besu'))
249 | \ s:named_key_rhs(a:submode, a:lhs)
250 | \ a:rhs
251 |
252 | let keys = s:split_keys(a:lhs)
253 | for n in range(1, len(keys) - 1)
254 | let first_n_keys = join(keys[:-(n+1)], '')
255 | silent! execute s:map_command(a:mode, 'r')
256 | \ s:map_options(s:filter_flags(a:options, 'bu'))
257 | \ (s:named_key_prefix(a:submode) . first_n_keys)
258 | \ s:named_key_leave(a:submode)
259 | endfor
260 |
261 | return
262 | endfunction
263 |
264 |
265 |
266 |
267 | function! s:undefine_submode_mapping(submode, mode, options, lhs) "{{{2
268 | execute s:map_command(a:mode, 'u')
269 | \ s:map_options(s:filter_flags(a:options, 'b'))
270 | \ s:named_key_rhs(a:submode, a:lhs)
271 |
272 | let keys = s:split_keys(a:lhs)
273 | for n in range(len(keys), 1, -1)
274 | let first_n_keys = join(keys[:n-1], '')
275 | execute s:map_command(a:mode, 'u')
276 | \ s:map_options(s:filter_flags(a:options, 'b'))
277 | \ s:named_key_prefix(a:submode) . first_n_keys
278 | if s:longer_mapping_exists_p(s:named_key_prefix(a:submode), first_n_keys)
279 | execute s:map_command(a:mode, 'r')
280 | \ s:map_options(s:filter_flags(a:options, 'b'))
281 | \ s:named_key_prefix(a:submode) . first_n_keys
282 | \ s:named_key_leave(a:submode)
283 | break
284 | endif
285 | endfor
286 |
287 | return
288 | endfunction
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 | " Misc. "{{{1
298 | function! s:each_char(s) "{{{2
299 | return split(a:s, '.\zs')
300 | endfunction
301 |
302 |
303 |
304 |
305 | function! s:filter_flags(s, cs) "{{{2
306 | return join(map(s:each_char(a:cs), 's:has_flag_p(a:s, v:val) ? v:val : ""'),
307 | \ '')
308 | endfunction
309 |
310 |
311 |
312 |
313 | function! s:has_flag_p(s, c) "{{{2
314 | return 0 <= stridx(a:s, a:c)
315 | endfunction
316 |
317 |
318 |
319 |
320 | function! s:insert_mode_p(mode) "{{{2
321 | return a:mode =~# '^[iR]'
322 | endfunction
323 |
324 |
325 |
326 |
327 | function! s:longer_mapping_exists_p(submode, lhs) "{{{2
328 | " FIXME: Implement the proper calculation.
329 | " Note that mapcheck() can't be used for this purpose because it may
330 | " act as s:shorter_mapping_exists_p() if there is such a mapping.
331 | return !0
332 | endfunction
333 |
334 |
335 |
336 |
337 | function! s:map_command(mode, flags) "{{{2
338 | if s:has_flag_p(a:flags, 'u')
339 | return a:mode . 'unmap'
340 | else
341 | return a:mode . (s:has_flag_p(a:flags, 'r') ? 'map' : 'noremap')
342 | endif
343 | endfunction
344 |
345 |
346 |
347 |
348 | function! s:map_options(options) "{{{2
349 | let _ = {
350 | \ 'b': '',
351 | \ 'e': '',
352 | \ 's': '',
353 | \ 'u': '',
354 | \ }
355 | return join(map(s:each_char(a:options), 'get(_, v:val, "")'))
356 | endfunction
357 |
358 |
359 |
360 |
361 | function! s:mapping_exists_p(keyseq, mode) "{{{2
362 | return maparg(a:keyseq, a:mode) != ''
363 | endfunction
364 |
365 |
366 |
367 |
368 | function! s:may_override_showmode_p(mode) "{{{2
369 | " Normal mode / Visual mode (& its variants) / Insert mode (& its variants)
370 | return a:mode =~# "^[nvV\sS\]" || s:insert_mode_p(a:mode)
371 | endfunction
372 |
373 |
374 |
375 |
376 | function! s:named_key_before_action(submode) "{{{2
377 | return printf('(submode-before-action:%s)', a:submode)
378 | endfunction
379 |
380 |
381 |
382 |
383 | function! s:named_key_before_entering(submode) "{{{2
384 | return printf('(submode-before-entering:%s)', a:submode)
385 | endfunction
386 |
387 |
388 |
389 |
390 | function! s:named_key_before_entering_with(submode, lhs) "{{{2
391 | return printf('(submode-before-entering:%s:with:%s)', a:submode, a:lhs)
392 | endfunction
393 |
394 |
395 |
396 |
397 | function! s:named_key_enter(submode) "{{{2
398 | return printf('(submode-enter:%s)', a:submode)
399 | endfunction
400 |
401 |
402 |
403 |
404 | function! s:named_key_leave(submode) "{{{2
405 | return printf('(submode-leave:%s)', a:submode)
406 | endfunction
407 |
408 |
409 |
410 |
411 | function! s:named_key_prefix(submode) "{{{2
412 | return printf('(submode-prefix:%s)%s', a:submode, s:STEALTH_TYPEAHEAD)
413 | endfunction
414 |
415 |
416 |
417 |
418 | function! s:named_key_rhs(submode, lhs) "{{{2
419 | return printf('(submode-rhs:%s:for:%s)', a:submode, a:lhs)
420 | endfunction
421 |
422 |
423 |
424 |
425 | function! s:on_entering_submode(submode) "{{{2
426 | call s:set_up_options(a:submode)
427 | return ''
428 | endfunction
429 |
430 |
431 |
432 |
433 | function! s:on_executing_action(submode) "{{{2
434 | if (s:original_showmode || g:submode_always_show_submode)
435 | \ && s:may_override_showmode_p(mode())
436 | echohl ModeMsg
437 | echo '-- Submode:' a:submode '--'
438 | echohl None
439 | endif
440 | return ''
441 | endfunction
442 |
443 |
444 |
445 |
446 | function! s:on_leaving_submode(submode) "{{{2
447 | if (s:original_showmode || g:submode_always_show_submode)
448 | \ && s:may_override_showmode_p(mode())
449 | if s:insert_mode_p(mode())
450 | let cursor_position = getpos('.')
451 | endif
452 |
453 | " BUGS: :redraw! doesn't redraw 'showmode'.
454 | execute "normal! \"
455 |
456 | if s:insert_mode_p(mode())
457 | call setpos('.', cursor_position)
458 | endif
459 | endif
460 | if !g:submode_keep_leaving_key && getchar(1) isnot 0
461 | " To completely ignore unbound key sequences in a submode,
462 | " here we have to fetch and drop the last key in the key sequence.
463 | call getchar()
464 | endif
465 | call s:restore_options()
466 | return ''
467 | endfunction
468 |
469 |
470 |
471 |
472 | function! s:remove_flag(s, c) "{{{2
473 | " Assumption: a:c is not a meta character.
474 | return substitute(a:s, a:c, '', 'g')
475 | endfunction
476 |
477 |
478 |
479 |
480 | function! s:restore_options() "{{{2
481 | if !s:options_overridden_p
482 | return
483 | endif
484 | let s:options_overridden_p = 0
485 |
486 | let &showcmd = s:original_showcmd
487 | let &showmode = s:original_showmode
488 | let &timeout = s:original_timeout
489 | let &timeoutlen = s:original_timeoutlen
490 | let &ttimeout = s:original_ttimeout
491 | let &ttimeoutlen = s:original_ttimeoutlen
492 |
493 | let s:current_submode = ''
494 |
495 | return
496 | endfunction
497 |
498 |
499 |
500 |
501 | function! s:set_up_options(submode) "{{{2
502 | if s:options_overridden_p
503 | return
504 | endif
505 | let s:options_overridden_p = !0
506 |
507 | let s:original_showcmd = &showcmd
508 | let s:original_showmode = &showmode
509 | let s:original_timeout = &timeout
510 | let s:original_timeoutlen = &timeoutlen
511 | let s:original_ttimeout = &ttimeout
512 | let s:original_ttimeoutlen = &ttimeoutlen
513 |
514 | " NB: 'showcmd' must be enabled to render the cursor properly.
515 | " If 'showcmd' is disabled and the current submode message is rendered, the
516 | " cursor is rendered at the end of the message, not the actual position in
517 | " the current window. (gh-9)
518 | set showcmd
519 | set noshowmode
520 | let &timeout = g:submode_timeout
521 | let &ttimeout = s:original_timeout ? !0 : s:original_ttimeout
522 | let &timeoutlen = g:submode_timeoutlen
523 | let &ttimeoutlen = s:original_ttimeoutlen < 0
524 | \ ? s:original_timeoutlen
525 | \ : s:original_ttimeoutlen
526 |
527 | let s:current_submode = a:submode
528 |
529 | return
530 | endfunction
531 |
532 |
533 |
534 |
535 | function! s:split_keys(keyseq) "{{{2
536 | " Assumption: Special keys such as are escaped with < and >, i.e.,
537 | " a:keyseq doesn't directly contain any escape sequences.
538 | return split(a:keyseq, '\(<[^<>]\+>\|.\)\zs')
539 | endfunction
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 | " __END__ "{{{1
549 | " vim: foldmethod=marker
550 |
--------------------------------------------------------------------------------
/doc/submode.txt:
--------------------------------------------------------------------------------
1 | *submode.txt* Create your own submodes
2 |
3 | Version 0.3.1
4 | Script ID: 2467
5 | Copyright (C) 2008-2014 kana
6 | License: MIT license {{{
7 | Permission is hereby granted, free of charge, to any person obtaining
8 | a copy of this software and associated documentation files (the
9 | "Software"), to deal in the Software without restriction, including
10 | without limitation the rights to use, copy, modify, merge, publish,
11 | distribute, sublicense, and/or sell copies of the Software, and to
12 | permit persons to whom the Software is furnished to do so, subject to
13 | the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included
16 | in all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 | }}}
26 |
27 | CONTENTS *submode-contents*
28 |
29 | Introduction |submode-introduction|
30 | Interface |submode-interface|
31 | Functions |submode-functions|
32 | Variables |submode-variables|
33 | Bugs |submode-bugs|
34 | Changelog |submode-changelog|
35 |
36 |
37 |
38 |
39 | ==============================================================================
40 | INTRODUCTION *submode-introduction*
41 |
42 | *submode* is a Vim plugin to provide the way to define "submodes" to the
43 | built-in |vim-modes|. For example, whenever you type |g-| and/or |g+| to
44 | undo/redo many times, don't you want to type "g++--++..." instead
45 | "g+g+g-g-g+g+..."? With this plugin, you can define such interface with the
46 | following settings:
47 | >
48 | call submode#enter_with('undo/redo', 'n', '', 'g-', 'g-')
49 | call submode#enter_with('undo/redo', 'n', '', 'g+', 'g+')
50 | call submode#leave_with('undo/redo', 'n', '', '')
51 | call submode#map('undo/redo', 'n', '', '-', 'g-')
52 | call submode#map('undo/redo', 'n', '', '+', 'g+')
53 | <
54 | The above settings mean:
55 | - Define a new submode named "undo/redo".
56 | - Define "g-" and "g+" as key sequences to enter the submode "undo/redo" from
57 | Normal mode. Additionally, they does undo/redo before entering the submode
58 | "undo/redo".
59 | - In the submode "undo/redo", "-" and "+" do undo/redo.
60 | - In the submode "undo/redo", "" leaves the submode.
61 |
62 | *submode-leaving*
63 | By default, is automatically defined as a key to leave any submode.
64 | So you don't have to explicitly define like the above example.
65 | There are also 2 ways to leave submodes:
66 | - Type any key sequence which is not mapped in the submode.
67 | See also |g:submode_keep_leaving_key|.
68 | - Don't type any key for a long time.
69 | See |submode-variables| to configure the details of this time out.
70 |
71 |
72 | Requirements:
73 | - Vim 7.2 or later
74 |
75 | Latest version:
76 | https://github.com/kana/vim-submode
77 |
78 | Document in HTML format:
79 | http://vim-doc.heroku.com/view?https://raw.github.com/kana/vim-submode/master/doc/submode.txt
80 |
81 |
82 |
83 |
84 | ==============================================================================
85 | INTERFACE *submode-interface*
86 |
87 | ------------------------------------------------------------------------------
88 | COMMANDS *submode-commands*
89 |
90 | :SubmodeRestoreOptions *:SubmodeRestoreOptions*
91 | Ex command version of |submode#restore_options()|.
92 |
93 |
94 |
95 |
96 | ------------------------------------------------------------------------------
97 | FUNCTIONS *submode-functions*
98 |
99 | *submode#current()*
100 | submode#current()
101 | Return the name of the current submode. If any
102 | submode is not currently active, return an empty
103 | string instead.
104 |
105 | *submode#enter_with()*
106 | submode#enter_with({submode}, {modes}, {options}, {lhs}, [{rhs}])
107 | Define a key mapping to enter the {submode} from
108 | {modes}. If {rhs} is given, it will be executed
109 | whenever entering the {submode} by {lhs}.
110 |
111 | See |submode#map()| for the details of arguments.
112 |
113 | *submode#leave_with()*
114 | submode#leave_with({submode}, {modes}, {options}, {lhs})
115 | Define a key mapping ({lhs}) to leave the {submode} in
116 | {modes}.
117 |
118 | See |submode#map()| for the details of arguments.
119 |
120 | *submode#map()*
121 | submode#map({submode}, {modes}, {options}, {lhs}, {rhs})
122 | Define a key mapping ({lhs} to {rhs}) in the {submode}
123 | in {modes}.
124 |
125 | {submode} String
126 | The name of the submode. It is recommended to
127 | use only the following characters:
128 |
129 | Alphabets A-Z, a-z
130 | Digits 0-9
131 | Some symbols -, _, /
132 |
133 | Note that the submode name is used as parts of
134 | internal key mappings. Use a short name.
135 |
136 | {modes} String
137 | A sequence of letters which specifies the
138 | modes to define a key mapping. The meanings
139 | of letters are as follows:
140 |
141 | c Command-line mode
142 | i Insert mode
143 | n Normal mode
144 | s Select mode only
145 | v Visual mode and Select mode
146 | x Visual mode only
147 |
148 | Note that Operator-pending mode and
149 | |language-mapping| are not supported, because
150 | the both modes are always leaved by 1 key
151 | sequence, so that submdoes can't be built on
152 | the both modes.
153 |
154 | {options} String
155 | A sequence of letters which specifies some
156 | options for a key mapping to be defined. The
157 | meanings of letters are as follows:
158 |
159 | b Same as |:map-|.
160 | e Same as |:map-|.
161 | r {rhs} may be remapped.
162 | If this letter is not included,
163 | {rhs} will be never remapped.
164 | s Same as |:map-|.
165 | u Same as |:map-|.
166 | x After executing {rhs}, leave the
167 | submode. This matters only for
168 | |submode#map()|.
169 |
170 | {lhs} String
171 | A key sequence to type.
172 |
173 | To denote a special key such as , write
174 | it in <>-escaped form instead of the character
175 | as is. For example, use '' instead of
176 | "\".
177 |
178 | {rhs} String
179 | A key sequence to be executed by typing {lhs}.
180 |
181 | See also {lhs} for other notes.
182 |
183 | submode#restore_options() *submode#restore_options()*
184 | Restore options overriden by this plugin.
185 |
186 | This plugin overrides some options before entering
187 | a submode and restores the options after leaving
188 | a submode. can be used to leave a submode, but
189 | it disturbs to restore the options. Call this
190 | function if you do so.
191 |
192 | *submode#unmap()*
193 | submode#unmap({submode}, {modes}, {options}, {lhs})
194 | Delete a key mapping ({lhs} to something) in the
195 | {submode} in {modes}.
196 |
197 | See |submode#map()| for the details of arguments.
198 | Note that only "b" matters for {options} and other
199 | letters are just ignored.
200 |
201 | ------------------------------------------------------------------------------
202 | VARIABLES *submode-variables*
203 |
204 | *g:submode_always_show_submode*
205 | g:submode_always_show_submode boolean (default: false)
206 | Show always the current submode, even if 'showmode' is disabled.
207 | Use this option if you use vim-airline or vim-powerline.
208 |
209 | 'showmode' g:submode_always_show_submode the current submode ~
210 | off off not shown
211 | on off shown
212 | off on shown
213 | on on shown
214 |
215 | *g:submode_keep_leaving_key*
216 | g:submode_keep_leaving_key boolean (default: false)
217 | Whenever you type any key which is not mapped in the current submode,
218 | it causes to leave from the submode. In this case, the key is
219 | consumed by default. If this variable is set to true, the key is not
220 | consumed and will be processed by Vim.
221 |
222 | For example, when you type an unmapped key "X" to leave from the
223 | current submode of Normal mode, the "X" will be consumed by default.
224 | If this variable is set to true, the "X" will be processed by Vim, so
225 | that a characer before the cursor will be deleted unless you map |X|
226 | to something.
227 |
228 | *g:submode_keyseqs_to_leave*
229 | g:submode_keyseqs_to_leave list of strings (default: [''])
230 | The default key sequences to leave a submode.
231 |
232 | *g:submode_timeout*
233 | g:submode_timeout boolean (default: same as 'timeout')
234 | If this value is true, time out on submodes is enabled. Otherwise,
235 | time out is disabled. If time out is enabled, not typing any key in
236 | a submode for a long time causes to leave the submode.
237 |
238 | If this variable is not defined, the value of 'timeout' is used
239 | instead.
240 |
241 | *g:submode_timeoutlen*
242 | g:submode_timeoutlen number (default: same as 'timeoutlen')
243 | The time in milliseconds that is waited for typing keys in a submode.
244 |
245 | If this variable is not defined, the value of 'timeoutlen' is used
246 | instead.
247 |
248 |
249 |
250 |
251 | ==============================================================================
252 | BUGS *submode-bugs*
253 |
254 | LIMITATIONS ~
255 |
256 | - The maximum length of {lhs} of normal key mappings is 50. Since submode key
257 | mappings are built on top of normal key mappings, the maximum length of
258 | a submode {lhs} is shorter than 50. Usually 10 or more characters are
259 | available, depending on a submode name. And it is enough length because you
260 | don't want to type 4 or more keys to execute a command.
261 |
262 | - In {rhs} of a key mapping for a submode, cannot be used. Because key
263 | mappings for a submode is defined by this plugin, not callers.
264 |
265 | - To behave the same as Normal mode and Visual mode, any unbound key sequence
266 | should be ignored in a submode, but it's impossible to implement.
267 |
268 | - 'showcmd' is always turned on a submode to render the cursor properly.
269 |
270 | - If 'showcmd' is turned on and 'encoding' is set to a non-Unicode encoding,
271 | ".........." is showed at the bottom right corner while a submode is active.
272 | This is to hide a part of internal key mappings for submode key mappings.
273 |
274 |
275 | PROBLEMS ~
276 |
277 | - [count] is not supported in a submode.
278 |
279 | - |submode#unmap()| does not actually unmap key mappings. It just replaces
280 | rhs with , but it may cause some problems.
281 |
282 | - The current API to define submode key mappings is somewhat low-level.
283 | It might be useful to add |:map|-like commands for readability.
284 |
285 |
286 |
287 |
288 | ==============================================================================
289 | CHANGELOG *submode-changelog*
290 |
291 | 0.3.1 2014-02-16T18:59:21+09:00 *submode-changelog-0.3.1*
292 | - Fix to hide unintended messages which were shown in the command line
293 | whenever users leave from a submode.
294 |
295 | 0.3.0 2014-02-15T21:15:46+09:00 *submode-changelog-0.3.0*
296 | - Add |submode#current()|.
297 | - Tidy up the document a bit.
298 |
299 | 0.2.0 2014-02-05T23:56:14+09:00 *submode-changelog-0.2.0*
300 | - Add |g:submode_always_show_submode| for users preferring
301 | 'statusline' such as vim-airline and vim-powerline.
302 | - Fix a rendering problem on the cursor. The problem was happened if
303 | 'showcmd' is off and 'showmode' is on.
304 | - Fix not to show internal key mappings in 'showcmd' area.
305 | - Add a note about a limitation of {lhs} length. See |submode-bugs|.
306 |
307 | 0.1.0 2013-03-16T16:34:49+09:00 *submode-changelog-0.1.0*
308 | - Allow to keep a key to leave from the current mode.
309 | See also |g:submode_keep_leaving_key| for the details.
310 | - Improve the document a bit.
311 |
312 | 0.0.1 2012-03-24T14:32:30+09:00 *submode-changelog-0.0.1*
313 | - Refine the document a bit.
314 | - Refine the internal structure a bit.
315 |
316 | 0.0.0 2008-11-27T01:58:43+09:00 *submode-changelog-0.0.0*
317 | - Initial version.
318 |
319 |
320 |
321 |
322 | ==============================================================================
323 | vim:tw=78:ts=8:ft=help:norl:fen:fdl=0:fdm=marker:
324 |
--------------------------------------------------------------------------------
/t/current.vim:
--------------------------------------------------------------------------------
1 | call submode#enter_with('foo', 'n', '', 'sa')
2 | call submode#enter_with('bar', 'n', '', 'sb')
3 | call submode#enter_with('baz', 'n', '', 'sc')
4 | call submode#map('foo', 'n', 'e', 'm', 'Stash()')
5 | call submode#map('bar', 'n', 'e', 'm', 'Stash()')
6 | call submode#map('baz', 'n', 'e', 'm', 'Stash()')
7 |
8 | let g:submode = ''
9 | function! Stash()
10 | let g:submode = submode#current()
11 | return ''
12 | endfunction
13 |
14 | describe 'submode#current'
15 | it 'returns an empty string if any submode is not active'
16 | Expect submode#current() ==# ''
17 | end
18 |
19 | it 'returns the name of the current submode'
20 | execute 'normal' "sa\"
21 | Expect g:submode ==# ''
22 |
23 | execute 'normal' "sam\"
24 | Expect g:submode ==# 'foo'
25 |
26 | execute 'normal' "sbm\"
27 | Expect g:submode ==# 'bar'
28 |
29 | execute 'normal' "scm\"
30 | Expect g:submode ==# 'baz'
31 |
32 | Expect submode#current() ==# ''
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/t/expr.vim:
--------------------------------------------------------------------------------
1 | function! Flip()
2 | let g:flipped = !g:flipped
3 | return g:flipped
4 | endfunction
5 | let g:flipped = 0
6 |
7 | call submode#enter_with('expr', 'n', 'e', 'j', 'Flip() ? "k" : "j"')
8 |
9 | describe ' mapping in a submode'
10 | before
11 | new
12 | put =range(1, 30)
13 | 1 delete _
14 | end
15 |
16 | after
17 | quit!
18 | end
19 |
20 | it 'works'
21 | normal! 10G
22 | Expect line('.') == 10
23 |
24 | normal j
25 | Expect line('.') == 9
26 |
27 | normal j
28 | Expect line('.') == 10
29 |
30 | normal j
31 | Expect line('.') == 9
32 |
33 | normal j
34 | Expect line('.') == 10
35 | end
36 |
37 | it 'is not applied to the default key mapping to leave a submode'
38 | normal! 10G
39 |
40 | let v:errmsg = ''
41 | execute 'normal' "j\"
42 | Expect v:errmsg ==# ''
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/t/keep-leaving-key.vim:
--------------------------------------------------------------------------------
1 | call submode#enter_with('boost', 'n', '', 'j', 'j')
2 | call submode#enter_with('boost', 'n', '', 'k', 'k')
3 | call submode#map('boost', 'n', '', 'j', 'jjj')
4 | call submode#map('boost', 'n', '', 'k', 'kkk')
5 |
6 | describe 'g:submode_keep_leaving_key'
7 | before
8 | new
9 | put =range(1, 30)
10 | 1 delete _
11 | end
12 |
13 | after
14 | quit!
15 | end
16 |
17 | it 'does not keep a leaving key by default'
18 | Expect line('.') == 1
19 |
20 | normal ggj
21 | Expect line('.') == 2
22 |
23 | normal ggjj
24 | Expect line('.') == 5
25 |
26 | normal ggjjj
27 | Expect line('.') == 8
28 |
29 | normal ggjjjx
30 | Expect line('.') == 8
31 | Expect getline('.') ==# '8'
32 | end
33 |
34 | it 'does not keep a leaving key if g:submode_keep_leaving_key is false'
35 | let g:submode_keep_leaving_key = 0
36 |
37 | Expect line('.') == 1
38 |
39 | normal ggj
40 | Expect line('.') == 2
41 |
42 | normal ggjj
43 | Expect line('.') == 5
44 |
45 | normal ggjjj
46 | Expect line('.') == 8
47 |
48 | normal ggjjjx
49 | Expect line('.') == 8
50 | Expect getline('.') ==# '8'
51 | end
52 |
53 | it 'keeps a leaving key if g:submode_keep_leaving_key is true'
54 | let g:submode_keep_leaving_key = 1
55 |
56 | Expect line('.') == 1
57 |
58 | normal ggj
59 | Expect line('.') == 2
60 |
61 | normal ggjj
62 | Expect line('.') == 5
63 |
64 | normal ggjjj
65 | Expect line('.') == 8
66 |
67 | normal ggjjjx
68 | Expect line('.') == 8
69 | Expect getline('.') ==# ''
70 | end
71 | end
72 |
--------------------------------------------------------------------------------