mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-23 08:13:08 +08:00
Move selection_direction_t to pager.h and make it a class enum
This commit is contained in:
parent
3c9f95594a
commit
d8ac051f89
18
src/common.h
18
src/common.h
|
@ -137,24 +137,6 @@ enum {
|
|||
};
|
||||
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
|
||||
/// 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.
|
||||
const struct {
|
||||
selection_direction_t dir;
|
||||
selection_motion_t dir;
|
||||
size_t sel;
|
||||
} cmds[] = {
|
||||
// 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.
|
||||
{direction_west, 15},
|
||||
{selection_motion_t::west, 15},
|
||||
// East goes back.
|
||||
{direction_east, 0},
|
||||
{selection_motion_t::east, 0},
|
||||
|
||||
// "Next" motion goes down the column.
|
||||
{direction_next, 1},
|
||||
{direction_next, 2},
|
||||
{selection_motion_t::next, 1},
|
||||
{selection_motion_t::next, 2},
|
||||
|
||||
{direction_west, 17},
|
||||
{direction_east, 2},
|
||||
{direction_east, 6},
|
||||
{direction_east, 10},
|
||||
{direction_east, 14},
|
||||
{direction_east, 18},
|
||||
{selection_motion_t::west, 17},
|
||||
{selection_motion_t::east, 2},
|
||||
{selection_motion_t::east, 6},
|
||||
{selection_motion_t::east, 10},
|
||||
{selection_motion_t::east, 14},
|
||||
{selection_motion_t::east, 18},
|
||||
|
||||
{direction_west, 14},
|
||||
{direction_east, 18},
|
||||
{selection_motion_t::west, 14},
|
||||
{selection_motion_t::east, 18},
|
||||
|
||||
// Eastward motion wraps back to the upper left, westward goes to the prior column.
|
||||
{direction_east, 3},
|
||||
{direction_east, 7},
|
||||
{direction_east, 11},
|
||||
{direction_east, 15},
|
||||
{selection_motion_t::east, 3},
|
||||
{selection_motion_t::east, 7},
|
||||
{selection_motion_t::east, 11},
|
||||
{selection_motion_t::east, 15},
|
||||
|
||||
// Pages.
|
||||
{direction_page_north, 12},
|
||||
{direction_page_south, 15},
|
||||
{direction_page_north, 12},
|
||||
{direction_east, 16},
|
||||
{direction_page_south, 18},
|
||||
{direction_east, 3},
|
||||
{direction_north, 2},
|
||||
{direction_page_north, 0},
|
||||
{direction_page_south, 3},
|
||||
{selection_motion_t::page_north, 12},
|
||||
{selection_motion_t::page_south, 15},
|
||||
{selection_motion_t::page_north, 12},
|
||||
{selection_motion_t::east, 16},
|
||||
{selection_motion_t::page_south, 18},
|
||||
{selection_motion_t::east, 3},
|
||||
{selection_motion_t::north, 2},
|
||||
{selection_motion_t::page_north, 0},
|
||||
{selection_motion_t::page_south, 3},
|
||||
|
||||
};
|
||||
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.
|
||||
#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) {
|
||||
case direction_north:
|
||||
case direction_east:
|
||||
case direction_south:
|
||||
case direction_west:
|
||||
case direction_page_north:
|
||||
case direction_page_south: {
|
||||
case selection_motion_t::north:
|
||||
case selection_motion_t::east:
|
||||
case selection_motion_t::south:
|
||||
case selection_motion_t::west:
|
||||
case selection_motion_t::page_north:
|
||||
case selection_motion_t::page_south: {
|
||||
return true;
|
||||
}
|
||||
case direction_next:
|
||||
case direction_prev:
|
||||
case direction_deselect: {
|
||||
case selection_motion_t::next:
|
||||
case selection_motion_t::prev:
|
||||
case selection_motion_t::deselect: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
DIE("should never reach this statement");
|
||||
DIE("unreachable");
|
||||
}
|
||||
|
||||
/// 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::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) {
|
||||
// Must have something to select.
|
||||
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.
|
||||
if (selected_completion_idx == PAGER_SELECTION_NONE) {
|
||||
switch (direction) {
|
||||
case direction_south:
|
||||
case direction_page_south:
|
||||
case direction_next:
|
||||
case direction_north:
|
||||
case direction_prev: {
|
||||
case selection_motion_t::south:
|
||||
case selection_motion_t::page_south:
|
||||
case selection_motion_t::next:
|
||||
case selection_motion_t::north:
|
||||
case selection_motion_t::prev: {
|
||||
// These directions do something sane.
|
||||
if (direction == direction_prev
|
||||
|| direction == direction_north) {
|
||||
if (direction == selection_motion_t::prev ||
|
||||
direction == selection_motion_t::north) {
|
||||
selected_completion_idx = completion_infos.size() - 1;
|
||||
} else {
|
||||
selected_completion_idx = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case direction_page_north:
|
||||
case direction_east:
|
||||
case direction_west:
|
||||
case direction_deselect: {
|
||||
case selection_motion_t::page_north:
|
||||
case selection_motion_t::east:
|
||||
case selection_motion_t::west:
|
||||
case selection_motion_t::deselect: {
|
||||
// These do nothing.
|
||||
return false;
|
||||
}
|
||||
|
@ -639,14 +639,14 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
|
|||
size_t new_selected_completion_idx;
|
||||
if (!selection_direction_is_cardinal(direction)) {
|
||||
// Next, previous, or deselect, all easy.
|
||||
if (direction == direction_deselect) {
|
||||
if (direction == selection_motion_t::deselect) {
|
||||
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;
|
||||
if (new_selected_completion_idx >= completion_infos.size()) {
|
||||
new_selected_completion_idx = 0;
|
||||
}
|
||||
} else if (direction == direction_prev) {
|
||||
} else if (direction == selection_motion_t::prev) {
|
||||
if (selected_completion_idx == 0) {
|
||||
new_selected_completion_idx = completion_infos.size() - 1;
|
||||
} 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);
|
||||
|
||||
switch (direction) {
|
||||
case direction_page_north: {
|
||||
case selection_motion_t::page_north: {
|
||||
if (current_row > page_height) {
|
||||
current_row = current_row - page_height;
|
||||
} else {
|
||||
|
@ -670,7 +670,7 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
|
|||
}
|
||||
break;
|
||||
}
|
||||
case direction_north: {
|
||||
case selection_motion_t::north: {
|
||||
// Go up a whole row. If we cycle, go to the previous column.
|
||||
if (current_row > 0) {
|
||||
current_row--;
|
||||
|
@ -684,7 +684,7 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
|
|||
}
|
||||
break;
|
||||
}
|
||||
case direction_page_south: {
|
||||
case selection_motion_t::page_south: {
|
||||
if (current_row + page_height < rendering.rows) {
|
||||
current_row += page_height;
|
||||
} else {
|
||||
|
@ -695,7 +695,7 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
|
|||
}
|
||||
break;
|
||||
}
|
||||
case direction_south: {
|
||||
case selection_motion_t::south: {
|
||||
// Go down, unless we are in the last row.
|
||||
// If we go over the last element, wrap to the first.
|
||||
if (current_row + 1 < rendering.rows &&
|
||||
|
@ -707,7 +707,7 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
|
|||
}
|
||||
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
|
||||
// end, wrap.
|
||||
if (current_col + 1 < rendering.cols &&
|
||||
|
@ -719,7 +719,7 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
|
|||
}
|
||||
break;
|
||||
}
|
||||
case direction_west: {
|
||||
case selection_motion_t::west: {
|
||||
// Go west, wrapping to the previous row.
|
||||
if (current_col > 0) {
|
||||
current_col--;
|
||||
|
|
19
src/pager.h
19
src/pager.h
|
@ -36,6 +36,23 @@ class 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.
|
||||
#define PAGER_SPACER_STRING L" "
|
||||
#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
|
||||
// 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);
|
||||
|
||||
// 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 clear_pager();
|
||||
void select_completion_in_direction(enum selection_direction_t dir);
|
||||
void select_completion_in_direction(selection_motion_t dir);
|
||||
void flash();
|
||||
|
||||
void mark_repaint_needed() { repaint_needed = true; }
|
||||
|
@ -1410,7 +1410,7 @@ void reader_data_t::clear_pager() {
|
|||
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);
|
||||
if (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);
|
||||
reader_repaint_needed();
|
||||
} else {
|
||||
select_completion_in_direction(c == rl::complete ? direction_next
|
||||
: direction_prev);
|
||||
select_completion_in_direction(c == rl::complete ? selection_motion_t::next
|
||||
: selection_motion_t::prev);
|
||||
}
|
||||
} else {
|
||||
// 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.
|
||||
if (c == rl::complete_AND_SEARCH && !rls.comp_empty && !pager.empty()) {
|
||||
pager.set_search_field_shown(true);
|
||||
select_completion_in_direction(direction_next);
|
||||
select_completion_in_direction(selection_motion_t::next);
|
||||
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_fully_disclosed(true);
|
||||
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();
|
||||
}
|
||||
|
@ -2848,7 +2848,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
|
|||
case rl::backward_char: {
|
||||
editable_line_t *el = active_edit_line();
|
||||
if (is_navigating_pager_contents()) {
|
||||
select_completion_in_direction(direction_west);
|
||||
select_completion_in_direction(selection_motion_t::west);
|
||||
} else if (el->position > 0) {
|
||||
update_buff_pos(el, el->position - 1);
|
||||
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: {
|
||||
editable_line_t *el = active_edit_line();
|
||||
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()) {
|
||||
update_buff_pos(el, el->position + 1);
|
||||
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: {
|
||||
bool up = (c == rl::beginning_of_history);
|
||||
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 {
|
||||
if (up) {
|
||||
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: {
|
||||
if (is_navigating_pager_contents()) {
|
||||
// We are already navigating pager contents.
|
||||
selection_direction_t direction;
|
||||
selection_motion_t direction;
|
||||
if (c == rl::down_line) {
|
||||
// Down arrow is always south.
|
||||
direction = direction_south;
|
||||
direction = selection_motion_t::south;
|
||||
} else if (selection_is_at_top()) {
|
||||
// Up arrow, but we are in the first column and first row. End navigation.
|
||||
direction = direction_deselect;
|
||||
direction = selection_motion_t::deselect;
|
||||
} else {
|
||||
// Up arrow, go north.
|
||||
direction = direction_north;
|
||||
direction = selection_motion_t::north;
|
||||
}
|
||||
|
||||
// Now do the selection.
|
||||
select_completion_in_direction(direction);
|
||||
} else if (!pager.empty()) {
|
||||
// We pressed a direction with a non-empty pager, begin navigation.
|
||||
select_completion_in_direction(c == rl::down_line ? direction_south
|
||||
: direction_north);
|
||||
select_completion_in_direction(c == rl::down_line ? selection_motion_t::south
|
||||
: selection_motion_t::north);
|
||||
} else {
|
||||
// Not navigating the pager contents.
|
||||
editable_line_t *el = active_edit_line();
|
||||
|
|
Loading…
Reference in New Issue
Block a user