tags:

views:

410

answers:

4

I'm trying to define a vi 'map' command sequence, that would wrap the current word inside an HTML tag, e.g. the B (bold) tag. The map is defined as follows:

:map K ebi<B><esc>ea</B><esc>

The map starts with the motion "eb" to move to the beginning of the selected word, assuming that the most likely cursor position would be the beginning of the word or in the middle. The problem is, it does not work if the cursor is on the last character of the word - then the following word would be wrapped.

Is there a trick to make this map work reliably for any cursor position with a word?

A: 

Use lb instead.

e moves to the end of the current, or as you found, next word. b moves to the beginning of the current word or previous word if you're on the first character. To prevent moving to the previous word in the case of being on the first character, move one character to the right. Even if you're on the last letter of the word, b will take you to the right position.

So your whole line will be:

:map K lbi<B><esc>ea</B><esc>
Leonard
The 'b' motion will work as long as the cursor is not on the first character of the word - otherwise it would move to the previous word. That's the same dilemma as with the 'e' motion when the cursor is on the last character.
pythonquick
Now with the 'lb' motion it looks much better, very good!
pythonquick
+4  A: 

If this is a one off map, it's fine, but if you want to do more, or do it more often, you're much better off using text-objects with surround.vim

If you use that script, you can do (in normal mode)

ysiwtb>

You have to type that in literally. ys is to tell surround.vim to listen for a text motion. iw selects the word that you're currently on. t tells it you want to surround with a tag. b> tells it which tag you want to use.

Even if you don't want to use surround.vim, you can look into using text-objects (:help text-objects) in your maps. the iw or inner-word text object is what you want here, but I don't quite know how to wrap that up in a map yet.

EDIT: I figured how to use it in a map, here goes...

:map K viwO<Esc>i<b><Esc>lviw<Esc>a</b><Esc>

This will leave the cursor on the closing > of the closing tag. It should work wherever in the word the cursor is initially.

But like I said, surround.vim is preferable.

sykora
Random comment:I use Vim exclusively as an editor, yet I'm always bemused when people write out Vim commands because they look ridiculous. Muscle memory is a harsh mistress.
Flemish Bee Cycle
That is a neat trick. Good recommendation about surround.vim, thanks. +1 for both your and Leonard's solutions.
pythonquick
@flemish-bee-cycle: In this case it's even worse for me, because I don't use the qwerty keyboard layout, so my keybindings are custom. I needed to translate what I did back into the default keybindings so I could paste them here. {|
sykora
+2  A: 

Another way to do it: delete inner word (diw), insert the tags, find the last <, insert the deletion.

:map K diwi<b></b><Esc>F<P

closetag.vim : Functions and mappings to close open HTML/XML tags may be of interest.

fgm
and a slightly shorter version would be as follows::map K ciw<b></b><Esc>F<P
pythonquick
A: 

If you want a more global solution, you can try XPTemplate it can provide you surrounding. Just select your text, type select the good snippet (t_ I think) and type your tag name, but you can add a special template if you prefer.

Moreover, it's a very nice tools to use various languages, as you can see in this video

Raoul Supercopter