Fix pager backwards movement on half-filled last column

If the completion pager renders as

	foo1 bar1 baz1 qux1
	foo2 bar2 baz2
	foo3 bar3 baz3

and we go backwards from "foo1" (using left arrow), we'll end up at "baz3",
not "qux1". Pretty smart!

If however we go backwards once more, nothing happens.

The root cause is that there are two different kinds of selection indices:
the one before rendering (9/qux1) and the one after we cleverly subtract
the half-filled last column (8/baz3). The backwards movement ends up
decrementing the first, so it moves from 9 to 8 and nothing changes in
the rendering.

Fix this by using the selection index that we actually rendered.

There is another caller that relies on the old behavior of using the unrendered
selection index. Make it use a dedicated overload that does not depend on
the rendering.
This commit is contained in:
Johannes Altmanninger 2022-07-24 16:49:12 +02:00
parent 12d4b50d5f
commit bd5610349d
3 changed files with 19 additions and 5 deletions

View File

@ -2539,6 +2539,11 @@ static void test_pager_navigation() {
// East goes back.
{selection_motion_t::east, 0},
{selection_motion_t::west, 15},
{selection_motion_t::west, 11},
{selection_motion_t::east, 15},
{selection_motion_t::east, 0},
// "Next" motion goes down the column.
{selection_motion_t::next, 1},
{selection_motion_t::next, 2},

View File

@ -754,7 +754,7 @@ bool pager_t::select_next_completion_in_direction(selection_motion_t direction,
}
// Ensure our suggested row start is not past the selected row.
size_t row_containing_selection = this->get_selected_row(rendering);
size_t row_containing_selection = this->get_selected_row(rendering.rows);
if (suggested_row_start > row_containing_selection) {
suggested_row_start = row_containing_selection;
}
@ -826,17 +826,24 @@ const completion_t *pager_t::selected_completion(const page_rendering_t &renderi
size_t pager_t::get_selected_row(const page_rendering_t &rendering) const {
if (rendering.rows == 0) return PAGER_SELECTION_NONE;
return selected_completion_idx == PAGER_SELECTION_NONE
return rendering.selected_completion_idx == PAGER_SELECTION_NONE
? PAGER_SELECTION_NONE
: selected_completion_idx % rendering.rows;
: rendering.selected_completion_idx % rendering.rows;
}
size_t pager_t::get_selected_row(size_t rows) const {
if (rows == 0) return PAGER_SELECTION_NONE;
return selected_completion_idx == PAGER_SELECTION_NONE ? PAGER_SELECTION_NONE
: selected_completion_idx % rows;
}
size_t pager_t::get_selected_column(const page_rendering_t &rendering) const {
if (rendering.rows == 0) return PAGER_SELECTION_NONE;
return selected_completion_idx == PAGER_SELECTION_NONE
return rendering.selected_completion_idx == PAGER_SELECTION_NONE
? PAGER_SELECTION_NONE
: selected_completion_idx / rendering.rows;
: rendering.selected_completion_idx / rendering.rows;
}
void pager_t::clear() {

View File

@ -157,6 +157,8 @@ class pager_t {
// Indicates the row and column for the given rendering. Returns -1 if no selection.
size_t get_selected_row(const page_rendering_t &rendering) const;
size_t get_selected_column(const page_rendering_t &rendering) const;
// Indicates the row assuming we render this many rows. Returns -1 if no selection.
size_t get_selected_row(size_t rows) const;
// Produces a rendering of the completions, at the given term size.
page_rendering_t render() const;