17

Say I have this line of text in Vim:

(foo bar (baz) qux)
    ^

and my cursor is on the space between the words foo and bar, as indicated. I often find that, in situations like this, I want to delete the entire right-hand side of the outer parenthesized expression (that is, to the right of my cursor), while leaving the left-hand side intact. That is, I'd like to end up with:

(foo)

Usually, I’d accomplish this with dt) (“delete until )”), but the addition of a nested parenthetical complicates things: That command would leave me with (foo) qux). I could also use d2t), but I’d prefer not to have to manually count the number of nested parentheses. I could also use di), but that deletes the entire text inside of the parentheses, leaving me with ().

Is there a Vim motion with the balance-awareness of the i- and a-modified motions that is also relative to the current cursor position?

ib.
  • 27,830
  • 11
  • 80
  • 100
adrian
  • 1,447
  • 15
  • 24

2 Answers2

15

You can use the ]) motion with d.

d])
Peter Rincker
  • 43,539
  • 9
  • 74
  • 101
  • I didn't know about `])`; that's certainly simpler than my solution (but mine should still work for non-vim versions of vi). – Keith Thompson Aug 25 '11 at 00:09
  • @Keith Thompson: Your solution is certainly vi compatible which is nice. My fear w/ your solution is that it is dependent on `F(` finding the appropriate `(` to jump to. I think I would prefer to do `df)` and repeat w/ `.` and then `a)`. Or `mxF(` then repeat `F` motion with `,` until the correct `(` is found then ``%d`x`` – Peter Rincker Aug 25 '11 at 00:18
  • Yeah, I just thought of a case where my solution won't work: `( (before) foo ^ (after) )`. The `F(` or `?(` will find the left paren preceding `before`, not the nearest one enclosing the cursor position. (I remember a `:set lisp` command from many years ago. I see vim still has it. What does it do? Yeah, I should RTFM.) – Keith Thompson Aug 25 '11 at 00:42
  • @Keith Thompson: `set lisp` will change some indenting rules and allow`-` as part of a keyword. – Peter Rincker Aug 25 '11 at 00:53
3
mxF(%d`x

Breaking it down:

mx

Set a mark x (pick whatever letter you like)

F(

Find previous ( character

%

Jump to matching )

d`x

Delete from here to mark x

That works for your specific case; I'm not sure how general it is. If the previous ( is not on the current line, use ?(<return> rather than F(.

EDIT:
I didn't mention d]) because I didn't know about it.

My solution won't work for this case:

( (before) foo (after) )
              ^

because it jumps back to the nearest (, not the nearest enclosing (.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631