After some tinkering, this seemed to be the best available method for finding the bounds of the current screen line, in the absence of other answers. Alas, it does move the cursor, but restores its original position. The function returns a list of the beginning-of-line and end-of-line column indices, like [1, 25]
.
function! DispLineCols()
"display line columns: [bol, eol] columns for current screen line
let r = []
let p = getcurpos()
normal! g0
call add(r, col('.'))
normal! g$
call add(r, col('.'))
call setpos('.', p)
return r
endfunction
I wrote the following function to return a list of lists (in the same [bol, eol] format indicated above) for all screen lines that the current wrapped line comprises. For example, for a wrapped line that comprises three screen lines, this might return: [[1, 79], [80, 159], [160, 180]]
function! DispLinesCols()
"display lines columns: [[bol1, eol1], [bol2, eol2], ...] columns for
" all screen line wraps of current line
let r = []
let p = getcurpos()
normal! 0
call add(r, DispLineCols())
normal! g$l
while col('.') != r[-1][1]
call add(r, DispLineCols())
normal! g$l
endwhile
call setpos('.', p)
return r
endfunction
Not a perfect (or even elegant) solution, but gets the bounds of the display/screen line well enough. Still looking for better solutions...
EDIT: For completeness, here are two functions that will turn the column [bol, eol] output from the functions above into the actual text of the lines.
function! DispLineText()
"display line text: the text on the current screen line
let [beg, end] = DispLineCols()
return getline('.')[beg-1 : end-1]
endfunction
function! DispLinesText()
"display lines text: list of screen lines comprising the current line
let r = []
let l = getline('.')
for [beg, end] in DispLinesCols()
call add(r, l[beg-1 : end-1])
endfor
return r
endfunction