8

Is there a motion for capturing text in between / or \? I know there is motions for other symbols ---

ci" - Capture 'text' inside "text"

vi( - Visual capture int var inside foo(int var)

di[ - Delete word [word] into []

The only workaround I can find is by using Vim Surround, and using it to change surrounding \ into " (cs\"), and then working from there. However, not only is it that kind of tedious, but the plugin only supports backslashes, not forward.

jahroy
  • 20,588
  • 9
  • 52
  • 104
dook
  • 973
  • 1
  • 10
  • 26
  • 1
    I've probably edited my answer 100 times, but it currently works for any pattern (e.g. single characters, words, regular expressions, etc...) and works over multiple lines (_after moderate testing_). Great question! – jahroy May 15 '14 at 05:13

4 Answers4

8

You could write your own text-object for this pretty easily.

onoremap <silent> i/ :<C-U>normal! T/vt/<CR> " inside /
onoremap <silent> a/ :<C-U>normal! F/vf/<CR> " around /

For it to work with visual mode :

xnoremap <silent> i/ :<C-U>normal! T/vt/<CR> " inside /
xnoremap <silent> a/ :<C-U>normal! F/vf/<CR> " around /

Similarly you could also do for \

Edit: Added info comments.

Dhruva Sagar
  • 6,291
  • 1
  • 23
  • 31
  • I think this answer definitely works the cleanest, though I'm having a little difficult understanding what it's doing. Nothing a little google-fu can't clear up. :) Thanks a bunch! – dook May 15 '14 at 04:41
  • Just a follow up to this, I wanted the same thing for matching regexes. For the "around" flavor I really wanted to take it one step further to match the regex flags as well so I came up with this version `xnoremap a/ :normal! F/vf/h/\/[gim]*/e` Seems to work so far! – Andrew Jan 15 '16 at 09:34
  • One more update, to add "y" flag and also clearing the search hi-lighting after you're done: `xnoremap a/ :normal! F/vf/h/\/[gimy]*/e:nohgv` – Andrew Jan 15 '16 at 09:54
3

Here's one way to do it with a mapping:

  nnoremap H mal??e+1<Enter>mb//<Enter>y`b`a

This mapping will yank everything between two occurrences of the last search pattern.

Place it in your .vimrc file to make it permanent.

Usage for your question:

  • search for forward slash: /\/ (note the backslash escape character)
  • position cursor between two slashes (or on second slash)
  • press H

Everything between the last / and the next / will get yanked.

Explanation:

  nnoremap H mal??e+1<Enter>mb//<Enter>y`b`a

 - nnoremap H      map H in normal mode, ignoring other mappings    
 - ma              place a mark (named a) at the current cursor location
 - l               move the cursor one char to the right
 - ??e+1<Enter>    move to 1 character after END of prev occurrence of last search pattern
 - mb              place a mark (named b) at the current cursor location
 - //<Enter>       go to the beginning of the next occurrence of the last search pattern
 - y`b             yank to the location of the mark named x (note: ` = "back tick")
 - `a              go to the mark named `a`

Example input:

This is a *funky* string
  • search for *
  • position cursor between two asterisks (or on 2nd asterisk)
  • press H

The word funky will be in the yank buffer.

You can use words as delimeters!

Example input:

<br>
Capture all this text.
<br>
  • search for <br>
  • press H in normal mode when between <br>s (or on 2nd <br>)

You can use regexes, too!

Example input:

<p>
Capture this paragraph.
</p>
  • search for <.\?p> (or <\/\{,1}p> to be more correct)
  • press H in normal mode when inside the paragraph (or on closing <p> tag)

...

A better approach might be to use a register to remember a delimiter, so you can use this mapping quickly and/or repeatedly. In other words, you could store / or \ or <\?p> in a register and use that to quickly capture text between your stored delimiter.

jahroy
  • 20,588
  • 9
  • 52
  • 104
  • 1
    This is quite the extensive answer! It went well beyond the scope of what I was asking for, but I love how it can capture between any searchable expression. I will definitely be using this in the future. :) – dook May 15 '14 at 05:38
  • 1
    @bark - Glad I could help! I learned a bunch while writing it, so thanks for asking the question! – jahroy May 15 '14 at 06:08
  • Is it possible to align mapping with existing Vim's convention? ci/ - should change inside slashes di, - should delete inside commas va% - should visually select between and including % – SenG Jun 08 '15 at 03:14
2

there is no built-in text object with slash. However there are plugins support customized text-object, like: targets

Kent
  • 173,042
  • 30
  • 210
  • 270
  • This may not have exactly answered my question, but thank you for the plugin link. I tried it out and it's kind of fun to play with. – dook May 15 '14 at 04:42
2

A recently proposed Vim patch adds a text object for arbitrary matched pairs:

https://groups.google.com/d/topic/vim_dev/pZxLAAXxk0M/discussion

Ben
  • 7,861
  • 1
  • 22
  • 43