mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 04:43:10 +00:00
Move selection_direction_t to pager.h and make it a class enum
This commit is contained in:
parent
3c9f95594a
commit
d8ac051f89
5 changed files with 93 additions and 93 deletions
18
src/common.h
18
src/common.h
|
@ -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.
|
||||||
///
|
///
|
||||||
|
|
|
@ -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++) {
|
||||||
|
|
|
@ -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--;
|
||||||
|
|
19
src/pager.h
19
src/pager.h
|
@ -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.
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue