Aqui está o porquê da pergunta estar no SO: é necessário um script não trivial ...
" Public Mappings {{{1
onoremap <silent> i% :<c-u>call <sid>SelectFirstPair(1,0)<cr>
xnoremap <silent> i% :<c-u>call <sid>SelectFirstPair(1,1)<cr><esc>gv
onoremap <silent> a% :<c-u>call <sid>SelectFirstPair(0,0)<cr>
xnoremap <silent> a% :<c-u>call <sid>SelectFirstPair(0,1)<cr><esc>gv
" Public Mappings }}}1
"------------------------------------------------------------------------
" Private Functions {{{1
" Note: most functions are best placed into
" autoload/«your-initials»/«omap_any_bracket».vim
" Keep here only the functions are are required when the plugin is loaded,
" like functions that help building a vim-menu for this plugin.
let s:k_pairs = {
\ '(': ')',
\ '[': ']',
\ '{': '}',
\ '<': '>'
\ }
let s:k_begin = '[([{<]'
let s:k_end = '[)\]}>]'
function! s:SelectFirstPair(inner, visual)
" In case we already are in visual mode, we may have to extend the current
" zone if it selects a pair of brackets
if a:visual
let char_b = lh#position#char_at_mark("'<")
if char_b =~ s:k_begin
\ && s:k_pairs[char_b] == lh#position#char_at_mark("'>")
call search('.', 'bW') " previous char
elseif a:inner
" handle case the case "vi%i%i%"
let current_pos = getpos('.')
call setpos('.', getpos("'<"))
call search('.', 'bW') " previous char
let pos_b = getpos('.')
call setpos('.', getpos("'>"))
call search('.', 'W') " next char
let pos_e = getpos('.')
let char_b = lh#position#char_at_pos(pos_b)
let char_e = lh#position#char_at_pos(pos_e)
echomsg "chars = ".char_b.char_e
if char_b =~ s:k_begin
\ && s:k_pairs[char_b] == char_e
call setpos('.', pos_b) " restore start_pos
call search('.', 'bW') " previous char
else
call setpos('.', current_pos) " restore init_pos
endif
endif
endif
" Searching the n outer blocks requested
let cnt = v:count <= 0 ? 1 : v:count
while cnt > 0
let cnt -= 1
let char_c = lh#position#char_at_pos(getpos('.'))
let accept_at_current = char_c =~ s:k_begin ? 'c' : ''
" Begin of the current outer block
if 0 ==searchpair(s:k_begin, '', s:k_end, 'bW'.accept_at_current, 'lh#syntax#skip()')
throw "No outer bloc"
endif
if cnt > 0
call search('.', 'bW') " previous char
endif
endwhile
let char_b = lh#position#char_at_pos(getpos('.'))
normal! v
" End of the outer block
let pos_e = searchpair(s:k_begin, '', s:k_end, 'W', 'lh#syntax#skip()')
let char_e = lh#position#char_at_pos(getpos('.'))
if pos_e == 0
throw "pos_e == 0"
elseif s:k_pairs[char_b] != char_e
echomsg "unbalanced blocks"
endif
" Adjusting the extremities
if a:inner
call search('.', 'b')
normal! o
call search('.')
normal! o
endif
endfunction
" Private Functions }}}1
NB: Eu reutilizei a função do lh-vim-lib - BTW, há um pequeno bug na versão do lh#position#char_at_pos()
in conf: col()
não deve ser usado.
line 13: E15: Invalid expression: E15: Invalid expression: {
(…). Eu tenho o vim 7.2, seu código requer 7.3? A propósito, enquanto as questões de programação geralmente são redirecionadas para o SO, respostas de script (para shells, editores e outros programas que podem ser gravados) são comuns aqui.