How to quickly select parenthesized text from outside of the parentheses in Vim?

The difference between {a,i}×{(,),b} text-object commands and their ", ', ` counterparts primarily results from the difference in definitions of a block and a quoted string (see :help v_ab, :help v_aquote).

While the latter is the text from the previous quote character on the current line until the next one on that same line (escaped ones aside), the former is the text between the nth previous unmatched opening parenthesis and the matching closing one. Simply put, the command va( (without a count) is like [(v%—if there is no unmatched parenthesis before the cursor, both select nothing. However, the command va" scans the current line to find a matching pair of quotes, anyway.

The main reason for this difference in behavior, I suppose, is that quoted strings, in contrast to parenthesis, are assumed to be non-nested (at least in perspective of the built-in Vim text objects).

To select the text in the next parenthesis on the current line, one can use %vi( or %va(, depending on whether it is desirable to include the parentheses in the selection or not, respectively.


There is a comment on Hacker News that points to a script supposedly solving the issue.

Untested, but it’s by Steve Losh, so it might be good.

--- EDIT ---

Here is a working link and here it is copied here for posterity:

" Motion for "next/last object". For example, "din(" would go to the next "()" pair
" and delete its contents.

onoremap an :<c-u>call <SID>NextTextObject('a', 'f')<cr>
xnoremap an :<c-u>call <SID>NextTextObject('a', 'f')<cr>
onoremap in :<c-u>call <SID>NextTextObject('i', 'f')<cr>
xnoremap in :<c-u>call <SID>NextTextObject('i', 'f')<cr>

onoremap al :<c-u>call <SID>NextTextObject('a', 'F')<cr>
xnoremap al :<c-u>call <SID>NextTextObject('a', 'F')<cr>
onoremap il :<c-u>call <SID>NextTextObject('i', 'F')<cr>
xnoremap il :<c-u>call <SID>NextTextObject('i', 'F')<cr>

function! s:NextTextObject(motion, dir)
  let c = nr2char(getchar())

  if c ==# "b"
      let c = "("
  elseif c ==# "B"
      let c = "{"
  elseif c ==# "d"
      let c = "["
  endif

  exe "normal! ".a:dir.c."v".a:motion.c
endfunction

Tags:

Vim