Vim Tips Wiki
Register
Advertisement

Duplicate tip

This tip is very similar to the following:

These tips need to be merged – see the merge guidelines.

Tip 318 Printable Monobook Previous Next

created August 22, 2002 · complexity intermediate · author Abitkin · version 5.7


This is an extension of VimTip153. I found this tip useful, but the jump seemed out of place for me, I couldn't enter just one ' or ", and so I created an improvement

Basically, I set it up so that when you're in perl and have a non keyword charcter, (except for @, $ and % for perl) and you type a { you get:

{
  | <- cursor
}

Whereas, when I have a keyword I get:

word{}

With the cursor in the middle, for hashes in perl. I can jump out of any block, except the "..." or '...' blocks, by typing their closing character. So } jumps me out past the next } in the file.

Warning, this search may wrap around.

Finally, I made it so that, using the alt key,

  • <Alt-'> inserts a '
  • <Alt-/> inserts a "
  • <Alt-[> inserts a [
  • <Alt-]> inserts a ]
  • <Alt--> inserts a {
  • <Alt-=> inserts a }
  • <Alt-,> inserts a <
  • <Alt-.> inserts a >
" File - matchMe.vim
" Date - Wednesday, August 21, 2002
" This code fixes my problem with
" does the one format for perl and acts correctly with
" hashes
function! InsertBrackets()
  let fileType = &ft
  if fileType == 'perl'
    let col = col('.') - 1
    if !col || getline('.')[col - 1] !~ '\k' && getline('.')[col - 1] !~ '\$' && getline('.')[col - 1] !~ '@' && getline('.')[col - 1] !~ '%' && getline('.')[col - 1] !~ '#'
      return "{\<CR>\<BS>}\<Esc>ko"
    else
      return "{}\<Esc>i\<c-o>:echo \<CR>"
    endif
  else
    return "{\<CR>\<BS>}\<Esc>ko"
  endif
endfunction

" This code jumps out of the brackets
function! JumpNext(startChar, endChar)
  let ret1 = "\<Esc>:echo searchpair('".a:startChar."','','".a:endChar."','W','synIDattr(synID(line(\".\"), col(\".\"), 0), \"name\") =~? \"string\"')\<CR>i\<Right>"
  return ret1
endfunction

" mappings
inoremap " ""<Esc>i<c-o>:echo <CR>
inoremap ' ''<Esc>i<c-o>:echo <CR>
inoremap < <><Esc>i<c-o>:echo <CR>
inoremap ( ()<Esc>i<c-o>:echo <CR>
inoremap [ []<Esc>i<c-o>:echo <CR>
inoremap { <c-r>=InsertBrackets ()<CR>
inoremap > <c-r>=JumpNext("<",">")<CR>
inoremap ) <c-r>=JumpNext("(",")")<CR>
inoremap ] <c-r>=JumpNext("[","]")<CR>
inoremap } <c-r>=JumpNext("{","}")<CR>
inoremap <m--> [
inoremap <m-=> ]
inoremap <m-/> "
inoremap <m-[> {
inoremap <m-]> }
inoremap <m-,> <
inoremap <m-.> >
inoremap <m-9> (
inoremap <m-0> )
inoremap <m-'> '

Comments[]

I used a similar (but mostly far more basic...) set of functions and mappings for my C and Python code, but with a slightly different behavior...

Here is some code I find a bit more convenient (at least for my liking).

fun! s:Toggle_EditHelpers()
  if !exists('b:edithelpers_on') || b:edithelpers_on == 0
    let b:edithelpers_on=1
    inoremap '' ''<Esc>i
    inoremap ''' '''
    inoremap """ """
    inoremap "" ""<Esc>i
    inoremap <> <><Esc>i
    inoremap [] []<Esc>i
    inoremap () ()<Esc>i
    inoremap {} {}<Esc>i
    cnoremap '' ''<Left>
    cnoremap ''' '''
    cnoremap """ """
    cnoremap "" ""<Left>
    cnoremap <> <><Left>
    cnoremap [] []<Left>
    cnoremap () ()<Left>
    cnoremap {} {}<Left>
  else
    let b:edithelpers_on=0
    iunmap ''
    iunmap '''
    iunmap """
    iunmap ""
    iunmap <>
    iunmap []
    iunmap ()
    iunmap {}
    cunmap ''
    cunmap '''
    cunmap """
    cunmap ""
    cunmap <>
    cunmap []
    cunmap ()
    cunmap {}
  endif
endfun
" Allow to be easily switched on and off.
nnoremap <silent><F9> :call <SID>Toggle_EditHelpers()<CR>
vnoremap <silent><F9> <C-C>:call <SID>Toggle_EditHelpers()<CR>
inoremap <silent><F9> <C-O>:call <SID>Toggle_EditHelpers()<CR>
" turn on by default
:call <SID>Toggle_EditHelpers()

One more update. I found this quite useful, as sometimes I delete the ending char, to insert it around a block, and then when I type it again, I just get a flash...

" This code jumps out of the brackets
function! JumpNext(startChar, endChar,oneItem)
 let ret1 = "\<Esc>:if \"0\"==searchpair('".a:startChar."','','".a:endChar."','W','synIDattr(synID(line(\".\"), col(\".\"), 0), \"name\") =~? \"string\"')\<CR>exec(\"normal i".a:oneItem."\")\<CR>endif\<CR>i\<Right>"
 return ret1
endfunction

" mappings
inoremap > <c-r>=JumpNext("<",">","\<m-.>")<CR>
inoremap ) <c-r>=JumpNext("(",")","\<m-0>")<CR>
inoremap ] <c-r>=JumpNext("[","]","\<m-=>")<CR>
inoremap } <c-r>=JumpNext("{","}","\<m-]>")<CR>

My only guess is that your escape char is <m-[> Changing that binding may fix your problem.

Here's an update, with toggle, and the toggle should let your escape work again:

" File - matchMe.vim
" Date - Wednesday, August 21, 2002
" This code fixes my problem with
" does the one format for perl, and acts
" correctly with hashes.
function! InsertBrackets()
  let fileType = &ft
  if fileType == 'perl'
    let col = col('.') - 1
    if !col || getline('.')[col - 1] !~ '\k' && getline('.')[col - 1] !~ '\$' && getline('.')[col - 1] !~ '@' && getline('.')[col - 1] !~ '%' && getline('.')[col - 1] !~ '#'
      return "{\<CR>\<BS>}\<Esc>ko"
    else
      return "{}\<Esc>i\<c-o>:echo \<CR>"
    endif
  else
    return "{\<CR>\<BS>}\<Esc>ko"
  endif
endfunction

" This code jumps out of the brackets
function! JumpNext(startChar, endChar,oneItem)
  let ret1 = "\<Esc>:if \"0\"==searchpair('".a:startChar."','','".a:endChar."','W','synIDattr(synID(line(\".\"), col(\".\"), 0), \"name\") =~? \"string\"')\<CR>exec(\"normal i".a:oneItem."\")\<CR>endif\<CR>i\<Right>"
  return ret1
endfunction

" Added toggle.
fun! s:Toggle_Edit2()
  if exists('b:edithelpers_on') && b:edithelpers_on == 1
    if (!exists('b:edithelpers2_on') || b:edithelpers2_on == 0)
      let b:edithelpers2_on=1
      " mappings
      inoremap > <c-r>=JumpNext("<",">","\<m-.>")<CR>
      inoremap ) <c-r>=JumpNext("(",")","\<m-0>")<CR>
      inoremap ] <c-r>=JumpNext("[","]","\<m-=>")<CR>
      inoremap } <c-r>=JumpNext("{","}","\<m-]>")<CR>
      inoremap <m-=> ]
      inoremap <m-]> }
      inoremap <m-.> >
      inoremap <m-0> )
    else
      let b:edithelpers2_on=0
      iunmap >
      iunmap )
      iunmap ]
      iunmap }
      iunmap <m-=>
      iunmap <m-]>
      iunmap <m-.>
      iunmap <m-0>
    endif
  endif
endfun

" Added toggle.
fun! s:Toggle_Edit()
  if !exists('b:edithelpers_on') || b:edithelpers_on == 0
    let b:edithelpers_on=1
    " mappings
    inoremap " ""<Esc>i<c-o>:echo <CR>
    inoremap ' ''<Esc>i<c-o>:echo <CR>
    inoremap < <><Esc>i<c-o>:echo <CR>
    inoremap ( ()<Esc>i<c-o>:echo <CR>
    inoremap [ []<Esc>i<c-o>:echo <CR>
    inoremap { <c-r>=InsertBrackets ()<CR>
    inoremap <m--> [
    inoremap <m-/> "
    inoremap <m-[> {
    inoremap <m-,> <
    inoremap <m-9> (
    inoremap <m-'> '
    if !exists('b:edithelpers2_on') || b:edithelpers2_on == 0
      call <SID>Toggle_Edit2()
    endif
  else
    iunmap "
    iunmap '
    iunmap <
    iunmap (
    iunmap [
    iunmap {
    iunmap <m-->
    iunmap <m-/>
    iunmap <m-[>
    iunmap <m-,>
    iunmap <m-9>
    iunmap <m-'>
    if exists('b:edithelpers2_on') && b:edithelpers2_on == 1
      call <SID>Toggle_Edit2()
    endif
    let b:edithelpers_on=0
  endif
endfun

nnoremap <silent><F9> :call <SID>Toggle_Edit()<CR>
inoremap <silent><F9> <C-O>:call <SID>Toggle_Edit()<CR>
call <SID>Toggle_Edit()
nnoremap <silent><F8> :call <SID>Toggle_Edit2()<CR>
inoremap <silent><F8> <C-O>:call <SID>Toggle_Edit2()<CR>
" F-8 toggles the jump
" F-9 toggles the bracketing feature and overrides F-8

I think I understand why it doesn't work.

When the function is first called, you get, e.g.,

inoremap " ""<Esc>i<c-o>:echo <CR>

but by the time you toggle it (calling the fucntion again)

iunmap "

It doesn't work because the " is substituted by " " by the interpreter, which is under the influence of the first inoremap, hence the error "No such mapping". I don't know why the interpreter behaves like this, It might be something I have in my .vimrc. Any solutions?


Advertisement