I find that the live buffer of the window is available in the python interface. This means I can use python to iterate the lines and compute for myself how many times each line wraps over, and then this can be summed to obtain an estimate of what the real working height of the buffer in the window is.
Here's an example of how you'd extricate some of this data from vimscript. I wrote this code here to inspect the data structures available inside vim.windows
:
python << EOF
for win in vim.windows:
print ", ".join([str(x) for x in [win.col, win.row, win.width, win.height]]);
windir = dir(win)
print 'dir: ' + str(windir)
for method in windir:
attr = getattr(win, method)
if method == 'buffer':
print ' buffer: length ' + str(len(attr))
print ' buffer[0]: ' + str(attr[0])
elif method[0] != '_':
print ' ' + method + ': ' + str(attr)
EOF
Some rather annoying things to keep in mind:
- this height i'm talking about depends on the width of the vim window (when wrapping)
- have to correctly deal with tabs and other chars which take up more space. I am unable to think of anything other than the Tab that has these properties (and even if I did use Unicode characters which I rarely do, I'm pretty sure i've never seen any that are supposed to take up more than one column), and with Tab the semantics seem pretty simple, it will take up exactly
&tabstop
columns.
- the width of the window includes the numberline. The numberline's width is dependent on the line count of the buffer, but also at least as wide as
&numberwidth
.
- the width of the window also includes the sign gutter. Luckily this is only ever a width of 0 or 2, right now all i can figure out is we need to use
redir
with sign place [bufnr]
to find out for sure about the presence of this sign column.
- the type of wrapping (
set linebreak
) affects this (Maybe we replicate this wrap-by-word on the python side...)
There may be yet other factors that lead Vim to need more or less space than what we would naively compute in this way. Hopefully linebreak
is one of the few remaining Vim features (maybe, hopefully it's the only one) that affect this. I can confirm that conceal
does not interfere with wrapping offsets.
Obtaining the height this way should be many times more performant than using vimscript techniques, which invariably result in a lot more Vim frontend logic to execute.
gj
in a loop to scan the height. it's very very ugly, but it will not be slow because i will always terminate it within 200 stepsshowbreak
,number
(withrelativenumber
),foldcolumn
(or when using signs).