├── README.md ├── autoload └── showmap.vim ├── doc └── showmap.txt ├── img ├── vim-showmap.png └── vim-showmap_thumb.png └── plugin └── showmap.vim /README.md: -------------------------------------------------------------------------------- 1 | Vim-showmap 2 | ============ 3 | Showmap helps you type multi-char mappings. 4 | 5 | For instance, in Tpope's _unimpaired_ plugin, you can toggle some Vim options 6 | with the `co` maps Eg. `col` toggles the 'list' option. Say you quickly want 7 | to toggle 'cursorcolumn': you start typing `co`, and then... damn, what's the 8 | letter again for 'cursorcolumn'? 'c'? Nah, that's 'cursorline'. Shoot, the 9 | mapping timed out... 10 | 11 | Showmap automatically binds a helper mapping on common prefixes, like `co`, 12 | and when you stall at that point, a list of available keys is shown; the 13 | helper can wait as long as you want for you to complete it, or you can get 14 | more details about individual mappings. 15 | 16 | Screenshots 17 | ------------ 18 | Stalling on `t`, my prefix for setting/toggling some mode/options: 19 | 20 | [![](img/vim-showmap_thumb.png)](img/vim-showmap.png) 21 | 22 | (Taken on minTTY with Office Code Pro font and [Fahrenheit color theme](https://github.com/fcpg/vim-fahrenheit)) 23 | 24 | Installation 25 | ------------- 26 | Use your favorite method: 27 | * [Pathogen][1] - git clone https://github.com/fcpg/vim-showmap ~/.vim/bundle/vim-showmap 28 | * [NeoBundle][2] - NeoBundle 'fcpg/vim-showmap' 29 | * [Vundle][3] - Plugin 'fcpg/vim-showmap' 30 | * manual - copy all of the files into your ~/.vim directory 31 | 32 | Help 33 | ----- 34 | Run :helptags (or :Helptags with Pathogen), then :help showmap 35 | 36 | License 37 | -------- 38 | [Attribution-ShareAlike 4.0 Int.](https://creativecommons.org/licenses/by-sa/4.0/) 39 | 40 | [1]: https://github.com/tpope/vim-pathogen 41 | [2]: https://github.com/Shougo/neobundle.vim 42 | [3]: https://github.com/gmarik/vundle 43 | -------------------------------------------------------------------------------- /autoload/showmap.vim: -------------------------------------------------------------------------------- 1 | " showmap.vim - help for multiple-key mapping sequences 2 | " Author: fcpg 3 | " Version: 1.0 4 | 5 | 6 | "----------------------- 7 | " Public functions {{{1 8 | "----------------------- 9 | 10 | " showmap#helper {{{2 11 | " Code to run on timeout 12 | " 1st arg is a sequence of printable key names 13 | " 2nd optional arg is a letter = mode (n,v,o,x,i,c) 14 | function! showmap#helper(seq, mode) 15 | call s:log2file(printf("helper(): [%s] [%s]", a:seq, a:mode)) 16 | if a:mode != 'n' 17 | let save_smd = &smd 18 | let &smd = 0 19 | endif 20 | " let not_mapped = 0 21 | let seq = a:seq 22 | let wait = 1 23 | let prompt_type = get(g:, 'showmap_auto_whatis_all', 0) ? 'l' : 's' 24 | while wait 25 | redraw 26 | call s:prompt(seq, a:mode, prompt_type) 27 | let [rc, c, raw] = s:getcharstr() 28 | redraw 29 | if rc == s:key_quit 30 | " quit 31 | break 32 | elseif rc == s:key_help 33 | " help 34 | let do_quit = s:whatis(seq, a:mode) 35 | if do_quit | break | else | continue | endif 36 | elseif rc == s:key_help_all 37 | " list all 38 | let prompt_type = prompt_type == 'l' ? 's' : 'l' 39 | continue 40 | elseif rc == s:key_multi 41 | call s:resume_map(seq) 42 | break 43 | endif 44 | if c != '' 45 | if maparg(seq . c, a:mode) != '' 46 | " send the keys 47 | let rawseq = s:str2raw(seq) 48 | let feedstr = rawseq . (raw ? rc : c) 49 | redraw 50 | call feedkeys(feedstr, 't') 51 | else 52 | let comps = s:list_completions(seq.c, a:mode) 53 | if !empty(comps) 54 | " prefix only - add char and loop 55 | let seq .= c 56 | continue 57 | elseif !exists('g:showmap_map_check') 58 | \ || exists('g:showmap_no_map_check["'.a:mode.'"]["'.seq.'"]') 59 | " send the keys, with noremap 60 | let rawseq = s:str2raw(seq) 61 | let feedstr = rawseq . (raw ? rc : c) 62 | redraw 63 | call feedkeys(feedstr, 'nt') 64 | else 65 | call s:error("Not mapped.") 66 | continue 67 | endif 68 | endif 69 | endif 70 | let wait = 0 71 | endwhile 72 | if a:mode != 'n' 73 | let &smd = save_smd 74 | endif 75 | if exists('t:showmap_cmdheight') 76 | let &cmdheight = t:showmap_cmdheight 77 | unlet t:showmap_cmdheight 78 | endif 79 | "if not_mapped 80 | " echo "Not mapped." | redraw 81 | "endif 82 | if a:mode == 'i' 83 | return '' 84 | endif 85 | endfun 86 | 87 | 88 | " showmap#bind_helper {{{2 89 | " Create mapping on given key sequence 90 | " 1st arg is a sequence of printable key names 91 | " 2nd optional arg is a string with letters = mode (default to 'n') 92 | function! showmap#bind_helper(seq, ...) 93 | let modes = (a:0 ? a:1 : 'n') 94 | for mode in split(modes, '\zs') 95 | if index(s:accepted_modes, mode) == -1 96 | echoerr "Error: invalid map mode <".mode.">" 97 | continue 98 | endif 99 | let seq = substitute(a:seq, '\c', s:raw2str(s:mapleader()), '') 100 | let esc_seq = escape(substitute(seq, '<', '', 'g'), '\"') 101 | let exestr = mode."map ".a:seq." showmap#helper(". 102 | \ '"'.esc_seq.'",'. 103 | \ '"'.mode.'"'. 104 | \ ")" 105 | call s:log2file("bind_helper(): exestr: ".exestr) 106 | exe exestr 107 | endfor 108 | endfun 109 | 110 | 111 | " showmap#autobind {{{2 112 | " Automatically create mapping on existing mappings 113 | function! showmap#autobind(modes) 114 | call s:log2file(printf("autobind(): [%s]", a:modes)) 115 | for mode in split(a:modes, '\zs') 116 | if index(s:accepted_modes, mode) == -1 117 | echoerr "Error: invalid map mode <".mode.">" 118 | continue 119 | endif 120 | redir => rawlist 121 | silent exec mode.'map' 122 | redir END 123 | let rawlines = split(rawlist, "\n") 124 | let binds = {} 125 | for line in rawlines 126 | " discard mode indicators 127 | let without_modes = strpart(line, 3) 128 | if strpart(without_modes,0,6) ==? '' 129 | \ || strpart(without_modes,0,5) ==? '' 130 | " ignore mappings not meant to be typed 131 | continue 132 | endif 133 | let spc_pos = stridx(without_modes, ' ') 134 | let lhs = (spc_pos != -1) 135 | \ ? strpart(without_modes, 0, spc_pos) 136 | \ : without_modes 137 | let lhs_tokenize = lhs 138 | let lhs_tokens = [] 139 | while lhs_tokenize != '' 140 | if lhs_tokenize[0] == '<' 141 | " check special char name 142 | let str_pos = matchstrpos(lhs_tokenize, '^'.s:char_pattern) 143 | if str_pos[1] != -1 144 | " found a special char name 145 | call add(lhs_tokens, str_pos[0]) 146 | let lhs_tokenize = strpart(lhs_tokenize, str_pos[2]) 147 | else 148 | " no special char name, the '<' was just the '<' char 149 | call add(lhs_tokens, strcharpart(lhs_tokenize, 0, 1)) 150 | let lhs_tokenize = strcharpart(lhs_tokenize, 1) 151 | endif 152 | else 153 | " add the single char to tokens and keep tokenizing 154 | call add(lhs_tokens, strcharpart(lhs_tokenize, 0, 1)) 155 | let lhs_tokenize = strcharpart(lhs_tokenize, 1) 156 | endif 157 | endwhile 158 | let lhs_len = len(lhs_tokens) 159 | call s:log2file(printf(" count: [%d] %20s %s\n", 160 | \ lhs_len,lhs,string(lhs_tokens))) 161 | if lhs_len >= s:autobind_minlen 162 | let lhs_prefix = join(lhs_tokens[0:s:autobind_minlen-2], '') 163 | if !has_key(binds, lhs_prefix) 164 | " don't overwrite map if one exists 165 | if maparg(lhs_prefix, mode) == '' 166 | if !exists('g:showmap_autobind_exceptions["'.mode.'"]["'.lhs_prefix.'"]') 167 | if (!exists('s:autobind_default_exceptions["'.mode.'"]["'.lhs_prefix.'"]') 168 | \ || exists('g:showmap_no_autobind_default_exceptions')) 169 | " the binding is created here 170 | call showmap#bind_helper(lhs_prefix, mode) 171 | call s:log2file("showmap#bind_helper(".lhs_prefix.','.mode.')') 172 | else 173 | call s:log2file(' autobind_default_exceptions["'.mode.'"]["'.lhs_prefix.'"]') 174 | endif 175 | else 176 | call s:log2file(' autobind_exceptions["'.mode.'"]["'.lhs_prefix.'"]') 177 | endif 178 | endif 179 | let binds[lhs_prefix] = 1 180 | endif 181 | endif 182 | endfor 183 | call s:log2file(" end of rawlines loop") 184 | endfor 185 | endfun 186 | 187 | 188 | "------------------------ 189 | " Private functions {{{1 190 | "------------------------ 191 | 192 | " s:mapleader {{{2 193 | " Normalizes the g:mapleader (and handles the case where it doesn't exist)" 194 | function! s:mapleader() 195 | let l:mapleader = "\\" 196 | if exists("g:mapleader") 197 | let l:mapleader = g:mapleader 198 | endif 199 | return l:mapleader 200 | endfun 201 | 202 | " s:resume_map {{{2 203 | " Wait for a key, quit helper and resume normal typing 204 | function! s:resume_map(seq) 205 | call s:log2file(printf("resuume_map(): [%s]", a:seq)) 206 | " put back sequence in the feed and resume 207 | let rawseq = s:str2raw(a:seq) 208 | " Wait for next char (to avoid timeouts) 209 | let [rc, c, raw] = s:getcharstr() 210 | " Discard 'Press Return' prompt if any 211 | redraw 212 | let feedstr = rawseq . (raw ? rc : c) 213 | "call s:log2file(" before feedkeys(".string(feedstr).", 't')") 214 | call feedkeys(feedstr, 't') 215 | "call s:log2file(" after feedkeys(".string(feedstr).", 't')") 216 | echo '' | redraw 217 | endfun 218 | 219 | 220 | " s:whatis {{{2 221 | " Read a char and show mapping of seq+char 222 | function! s:whatis(seq, mode) 223 | let [rc, c, raw] = s:getcharstr() 224 | if rc == s:key_multi 225 | let c = input("Keys to lookup> ") 226 | endif 227 | let map_info = maparg(a:seq.c, a:mode, 0, 1) 228 | echo '' | redraw 229 | if empty(map_info) 230 | call s:error("Key(s) not mapped.") 231 | return 232 | endif 233 | let lhs = map_info['lhs'] 234 | let rhs = map_info['rhs'] 235 | call s:print_map(a:seq, lhs, rhs) 236 | redraw 237 | if exists('g:showmap_whatis_timeout') 238 | exe 'sleep' g:showmap_whatis_timeout 239 | else 240 | let [rc, c, raw] = s:getcharstr() 241 | if rc == s:key_whatis_exec 242 | call s:log2file(" whatis_exec: ".lhs) 243 | let feedstr = s:str2raw(lhs) 244 | echo '' | redraw 245 | call feedkeys(feedstr, 't') 246 | return 1 247 | endif 248 | endif 249 | endfun 250 | 251 | 252 | " s:whatis_all {{{2 253 | " Show all mappings [lhs+rhs] of seq 254 | " Return 0 = continue, 1 = quit helper (after cleanup) 255 | function! s:whatis_all(seq, mode) 256 | let list_comp = s:list_completions(a:seq, a:mode) 257 | for compl in list_comp 258 | let map_info = maparg(a:seq.compl, a:mode, 0, 1) 259 | let lhs = map_info['lhs'] 260 | let rhs = map_info['rhs'] 261 | call s:print_map(a:seq, lhs, rhs) 262 | echon "\n" 263 | endfor 264 | endfun 265 | 266 | 267 | " s:print_map {{{2 268 | " Pretty-print a mapping 269 | function! s:print_map(seq, lhs, rhs) 270 | let lhs = a:lhs 271 | let rhs = a:rhs 272 | let lhslen = strchars(lhs) 273 | let rhslen = strchars(rhs) 274 | let caplen = lhslen + strchars(s:map_caption_sep) + rhslen 275 | let maxlen = s:cmd_chars_left(a:seq) 276 | let difflen = maxlen - caplen 277 | if difflen < 0 278 | " truncate rhs 279 | let rhs = strcharpart(rhs, 0, rhslen + difflen - 6) . ' ...' 280 | endif 281 | let lhs_comp = strcharpart(lhs, strchars(a:seq)) 282 | echon " " 283 | echohl ShowmapLHSPrefix | echon a:seq | echohl None 284 | echohl ShowmapLHSComp | echon lhs_comp | echohl None 285 | echon s:map_caption_sep 286 | echohl ShowmapRHS | echon rhs | echohl None 287 | endfun 288 | 289 | 290 | " s:getcharstr {{{2 291 | " Get char+name from user input 292 | " Return array [raw_char, char_name, is_raw?] 293 | function! s:getcharstr() 294 | let raw = 0 295 | let [rc, c] = s:getrealchar() 296 | if c == '' 297 | let c = s:raw2str(rc) 298 | let raw = 1 299 | endif 300 | return [rc, c, raw] 301 | endfun 302 | 303 | 304 | " s:getrealchar {{{2 305 | " Get a char from user input (CursorHold ignored) 306 | " Return array [raw_char, char_name] 307 | function! s:getrealchar() 308 | let wait = 1 309 | while wait 310 | let rc = getchar() 311 | let c = nr2char(rc) 312 | let raw = 0 313 | if c == '' 314 | if rc == "\" 315 | " keep waiting 316 | continue 317 | endif 318 | endif 319 | let wait = 0 320 | endwhile 321 | return [rc, c] 322 | endfun 323 | 324 | 325 | " s:prompt {{{2 326 | " Show prompt 327 | " 1st arg is a sequence of printable key names 328 | " 2nd arg is a letter = mode (n,v,o,x,i,c) 329 | " 3rd arg is the prompt type (s,l) = short or long 330 | function! s:prompt(seq, mode, type) 331 | call s:log2file(printf("prompt(): [%s] [%s] [%s]", a:seq, a:mode, a:type)) 332 | if exists('g:showmap_captions["'.a:mode.'"]["'.a:seq.'"]') 333 | let caption = g:showmap_captions[a:mode][a:seq] 334 | else 335 | if a:type == 'l' 336 | call s:whatis_all(a:seq, a:mode) 337 | else 338 | call s:short_list(a:seq, a:mode) 339 | endif 340 | endif 341 | endfun 342 | 343 | 344 | " s:short_list {{{2 345 | " Show all completions in a single line 346 | " 1st arg is a sequence of printable key names 347 | " 2nd optional arg is a letter = mode (n,v,o,x,i,c) 348 | function! s:short_list(seq, mode) 349 | call s:log2file(printf("short_list(): [%s] [%s]", a:seq, a:mode)) 350 | let lines = s:list_completions(a:seq, a:mode) 351 | let caption = join(lines, s:list_separator) 352 | let caplen = strchars(caption) 353 | let maxlen = s:cmd_chars_left(a:seq) 354 | if caplen > maxlen 355 | if exists('g:showmap_prompt_notruncate') 356 | let numlines = 1 + caplen / maxlen 357 | if numlines > &cmdheight 358 | if !exists('t:showmap_cmdheight') 359 | let t:showmap_cmdheight = &cmdheight 360 | endif 361 | let &cmdheight = numlines 362 | endif 363 | else 364 | let caption = strcharpart(caption, 0, maxlen - 5) . ' ...' 365 | endif 366 | endif 367 | echohl ShowmapPrefix 368 | echon ' '.a:seq 369 | echohl None 370 | echon s:prompt_sep 371 | echohl ShowmapList 372 | echon caption 373 | echohl None 374 | redraw 375 | endfun 376 | 377 | 378 | " s:error {{{2 379 | " Show error 380 | function! s:error(msg) 381 | if s:no_errors 382 | return 383 | endif 384 | redraw 385 | echo a:msg 386 | exe "sleep ".s:err_timeout 387 | endfun 388 | 389 | 390 | " s:cmd_chars_left {{{2 391 | " Return num of remaining chars available for printing on single line of cmd 392 | function! s:cmd_chars_left(seq) 393 | let seqlen = strchars(a:seq) 394 | let seplen = strchars(s:prompt_sep) 395 | let maxlen = &columns - seqlen - seplen - 4 396 | return maxlen 397 | endfun 398 | 399 | 400 | " s:list_completions {{{2 401 | " Return list of keys completing mappings starting with seq 402 | " 1st arg is a sequence of printable key names 403 | " 2nd arg is a letter = mode (n,v,o,x,i,c) 404 | function! s:list_completions(seq, mode) 405 | call s:log2file(printf("list_comp(): [%s] [%s]", a:seq, a:mode)) 406 | redir => rawlist 407 | silent exec a:mode.'map '.a:seq 408 | redir END 409 | let rawlines = split(rawlist, "\n") 410 | call s:log2file(" rawlines: ".string(rawlines)) 411 | let seq = substitute(a:seq, '\c', s:raw2str(s:mapleader()), '') 412 | let lines = [] 413 | for line in rawlines 414 | call s:log2file(" stridx('".line."', '".seq."')") 415 | let pos = stridx(line, seq) 416 | if pos != -1 417 | " remaining = lhs without starting seq 418 | let remaining_lhs_to_eol = strpart(line, pos+strlen(seq)) 419 | let spc_pos = stridx(remaining_lhs_to_eol, ' ') 420 | let remaining_lhs = (spc_pos != -1) 421 | \ ? strpart(remaining_lhs_to_eol, 0, spc_pos) 422 | \ : remaining_lhs_to_eol 423 | call add(lines, remaining_lhs) 424 | endif 425 | endfor 426 | if s:sort_list_completion 427 | call sort(lines) 428 | endif 429 | return lines 430 | endfun 431 | 432 | 433 | " s:raw2str {{{2 434 | " Convert raw key to its printable name (eg. ' ' => '') 435 | " 1st arg is the raw key, from getchar() or similar 436 | function! s:raw2str(c) 437 | call s:log2file(printf("raw2str(): [%s]", a:c)) 438 | if type(a:c) == type(0) 439 | return nr2char(a:c) 440 | elseif a:c == ' ' 441 | call s:log2file(" keyname: []") 442 | return '' 443 | elseif a:c == '\' 444 | call s:log2file(" keyname: [\\]") 445 | return '\' 446 | elseif char2nr(strpart(a:c,0,1)) == 128 447 | " input() will eat the content of feedkeys() and stuff will get eval'd 448 | call feedkeys("\".a:c."\") 449 | let keyname = input('') 450 | call s:log2file(printf(" keyname: [%s]", keyname)) 451 | return keyname 452 | else 453 | return a:c 454 | endif 455 | endfun 456 | 457 | 458 | " s:str2raw {{{2 459 | " Convert sequence of key names to raw chars 460 | function! s:str2raw(seq) 461 | call s:log2file(printf("str2raw(): [%s]", a:seq)) 462 | let seq = substitute(a:seq, '\c', s:mapleader(), '') 463 | let evalstr = printf('"%s"', escape( 464 | \ substitute(escape(seq, '\'), '<', '\\<', 'g'), 465 | \ '"')) 466 | call s:log2file(printf(" evalstr: [%s]", evalstr)) 467 | let rawseq = eval(evalstr) 468 | call s:log2file(printf(" rawseq: [%s]", rawseq)) 469 | return rawseq 470 | endfun 471 | 472 | 473 | " s:log2file {{{2 474 | " Debug to logfile 475 | function! s:log2file(msg) 476 | if !exists('g:showmap_debug') | return | endif 477 | call writefile( 478 | \ ['['.strftime("%T").'] '.a:msg], 479 | \ s:debug_logfile, 480 | \ "a") 481 | endfun 482 | 483 | 484 | "------------------------ 485 | " Variables/Options {{{1 486 | "------------------------ 487 | 488 | let s:char_pattern = '<\%([CSMAD]-\)*\%([a-zA-Z]\+\d*\|[^>]\)>' 489 | let s:accepted_modes = ['n', 'v', 'x', 's', 'o', 'i', 'c'] 490 | let s:debug_logfile = get(g:, 'showmap_debug_logfile', 491 | \ '/tmp/showmap.log') 492 | let s:prompt_sep = get(g:, 'showmap_prompt_separator', ' | ') 493 | let s:list_separator = get(g:, 'showmap_list_separator', ' ') 494 | let s:map_caption_sep = get(g:, 'showmap_whatis_separator', ' => ') 495 | let s:no_errors = get(g:, 'showmap_no_errors', 0) 496 | let s:err_timeout = get(g:, 'showmap_err_timeout', 1) 497 | let s:autobind_minlen = get(g:, 'showmap_autobind_minlen', 3) 498 | let s:sort_list_completion = get(g:, 'showmap_sort_list_completion', 1) 499 | let s:key_quit = char2nr(s:str2raw( 500 | \ get(g:, 'showmap_quit_key', ""))) 501 | let s:key_help = char2nr(s:str2raw( 502 | \ get(g:, 'showmap_help_key', ""))) 503 | let s:key_multi = char2nr(s:str2raw( 504 | \ get(g:, 'showmap_multi_key', ""))) 505 | let s:key_help_all = char2nr(s:str2raw( 506 | \ get(g:, 'showmap_helpall_key', ""))) 507 | let s:key_whatis_exec = char2nr(s:str2raw( 508 | \ get(g:, 'showmap_whatis_exec', ""))) 509 | 510 | " No autobind on mappings that fall back on key-waiting commands 511 | let s:autobind_default_exceptions = {'n': {}} 512 | for k in ['c', 'y', 'd'] 513 | for o in ['f', 'F', 't', 'T'] 514 | let s:autobind_default_exceptions['n'][k.o] = 1 515 | endfor 516 | endfor 517 | 518 | 519 | " vim: et sw=2: 520 | -------------------------------------------------------------------------------- /doc/showmap.txt: -------------------------------------------------------------------------------- 1 | *showmap.txt* Multiple-char mappings helper *showmap* 2 | 3 | showmap MANUAL 4 | 5 | 1. About showmap |showmap-about| 6 | 2. Quick Start |showmap-quickstart| 7 | 3. Key Mappings and Commands |showmap-keymappings| 8 | |showmap-commands| 9 | 4. Options |showmap-options| 10 | 5. Highlight Groups |showmap-highlight| 11 | 6. Changelog |showmap-changelog| 12 | 7. Contribute |showmap-contribute| 13 | 8. License |showmap-license| 14 | 15 | ============================================================================= 16 | 1. ABOUT showmap ~ 17 | *showmap-about* 18 | 19 | Multichar mappings starting with the same sequence (Eg. `xa`, 20 | `xb`, ...) are useful to make conceptual groups, but they suffer from 21 | two issues: 22 | 23 | - they time out 24 | - it's not always easy to remember all the keys 25 | 26 | Of course, you can always tweak the 'timeout' option, but it's global to all 27 | mappings, and sometimes you just need a shorter timeout Eg. for insert maps. 28 | 29 | Showmap automatically sets helper mappings on the common prefixes, so as to 30 | wait for a specific period of time (or indefinitely), while showing a list of 31 | available keys to complete the current prefix. 32 | 33 | In the example above, typing `x` and letting it timeout will call the 34 | showmap helper, listing the completions (`a` and `b`) in the echo area. You 35 | can then press `a` to execute `xa`, or `a` to check what the 36 | mapping does. 37 | 38 | ============================================================================= 39 | 2. QUICK START ~ 40 | *showmap-quickstart* 41 | 42 | 1. Install the plugin Eg. with Pathogen: 43 | > 44 | `cd ~/.vim/bundle && git clone https://github.com/fcpg/vim-showmap` 45 | < 46 | 2. Use your mappings as usual. If you stall while typing a three-char (by 47 | default) normal mapping, a contextual help will show up in the cmdline. 48 | 49 | ============================================================================= 50 | 3. KEY MAPPINGS AND FUNCTIONS ~ 51 | *showmap-keymappings* 52 | 53 | While showmap helper is active: 54 | 55 | - 56 | Wait for a keystroke and show the corresponding mapping (LHS => RHS) in 57 | the echo area. You can then press to execute it, or any other key 58 | to return to the completion list -- unless 'g:showmap_whatis_timeout' is 59 | set. 60 | 61 | - 62 | Resume the typing: the following keystrokes will be added to the current 63 | prefix in the standard input buffer, as if you typed the whole thing at 64 | once. The first keystroke after does not time out. 65 | 66 | - 67 | Prompt user to enter several chars and show the corrseponding mapping. 68 | 69 | - 70 | Show all mappings completing the current prefix. 71 | Press again to return to completion list, or to quit the helper. 72 | You can complete the mapping directly from here. 73 | 74 | - 75 | Quit the helper. 76 | *showmap-functions* 77 | 78 | *showmap#bind_helper* 79 | Arg: char name sequence 80 | Arg: mode(s) (default: 'n') 81 | 82 | Bind the showmap helper to the given sequence. 83 | Example: 84 | > 85 | call showmap#bind_helper("g", 'ni') 86 | < 87 | *showmap#autobind* 88 | Arg: mode(s) 89 | 90 | Automatically bind to all mapping prefixes of length 91 | 'showmap_autobind_minlen' for the given mode(s). 92 | Note that this function is automatically called by default for normal mode 93 | during startup, unless 'g:showmap_no_autobind' is set. 94 | Mappings starting with `` or `` are ignored. 95 | Example: 96 | > 97 | call showmap#autobind('i') 98 | < 99 | *showmap#helper* 100 | Arg: char name sequence 101 | Arg: mode 102 | 103 | Call the showmap helper. The mappings calling this function are normally 104 | created automatically by |showmap#bind_helper|() and/or |showmap#autobind|(). 105 | Example: 106 | > 107 | nmap t showmap#helper("t","n") 108 | < 109 | ============================================================================= 110 | 4. OPTIONS ~ 111 | *showmap-options* 112 | 113 | *g:showmap_no_autobind* default: `unset` 114 | Prevent automatic call of |showmap#autobind|() during startup. 115 | 116 | *g:showmap_prompt_separator* default: " | " 117 | Separator between prefix and list of completions. 118 | 119 | *g:showmap_list_separator* default: " " 120 | Separator between completion keys. 121 | 122 | *g:showmap_whatis_separator* default: " => " 123 | Separator between LHS and RHS when showing a mapping. 124 | 125 | *g:showmap_auto_whatis_all* default: `unset` 126 | Directly show all mappings (LHS and RHS) instead of the 127 | (short) list of completions. 128 | 129 | *g:showmap_whatis_timeout* default: `unset` 130 | How long in seconds to show a mapping. 131 | Wait for a keystroke if unset. 132 | 133 | *g:showmap_no_errors* default: `unset` 134 | Do not show errors (eg. "Key not mapped") 135 | 136 | *g:showmap_err_timeout* default: `1` 137 | How long in seconds to show the error messages. 138 | 139 | *g:showmap_autobind_minlen* default: `3` 140 | How long should mappings be before a common prefix is looked 141 | for by |showmap#autobind|(). If a prefix is found, the helper is 142 | bound at 'g:showmap_autobind_minlen' - 1 (2nd char of prefix, 143 | by default). 144 | 145 | *g:showmap_sort_list_completion* default: `1` 146 | Whether to sort completion list. 147 | 148 | *g:showmap_quit_key* default: `` 149 | Key to quit helper. 150 | Same format as :map Eg. `""` (without backslash). 151 | 152 | *g:showmap_help_key* default: `` 153 | Key to show a specific mapping. 154 | 155 | *g:showmap_multi_key* default: `` 156 | Key to resume typing from current prefix, or (after ) 157 | to show the mapping for a 2+ char completion. 158 | 159 | *g:showmap_helpall_key* default: `` 160 | Key to show all mappings with current prefix. 161 | 162 | *g:showmap_whatis_exec* default: `` 163 | Key to execute the mapping currently being shown (after ). 164 | 165 | *g:showmap_prompt_notruncate* default: `unset` 166 | Do not truncate completion lists longer than echo area 167 | (temporarily increase cmdline height if need be). 168 | 169 | *g:showmap_captions* default: `unset` 170 | Dictionary of `[mode][sequence] => "msg"`, for custom helper 171 | messages (instead of standard completion list). 172 | 173 | *g:showmap_no_autobind_default_exceptions* default: `unset` 174 | Ignore the default exceptions for |showmap#autobind|(). 175 | if unset (default), helper is prevented from binding to maps 176 | that fall back to f/F/t/T Eg. `cfu`. 177 | 178 | *g:showmap_autobind_exceptions* default: `unset` 179 | Dictionary of `[mode][sequence] => 1`, to prevent some helper 180 | bindings by |showmap#autobind|(). 181 | 182 | *g:showmap_map_check* default: `unset` 183 | Show "Key not mapped" message when pressing a key that 184 | does not trigger a mapping, and wait for another key till 185 | an existing mapping is triggered. By default, this option 186 | is unset, so mappings are not checked and keys are sent 187 | as is. 188 | 189 | *g:showmap_no_map_check* default: `unset` 190 | Dictionary of `[mode][sequence] => 1`, to bypass map checks 191 | on some sequences, if |g:showmap_map_check| is set. 192 | Eg. if you have maps on `z*`, `z@` etc. with the helper on `z`, 193 | this option lets the helper fall back on the standard `z` 194 | commands. 195 | 196 | ============================================================================= 197 | 5. HIGHLIGHT GROUPS ~ 198 | *showmap-highlight* 199 | *ShowmapPrefix* default: MoreMsg 200 | *ShowmapList* default: Normal 201 | *ShowmapLHSPrefix* default: SpecialKey 202 | *ShowmapLHSComp* default: MoreMsg 203 | *ShowmapRHS* default: String 204 | 205 | ============================================================================= 206 | 6. CHANGELOG ~ 207 | *showmap-changelog* 208 | 209 | [1.1] - 2017-02-07 210 | - Incremental completions, 'map_check' options 211 | [1.0] - 2017-02-02 212 | - Initial release 213 | 214 | ============================================================================= 215 | 7. CONTRIBUTE ~ 216 | *showmap-contribute* 217 | 218 | Contribute on [Github](https://github.com/fcpg/vim-showmap) 219 | 220 | ============================================================================= 221 | 8. LICENSE ~ 222 | *showmap-license* 223 | 224 | [Attribution-ShareAlike 4.0 Int.](https://creativecommons.org/licenses/by-sa/4.0/) 225 | 226 | vim: set expandtab sts=2 ts=2 sw=2 tw=78 ft=help norl: 227 | -------------------------------------------------------------------------------- /img/vim-showmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcpg/vim-showmap/120dc96c61edd0ec5dd038754379a6e85dc3c76f/img/vim-showmap.png -------------------------------------------------------------------------------- /img/vim-showmap_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcpg/vim-showmap/120dc96c61edd0ec5dd038754379a6e85dc3c76f/img/vim-showmap_thumb.png -------------------------------------------------------------------------------- /plugin/showmap.vim: -------------------------------------------------------------------------------- 1 | 2 | " showmap.vim - help for multiple-key mapping sequences 3 | if exists("g:loaded_showmap") || &cp 4 | finish 5 | endif 6 | let g:loaded_showmap = 1 7 | 8 | 9 | "---------------- 10 | " Highlight {{{1 11 | "---------------- 12 | 13 | hi default link ShowmapPrefix MoreMsg 14 | hi default link ShowmapList Normal 15 | hi default link ShowmapLHSPrefix SpecialKey 16 | hi default link ShowmapLHSComp MoreMsg 17 | hi default link ShowmapRHS String 18 | 19 | 20 | "----------- 21 | " Init {{{1 22 | "----------- 23 | 24 | augroup ShowmapGroup 25 | au! 26 | autocmd VimEnter * 27 | \ if !exists('g:showmap_no_autobind') 28 | \| call showmap#autobind(get(g:, 'showmap_autobind_modes', 'n')) 29 | \| endif 30 | augroup END 31 | 32 | 33 | " vim: et sw=2: 34 | --------------------------------------------------------------------------------