Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I want to do some tricky mappings that wraps currently selected visual area with some code. In order to do that I need to make sure that I am at the beginning of the current visual area. Is there any hotkey for that in visual mode?

share|improve this question
    
You mean like "I" or "0" ? –  ldigas Feb 26 '10 at 21:09
1  
Not a direct answer, but you might consider integrating surround.vim into your solution -- could save lots of effort, since it already provides this functionality. vim.org/scripts/script.php?script_id=1697 –  Jay Feb 27 '10 at 16:13

2 Answers 2

up vote 4 down vote accepted

If I understand correctly, you might be able to use

`<

and

`>

The tricky bit is that they go to the start/end of the previous visual area, not the current one.

So, you could do something like this:

:vmap __ <Esc>`>aEND<Esc>`<iSTART<Esc>l

In my version of Vim, after using that sequence, the last visual area is slightly wonky (re-selecting it with gv selects an area that is not quite right).

To move around in the current visual area a user can use o (and maybe O if using a block area) interactively, but these are not deterministic if you want to use them in a map.

So, I wrote the function below to make a deterministic version of o (defined as _^ and _$ below). The example _* command uses them to do a similar ‘wrapping’ as the above __, but also fakes keeping the visual area selected by re-selecting an area (1v) after doing the wrapping:

:function! MoveToVisualAreaExtrema(wantEnd) range
:  normal gv
:  let l:mode = mode()
:  " only character (v) and line mode (V) work with this implementation
:  if !(l:mode == 'v' || l:mode == 'V')
:    throw 'must be in character- or line-visual mode'
:  endif
:  " get original posision
:  let l:iLn = line('.')
:  let l:iCl = col('.')
:  " move to other end of visual selection
:  normal o
:  " get current position
:  let l:cLn = line('.')
:  let l:cCl = col('.')
:  let l:atEnd = (l:cLn > l:iLn) || (l:cLn == l:iLn) && (l:cCl > l:iCl)
:  if a:wantEnd != l:atEnd
:    normal o
:  endif
:  if l:mode == 'V'
:    execute 'normal ' . (a:wantEnd ? '$' : '0')
:  endif
:endfunction
:vmap _^ :call MoveToVisualAreaExtrema(0)<CR>
:vmap _$ :call MoveToVisualAreaExtrema(1)<CR>

:" Example: wrap ";print q();" around the visual region
:vmap _* _$<Esc>a);<Esc>gv_^<Esc>i;print q(<Esc>l1v
share|improve this answer

Capital H ("Home") will take you to the beginning, and "L" ("Last") to the end.

One bit of behaviour that might cause you trouble is that these put the cursor on the first non-blank character of the line, so type "0" to go to the absolute start of line.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.