Show file display position (rather than cursor position) in modeline?

I currently display the percent cursor position in my modeline:

## position of the cursor in the buffer, in percent
declare-option str modeline_pos_percent
declare-option str modeline_modified

set global modelinefmt '%val{cursor_line}:%val{cursor_char_column} {{mode_info}} %opt{filetype} [%val{session}] %sh{test $kak_modified = true && echo M} %opt{modeline_pos_percent}%% {{context_info}}'

hook global WinCreate .* %{
    hook window NormalIdle .* %{ evaluate-commands %sh{
        echo "set window modeline_pos_percent '$(($kak_cursor_line * 100 / $kak_buf_line_count))'"
    } }
}

However, this does not update when I scroll the buffer, as the cursor does not move automatically to be visible in newer version of Kakoune. The percent indicator only updates when I e.g. click with the mouse in the window.

This is a degradation in usability as I can’t tell where I am in the file or how big the file is when scrolling up and down with the mouse wheel.

Is there any way to get the displayed position rather than the cursor position? I looked at the value expansions in “:doc expansions” but none looked appropriate.

The expansion you’re looking for is %val{window_range}. Unfortunately, it represents the window coordinates as of the previous redraw, and may be inaccurate about the next redraw. In addition, it contains uninitialised values before the first redraw, so if you try to use it in a WinCreate or WinDisplay hook, your plugin might think it has a window trillions of lines high, or a negative height (see bug 4975 for details).

It should be fine in NormalIdle, though.

1 Like

Thank you, that helps!

Here’s the code I’ve come up with to extract the needed values and get the percentage value:

hook global WinCreate .* %{
    hook window NormalIdle .* %{ evaluate-commands %sh{
        percent=$(echo $kak_buf_line_count $kak_window_range \
          | perl -wanle \
'my $top = $F[1]; 
my $height = $F[3]; 
my $length = $F[0]; 
print $top >= $length - $height ? 100 : int($top / ($length - $height) * 100);' 
        ) ;
        echo "set window modeline_pos_percent '$percent'"
    } }
}

2 Likes