10

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?

2
  • You mean like "I" or "0" ?
    – Rook
    Feb 26, 2010 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, 2010 at 16:13

2 Answers 2

10

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
0

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .