Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I try to normalize access to Vim's command line mode from any other mode in order to simplify my actual mappings. For example to make the <f6> key work from anywhere I define the following mappings:

noremap <script> <unique> <silent> <f6> <sid>:echomsg 'Hello World!'<cr>
noremap! <script> <unique> <silent> <f6> <sid>:echomsg 'Hello World!'<cr>

The above mappings remap to the <sid>: key mapping given below before they get down to work:

noremap <unique> <expr> <sid>: <sid>StartCmdLineMode()
noremap! <unique> <expr> <sid>: <sid>StartCmdLineMode()
function! s:StartCmdLineMode()
  let a=mode()
  if a ==# 'n' 
    return ':'
  " Type <c-v><c-v> to insert ^V. 
  elseif a =~ '[vV^V]'
    return ":\<c-u>"
  elseif a ==# 'no'
    return "\<c-c>:"
  elseif a ==# 'i' 
    return "\<c-o>:"
  elseif a ==# 'c' 
    let b=getcmdtype()
    if b ==# ':' 
      return "\<c-e>\<c-u>"
    else
      return "\<c-c>:"
    endif
  else
    return ''
  endif
endfunction

Is there a staightforward way instead of my obfuscated approach?

share|improve this question
add comment

2 Answers

When does the following not work?

nnoremap <F6> <ESC><ESC>:command<CR>
share|improve this answer
add comment

In the meantime I came up with the following approach:

noremap <script> <unique> <SID><\O> <Nop>
inoremap <script> <unique> <SID><\O> <C-\><C-O><SID><\O>
cnoremap <script> <unique> <SID><\O> <C-\><C-N><SID><\O>
noremap <script> <unique> <SID><\N> <Nop>
noremap! <script> <unique> <SID><\N> <C-\><C-N><SID><\N>

For each Vim mode the <SID><\O> key sequence is mapped in order to appropriately escape (e.g. <C-\><C-O>) from Vim's current mode (e.g. insert-mode) to its normal mode. The right hand side of each mapping ends in its left hand side (e.g. <SID><\O>) in order to recursively try to escape again. The script-local (<script>, <SID>) recursion stops as soon the last escape key sequence reaches Vim's normal mode in which the <SID><\O> key sequence is mapped to nothing (<Nop>).

Likewise the <SID><\N> key sequence is mapped to not only escape once (<SID><\O>) from e.g. insert-mode before returning back but permanently stay in normal-mode.

With the help of the above definitions I mapped the <F1> and <S-F1> function keys as follows:

noremap <script> <unique> <expr> <F1> <SID>ToggleHelp(':<C-U>help', '<SID>')
noremap! <script> <unique> <expr> <F1> <SID>ToggleHelp(':<C-U>help', '<SID>')
noremap <script> <unique> <expr> <S-F1> <SID>ToggleHelp(':<C-U>helpgrep', '<SID>')
noremap! <script> <unique> <expr> <S-F1> <SID>ToggleHelp(':<C-U>helpgrep', '<SID>')
function! s:ToggleHelp(cmd, sid)
  ToggleVar s:HelpCwordOn
  let a=s:HelpCwordOn ? '<cword>' : '<cWORD>'
  return a:sid . '<\O>' . a:cmd . ' ' . expand(a) . ' '
endfunction
command! -bang -nargs=+ ToggleVar call <SID>ToggleVar(<bang>0, <f-args>)
function! s:ToggleVar(bang, var)
  let {a:var}=exists(a:var) ? !{a:var} : !a:bang
endfunction

Instead of having the <F1> key simply open Vim's help in a new window, it starts the :help command with the inner word (<cword>) under the cursor. By consecutively pressing the <F1> key, one switches to the outer word (<cWORD>) and toggels back again.

The 4 mappings from the use case above could also be defined as follows in order to not repeat yourself; i.e. keeping it "dry":

let a='noremap'
let b='<script> <unique> <expr>'
let c='<F1>'
let d='<S-F1>'
let e='<SID>ToggleHelp('':<C-U>help'
let f='grep'
let g=''', ''<SID>'')'
let h=b . ' ' . c . ' ' . e . g
let i=b . ' ' . d . ' ' . e . f . g
exec a . ' ' . h
exec a . '! ' . h
exec a . ' ' . i
exec a . '! ' . i
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.