Skip to content

Instantly share code, notes, and snippets.

@emanon001
Created March 13, 2012 15:46
Show Gist options
  • Save emanon001/2029500 to your computer and use it in GitHub Desktop.
Save emanon001/2029500 to your computer and use it in GitHub Desktop.
Vim script: Definition of key-mapping using a prefix key is supported.
let s:current_prefix_key = ''
command! -nargs=1 PrefixKeyMappingStart
\ let s:current_prefix_key = <q-args>
command! -nargs=0 PrefixKeyMappingEnd
\ let s:current_prefix_key = ''
function! s:create_prefix_key_mapping_commands()
let base_commands = ['map', 'nmap', 'vmap', 'xmap', 'smap', 'omap',
\ 'imap', 'lmap', 'cmap']
let command_prefix = 'P'
for command in base_commands
let bang = command ==# 'map' ? '-bang' : ''
" Map command.
execute printf('command! -nargs=+ %s %s%s
\ call s:create_prefix_mapping(''%s'',''<bang>'', <q-args>)',
\ bang, command_prefix, command, command)
" Nore-map command.
let nore_command = matchstr(command, '^\zs.*\zemap!\=') . 'noremap'
execute printf('command! -nargs=+ %s %s%s
\ call s:create_prefix_key_mapping(''%s'',''<bang>'', <q-args>)',
\ bang, command_prefix, nore_command, nore_command)
endfor
endfunction
function! s:create_prefix_key_mapping(command_name, bang, command_arg)
if s:current_prefix_key == ''
echohl WarningMsg | echomsg ':PrefixKeyMappingStart {prefix-key} is not executed.' | echohl None
return
endif
let map_arguments_pattern = '\%(' .
\ join(['<buffer>', '<silent>', '<special>', '<script>', '<expr>', '<unique>'], '\|') .
\ '\)'
let _ = matchlist(a:command_arg, '^\(\%('. map_arguments_pattern . '\s*\)*\)\(.*\)$')
execute a:command_name . a:bang _[1]
\ s:current_prefix_key . _[2]
endfunction
call s:create_prefix_key_mapping_commands()
let &l:indentexpr = 'GetVimPrefixKeyMappingIndent(' . &l:indentexpr . ')'
setlocal indentkeys+==PrefixKeyMappingEnd
if exists('*GetVimPrefixKeyMappingIndent')
finish
endif
function GetVimPrefixKeyMappingIndent(base_indent)
let indent = a:base_indent
let base_lnum = prevnonblank(v:lnum - 1)
let line = getline(base_lnum)
if 0 <= match(line, '\(^\||\)\s*\(PrefixKeyMappingStart\)\>')
let indent += &l:shiftwidth
endif
if 0 <= match(getline(v:lnum), '\(^\||\)\s*\(PrefixKeyMappingEnd\)\>')
let indent -= &l:shiftwidth
endif
return indent
endfunction
@emanon001
Copy link
Author

Usage

Create key mappings

PrefixKeyMappingStart {prefix-key}
  " P{key_mapping_command} {args} {lhs} {rhs}
  " -> {key_mapping_command} {args} {prefix-key}{lhs} {rhs}
  Pnnoremap {lhs} {rhs}
  Pinoremap {lhs} {rhs}
  Pvnoremap {lhs} {rhs}
PrefixKeyMappingEnd

@emanon001
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment