Now if I select something in visual mode, is there some way to get the selected area without having to yank it to some register?
I looked through
:h functions but didn't find anything.
If you really want to avoid the registers, you can use the visual marks to figure out byte positions of the selected text:
function! s:pos2byte(pos) abort return line2byte(a:pos) + a:pos endfunction function! s:get_visual_text() abort let b1 = s:pos2byte(getpos("'<")) let b2 = s:pos2byte(getpos("'>")) let text = '' while b1 < b2 let l = byte2line(b1) let lb = line2byte(l) let line = strpart(getline(l), b1 - lb - 1) let text .= line let b1 += len(line) endwhile return strpart(text, 0, len(text) - (b1 - b2) + 1) endfunction
It works well enough, but there's something about it that I don't trust. I think it might need more checks to make sure an infinite loops doesn't happen, and it won't work on visual blocks.
I prefer using the temporary register method because I don't have to think too hard about what's going to happen. This is the proper way to do it if you want to leave the buffer state undisturbed:
function! s:get_visual_text() abort " Save the window's view because `gv` may change the scroll position. let view = winsaveview() " Preserve the yank/change marks let m1 = getpos("'[") let m2 = getpos("']") " Preserve the 'a' register, as well as what kind of register it is. let reg_val = getreg('a') let reg_type = getregtype('a') " Yank text into the 'a' register and get the text normal! gv"ay let text = getreg('a') " Restore the 'a' register call setreg('a', reg_val, reg_type) " Restore the yank/change marks call setpos("'[", m1) call setpos("']", m2) " Restore the window's view call winrestview(view) return text endfunction
There is no other way but to yank it into a register. At best, you can restore the register once you're done.
For instance, I have the following utility function that cleans behind itself:
function! lh#visual#selection() try let a_save = @a normal! gv"ay return @a finally let @a = a_save endtry endfunction
(Note I know this question has been asked a few time on SO, but I'm not sure about vi.SE)
There is a way to select the previously selected visual area.
If you have selected some text through
V, or Ctrl+
v, you can reselect the portion by pressing
gv in normal mode. (You can reselect it irrespective of whether you did any operation or cancelled the selection)
Functions accept line range and marks as well. You can use your functions with visual marks like
:'<,'>function(). This will apply the function within the recently selected visual range.
Or, you can select the text through any of the visual modes and cancel selection and then use this in your function by executing
gv inside the function, like