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.
Vi and Vim Stack Exchange is a question and answer site for people using the vi and Vim families of text editors. It only takes a minute to sign up.
Sign up to join this communityIf 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[1]) + a:pos[2]
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
, 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 :execute 'gv'
.
to get the selected area without having to yank it to some register
, does it mean finding its position in the buffer with'<
and'>
, re-selecting it visually, or something else? And why? What is your final objective?