Move selection_direction_t to pager.h and make it a class enum

This commit is contained in:
ridiculousfish 2019-04-28 14:06:03 -07:00
parent 3c9f95594a
commit d8ac051f89
5 changed files with 93 additions and 93 deletions

View file

@ -137,24 +137,6 @@ enum {
}; };
typedef unsigned int escape_flags_t; typedef unsigned int escape_flags_t;
// Directions.
enum selection_direction_t {
// Visual directions.
direction_north,
direction_east,
direction_south,
direction_west,
direction_page_north,
direction_page_south,
// Logical directions.
direction_next,
direction_prev,
// Special value that means deselect.
direction_deselect
};
/// Issue a debug message with printf-style string formating and automatic line breaking. The string /// Issue a debug message with printf-style string formating and automatic line breaking. The string
/// will begin with the string \c program_name, followed by a colon and a whitespace. /// will begin with the string \c program_name, followed by a colon and a whitespace.
/// ///

View file

@ -1977,47 +1977,47 @@ static void test_pager_navigation() {
// Here are navigation directions and where we expect the selection to be. // Here are navigation directions and where we expect the selection to be.
const struct { const struct {
selection_direction_t dir; selection_motion_t dir;
size_t sel; size_t sel;
} cmds[] = { } cmds[] = {
// Tab completion to get into the list. // Tab completion to get into the list.
{direction_next, 0}, {selection_motion_t::next, 0},
// Westward motion in upper left goes to the last filled column in the last row. // Westward motion in upper left goes to the last filled column in the last row.
{direction_west, 15}, {selection_motion_t::west, 15},
// East goes back. // East goes back.
{direction_east, 0}, {selection_motion_t::east, 0},
// "Next" motion goes down the column. // "Next" motion goes down the column.
{direction_next, 1}, {selection_motion_t::next, 1},
{direction_next, 2}, {selection_motion_t::next, 2},
{direction_west, 17}, {selection_motion_t::west, 17},
{direction_east, 2}, {selection_motion_t::east, 2},
{direction_east, 6}, {selection_motion_t::east, 6},
{direction_east, 10}, {selection_motion_t::east, 10},
{direction_east, 14}, {selection_motion_t::east, 14},
{direction_east, 18}, {selection_motion_t::east, 18},
{direction_west, 14}, {selection_motion_t::west, 14},
{direction_east, 18}, {selection_motion_t::east, 18},
// Eastward motion wraps back to the upper left, westward goes to the prior column. // Eastward motion wraps back to the upper left, westward goes to the prior column.
{direction_east, 3}, {selection_motion_t::east, 3},
{direction_east, 7}, {selection_motion_t::east, 7},
{direction_east, 11}, {selection_motion_t::east, 11},
{direction_east, 15}, {selection_motion_t::east, 15},
// Pages. // Pages.
{direction_page_north, 12}, {selection_motion_t::page_north, 12},
{direction_page_south, 15}, {selection_motion_t::page_south, 15},
{direction_page_north, 12}, {selection_motion_t::page_north, 12},
{direction_east, 16}, {selection_motion_t::east, 16},
{direction_page_south, 18}, {selection_motion_t::page_south, 18},
{direction_east, 3}, {selection_motion_t::east, 3},
{direction_north, 2}, {selection_motion_t::north, 2},
{direction_page_north, 0}, {selection_motion_t::page_north, 0},
{direction_page_south, 3}, {selection_motion_t::page_south, 3},
}; };
for (size_t i = 0; i < sizeof cmds / sizeof *cmds; i++) { for (size_t i = 0; i < sizeof cmds / sizeof *cmds; i++) {

View file

@ -39,24 +39,24 @@ typedef std::vector<comp_t> comp_info_list_t;
/// Text we use for the search field. /// Text we use for the search field.
#define SEARCH_FIELD_PROMPT _(L"search: ") #define SEARCH_FIELD_PROMPT _(L"search: ")
inline bool selection_direction_is_cardinal(selection_direction_t dir) { inline bool selection_direction_is_cardinal(selection_motion_t dir) {
switch (dir) { switch (dir) {
case direction_north: case selection_motion_t::north:
case direction_east: case selection_motion_t::east:
case direction_south: case selection_motion_t::south:
case direction_west: case selection_motion_t::west:
case direction_page_north: case selection_motion_t::page_north:
case direction_page_south: { case selection_motion_t::page_south: {
return true; return true;
} }
case direction_next: case selection_motion_t::next:
case direction_prev: case selection_motion_t::prev:
case direction_deselect: { case selection_motion_t::deselect: {
return false; return false;
} }
} }
DIE("should never reach this statement"); DIE("unreachable");
} }
/// Returns numer / denom, rounding up. As a "courtesy" 0/0 is 0. /// Returns numer / denom, rounding up. As a "courtesy" 0/0 is 0.
@ -601,7 +601,7 @@ pager_t::pager_t()
bool pager_t::empty() const { return unfiltered_completion_infos.empty(); } bool pager_t::empty() const { return unfiltered_completion_infos.empty(); }
bool pager_t::select_next_completion_in_direction(selection_direction_t direction, bool pager_t::select_next_completion_in_direction(selection_motion_t direction,
const page_rendering_t &rendering) { const page_rendering_t &rendering) {
// Must have something to select. // Must have something to select.
if (this->completion_infos.empty()) { if (this->completion_infos.empty()) {
@ -611,24 +611,24 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
// Handle the case of nothing selected yet. // Handle the case of nothing selected yet.
if (selected_completion_idx == PAGER_SELECTION_NONE) { if (selected_completion_idx == PAGER_SELECTION_NONE) {
switch (direction) { switch (direction) {
case direction_south: case selection_motion_t::south:
case direction_page_south: case selection_motion_t::page_south:
case direction_next: case selection_motion_t::next:
case direction_north: case selection_motion_t::north:
case direction_prev: { case selection_motion_t::prev: {
// These directions do something sane. // These directions do something sane.
if (direction == direction_prev if (direction == selection_motion_t::prev ||
|| direction == direction_north) { direction == selection_motion_t::north) {
selected_completion_idx = completion_infos.size() - 1; selected_completion_idx = completion_infos.size() - 1;
} else { } else {
selected_completion_idx = 0; selected_completion_idx = 0;
} }
return true; return true;
} }
case direction_page_north: case selection_motion_t::page_north:
case direction_east: case selection_motion_t::east:
case direction_west: case selection_motion_t::west:
case direction_deselect: { case selection_motion_t::deselect: {
// These do nothing. // These do nothing.
return false; return false;
} }
@ -639,14 +639,14 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
size_t new_selected_completion_idx; size_t new_selected_completion_idx;
if (!selection_direction_is_cardinal(direction)) { if (!selection_direction_is_cardinal(direction)) {
// Next, previous, or deselect, all easy. // Next, previous, or deselect, all easy.
if (direction == direction_deselect) { if (direction == selection_motion_t::deselect) {
new_selected_completion_idx = PAGER_SELECTION_NONE; new_selected_completion_idx = PAGER_SELECTION_NONE;
} else if (direction == direction_next) { } else if (direction == selection_motion_t::next) {
new_selected_completion_idx = selected_completion_idx + 1; new_selected_completion_idx = selected_completion_idx + 1;
if (new_selected_completion_idx >= completion_infos.size()) { if (new_selected_completion_idx >= completion_infos.size()) {
new_selected_completion_idx = 0; new_selected_completion_idx = 0;
} }
} else if (direction == direction_prev) { } else if (direction == selection_motion_t::prev) {
if (selected_completion_idx == 0) { if (selected_completion_idx == 0) {
new_selected_completion_idx = completion_infos.size() - 1; new_selected_completion_idx = completion_infos.size() - 1;
} else { } else {
@ -662,7 +662,7 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
size_t page_height = std::max(rendering.term_height - 1, (size_t)1); size_t page_height = std::max(rendering.term_height - 1, (size_t)1);
switch (direction) { switch (direction) {
case direction_page_north: { case selection_motion_t::page_north: {
if (current_row > page_height) { if (current_row > page_height) {
current_row = current_row - page_height; current_row = current_row - page_height;
} else { } else {
@ -670,7 +670,7 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
} }
break; break;
} }
case direction_north: { case selection_motion_t::north: {
// Go up a whole row. If we cycle, go to the previous column. // Go up a whole row. If we cycle, go to the previous column.
if (current_row > 0) { if (current_row > 0) {
current_row--; current_row--;
@ -684,7 +684,7 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
} }
break; break;
} }
case direction_page_south: { case selection_motion_t::page_south: {
if (current_row + page_height < rendering.rows) { if (current_row + page_height < rendering.rows) {
current_row += page_height; current_row += page_height;
} else { } else {
@ -695,7 +695,7 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
} }
break; break;
} }
case direction_south: { case selection_motion_t::south: {
// Go down, unless we are in the last row. // Go down, unless we are in the last row.
// If we go over the last element, wrap to the first. // If we go over the last element, wrap to the first.
if (current_row + 1 < rendering.rows && if (current_row + 1 < rendering.rows &&
@ -707,7 +707,7 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
} }
break; break;
} }
case direction_east: { case selection_motion_t::east: {
// Go east, wrapping to the next row. There is no "row memory," so if we run off the // Go east, wrapping to the next row. There is no "row memory," so if we run off the
// end, wrap. // end, wrap.
if (current_col + 1 < rendering.cols && if (current_col + 1 < rendering.cols &&
@ -719,7 +719,7 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
} }
break; break;
} }
case direction_west: { case selection_motion_t::west: {
// Go west, wrapping to the previous row. // Go west, wrapping to the previous row.
if (current_col > 0) { if (current_col > 0) {
current_col--; current_col--;

View file

@ -36,6 +36,23 @@ class page_rendering_t {
page_rendering_t(); page_rendering_t();
}; };
enum class selection_motion_t {
// Visual directions.
north,
east,
south,
west,
page_north,
page_south,
// Logical directions.
next,
prev,
// Special value that means deselect.
deselect
};
// The space between adjacent completions. // The space between adjacent completions.
#define PAGER_SPACER_STRING L" " #define PAGER_SPACER_STRING L" "
#define PAGER_SPACER_STRING_WIDTH 2 #define PAGER_SPACER_STRING_WIDTH 2
@ -136,7 +153,7 @@ class pager_t {
// Changes the selected completion in the given direction according to the layout of the given // Changes the selected completion in the given direction according to the layout of the given
// rendering. Returns true if the selection changed. // rendering. Returns true if the selection changed.
bool select_next_completion_in_direction(selection_direction_t direction, bool select_next_completion_in_direction(selection_motion_t direction,
const page_rendering_t &rendering); const page_rendering_t &rendering);
// Returns the currently selected completion for the given rendering. // Returns the currently selected completion for the given rendering.

View file

@ -447,7 +447,7 @@ class reader_data_t : public std::enable_shared_from_this<reader_data_t> {
void handle_readline_command(readline_cmd_t cmd, readline_loop_state_t &rls); void handle_readline_command(readline_cmd_t cmd, readline_loop_state_t &rls);
void clear_pager(); void clear_pager();
void select_completion_in_direction(enum selection_direction_t dir); void select_completion_in_direction(selection_motion_t dir);
void flash(); void flash();
void mark_repaint_needed() { repaint_needed = true; } void mark_repaint_needed() { repaint_needed = true; }
@ -1410,7 +1410,7 @@ void reader_data_t::clear_pager() {
mark_repaint_needed(); mark_repaint_needed();
} }
void reader_data_t::select_completion_in_direction(enum selection_direction_t dir) { void reader_data_t::select_completion_in_direction(selection_motion_t dir) {
bool selection_changed = pager.select_next_completion_in_direction(dir, current_page_rendering); bool selection_changed = pager.select_next_completion_in_direction(dir, current_page_rendering);
if (selection_changed) { if (selection_changed) {
pager_selection_changed(); pager_selection_changed();
@ -2535,8 +2535,8 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
pager.set_fully_disclosed(true); pager.set_fully_disclosed(true);
reader_repaint_needed(); reader_repaint_needed();
} else { } else {
select_completion_in_direction(c == rl::complete ? direction_next select_completion_in_direction(c == rl::complete ? selection_motion_t::next
: direction_prev); : selection_motion_t::prev);
} }
} else { } else {
// Either the user hit tab only once, or we had no visible completion list. // Either the user hit tab only once, or we had no visible completion list.
@ -2601,7 +2601,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
// Show the search field if requested and if we printed a list of completions. // Show the search field if requested and if we printed a list of completions.
if (c == rl::complete_AND_SEARCH && !rls.comp_empty && !pager.empty()) { if (c == rl::complete_AND_SEARCH && !rls.comp_empty && !pager.empty()) {
pager.set_search_field_shown(true); pager.set_search_field_shown(true);
select_completion_in_direction(direction_next); select_completion_in_direction(selection_motion_t::next);
reader_repaint_needed(); reader_repaint_needed();
} }
} }
@ -2614,7 +2614,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
pager.set_search_field_shown(!sfs); pager.set_search_field_shown(!sfs);
pager.set_fully_disclosed(true); pager.set_fully_disclosed(true);
if (pager.is_search_field_shown() && !is_navigating_pager_contents()) { if (pager.is_search_field_shown() && !is_navigating_pager_contents()) {
select_completion_in_direction(direction_south); select_completion_in_direction(selection_motion_t::south);
} }
reader_repaint_needed(); reader_repaint_needed();
} }
@ -2848,7 +2848,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
case rl::backward_char: { case rl::backward_char: {
editable_line_t *el = active_edit_line(); editable_line_t *el = active_edit_line();
if (is_navigating_pager_contents()) { if (is_navigating_pager_contents()) {
select_completion_in_direction(direction_west); select_completion_in_direction(selection_motion_t::west);
} else if (el->position > 0) { } else if (el->position > 0) {
update_buff_pos(el, el->position - 1); update_buff_pos(el, el->position - 1);
reader_repaint_needed(); reader_repaint_needed();
@ -2858,7 +2858,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
case rl::forward_char: { case rl::forward_char: {
editable_line_t *el = active_edit_line(); editable_line_t *el = active_edit_line();
if (is_navigating_pager_contents()) { if (is_navigating_pager_contents()) {
select_completion_in_direction(direction_east); select_completion_in_direction(selection_motion_t::east);
} else if (el->position < el->size()) { } else if (el->position < el->size()) {
update_buff_pos(el, el->position + 1); update_buff_pos(el, el->position + 1);
reader_repaint_needed(); reader_repaint_needed();
@ -2916,7 +2916,8 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
case rl::end_of_history: { case rl::end_of_history: {
bool up = (c == rl::beginning_of_history); bool up = (c == rl::beginning_of_history);
if (is_navigating_pager_contents()) { if (is_navigating_pager_contents()) {
select_completion_in_direction(up ? direction_page_north : direction_page_south); select_completion_in_direction(up ? selection_motion_t::page_north
: selection_motion_t::page_south);
} else { } else {
if (up) { if (up) {
history_search.go_to_beginning(); history_search.go_to_beginning();
@ -2931,24 +2932,24 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
case rl::down_line: { case rl::down_line: {
if (is_navigating_pager_contents()) { if (is_navigating_pager_contents()) {
// We are already navigating pager contents. // We are already navigating pager contents.
selection_direction_t direction; selection_motion_t direction;
if (c == rl::down_line) { if (c == rl::down_line) {
// Down arrow is always south. // Down arrow is always south.
direction = direction_south; direction = selection_motion_t::south;
} else if (selection_is_at_top()) { } else if (selection_is_at_top()) {
// Up arrow, but we are in the first column and first row. End navigation. // Up arrow, but we are in the first column and first row. End navigation.
direction = direction_deselect; direction = selection_motion_t::deselect;
} else { } else {
// Up arrow, go north. // Up arrow, go north.
direction = direction_north; direction = selection_motion_t::north;
} }
// Now do the selection. // Now do the selection.
select_completion_in_direction(direction); select_completion_in_direction(direction);
} else if (!pager.empty()) { } else if (!pager.empty()) {
// We pressed a direction with a non-empty pager, begin navigation. // We pressed a direction with a non-empty pager, begin navigation.
select_completion_in_direction(c == rl::down_line ? direction_south select_completion_in_direction(c == rl::down_line ? selection_motion_t::south
: direction_north); : selection_motion_t::north);
} else { } else {
// Not navigating the pager contents. // Not navigating the pager contents.
editable_line_t *el = active_edit_line(); editable_line_t *el = active_edit_line();