mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-03-31 09:01:25 +08:00
Various tweaks and improvements to new pager, including disclosure
feature
This commit is contained in:
parent
ee9a4082b6
commit
7d3f808e4c
@ -362,6 +362,9 @@ rgb_color_t highlight_get_color(highlight_spec_t highlight, bool is_background)
|
|||||||
{
|
{
|
||||||
rgb_color_t result = rgb_color_t::normal();
|
rgb_color_t result = rgb_color_t::normal();
|
||||||
|
|
||||||
|
/* If sloppy_background is set, then we look at the foreground color even if is_background is set */
|
||||||
|
bool treat_as_background = is_background && ! (highlight & highlight_modifier_sloppy_background);
|
||||||
|
|
||||||
/* Get the primary variable */
|
/* Get the primary variable */
|
||||||
size_t idx = highlight_get_primary(highlight);
|
size_t idx = highlight_get_primary(highlight);
|
||||||
if (idx >= VAR_COUNT)
|
if (idx >= VAR_COUNT)
|
||||||
@ -377,9 +380,9 @@ rgb_color_t highlight_get_color(highlight_spec_t highlight, bool is_background)
|
|||||||
val_wstr = env_get_string(highlight_var[0]);
|
val_wstr = env_get_string(highlight_var[0]);
|
||||||
|
|
||||||
if (! val_wstr.missing())
|
if (! val_wstr.missing())
|
||||||
result = parse_color(val_wstr, is_background);
|
result = parse_color(val_wstr, treat_as_background);
|
||||||
|
|
||||||
/* Handle modifiers. Just one for now */
|
/* Handle modifiers. */
|
||||||
if (highlight & highlight_modifier_valid_path)
|
if (highlight & highlight_modifier_valid_path)
|
||||||
{
|
{
|
||||||
env_var_t val2_wstr = env_get_string(L"fish_color_valid_path");
|
env_var_t val2_wstr = env_get_string(L"fish_color_valid_path");
|
||||||
|
@ -40,6 +40,7 @@ enum
|
|||||||
|
|
||||||
/* The following values are modifiers */
|
/* The following values are modifiers */
|
||||||
highlight_modifier_valid_path = 0x100,
|
highlight_modifier_valid_path = 0x100,
|
||||||
|
highlight_modifier_sloppy_background = 0x200, //hackish, indicates that we should treat a foreground color as background, per certain historical behavior
|
||||||
|
|
||||||
/* Very special value */
|
/* Very special value */
|
||||||
highlight_spec_invalid = 0xFFFF
|
highlight_spec_invalid = 0xFFFF
|
||||||
@ -54,7 +55,7 @@ inline highlight_spec_t highlight_get_primary(highlight_spec_t val)
|
|||||||
|
|
||||||
inline highlight_spec_t highlight_make_background(highlight_spec_t val)
|
inline highlight_spec_t highlight_make_background(highlight_spec_t val)
|
||||||
{
|
{
|
||||||
assert(val >> 16 == 0);
|
assert(val >> 16 == 0); //should have nothing in upper bits, otherwise this is already a background
|
||||||
return val << 16;
|
return val << 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
72
pager.cpp
72
pager.cpp
@ -142,8 +142,8 @@ void pager_t::recalc_min_widths(comp_info_list_t * lst) const
|
|||||||
{
|
{
|
||||||
comp_t *c = &lst->at(i);
|
comp_t *c = &lst->at(i);
|
||||||
|
|
||||||
c->min_width = mini(c->desc_width, maxi(0, term_width/3 - 2)) +
|
c->min_width = mini(c->desc_width, maxi(0, available_term_width/3 - 2)) +
|
||||||
mini(c->desc_width, maxi(0, term_width/5 - 4)) +4;
|
mini(c->desc_width, maxi(0, available_term_width/5 - 4)) +4;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -613,8 +613,8 @@ void pager_t::set_term_size(int w, int h)
|
|||||||
{
|
{
|
||||||
assert(w > 0);
|
assert(w > 0);
|
||||||
assert(h > 0);
|
assert(h > 0);
|
||||||
term_width = w;
|
available_term_width = w;
|
||||||
term_height = h;
|
available_term_height = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -653,8 +653,24 @@ int pager_t::completion_try_print(size_t cols, const wcstring &prefix, const com
|
|||||||
*/
|
*/
|
||||||
int print=0;
|
int print=0;
|
||||||
|
|
||||||
|
/* Compute the effective term width and term height, accounting for disclosure */
|
||||||
|
int term_width = this->available_term_width;
|
||||||
|
int term_height = this->available_term_height - 1; // we always subtract 1 to make room for a comment row
|
||||||
|
if (! this->fully_disclosed)
|
||||||
|
term_height = mini(term_height, PAGER_UNDISCLOSED_MAX_ROWS);
|
||||||
|
|
||||||
size_t row_count = divide_round_up(lst.size(), cols);
|
size_t row_count = divide_round_up(lst.size(), cols);
|
||||||
|
|
||||||
|
/* We have more to disclose if we are not fully disclosed and there's more rows than we have in our term height */
|
||||||
|
if (! this->fully_disclosed && row_count > term_height)
|
||||||
|
{
|
||||||
|
rendering->remaining_to_disclose = row_count - term_height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rendering->remaining_to_disclose = 0;
|
||||||
|
}
|
||||||
|
|
||||||
int pref_tot_width=0;
|
int pref_tot_width=0;
|
||||||
int min_tot_width = 0;
|
int min_tot_width = 0;
|
||||||
int res=PAGER_RETRY;
|
int res=PAGER_RETRY;
|
||||||
@ -781,6 +797,26 @@ int pager_t::completion_try_print(size_t cols, const wcstring &prefix, const com
|
|||||||
assert(stop_row <= row_count);
|
assert(stop_row <= row_count);
|
||||||
assert(stop_row - start_row <= term_height);
|
assert(stop_row - start_row <= term_height);
|
||||||
completion_print(cols, width, start_row, stop_row, prefix, lst, rendering);
|
completion_print(cols, width, start_row, stop_row, prefix, lst, rendering);
|
||||||
|
|
||||||
|
/* Add the progress line. It's a "more to disclose" line if necessary. */
|
||||||
|
wcstring progress_text;
|
||||||
|
if (rendering->remaining_to_disclose == 1)
|
||||||
|
{
|
||||||
|
/* I don't expect this case to ever happen */
|
||||||
|
progress_text = L"and 1 more row";
|
||||||
|
}
|
||||||
|
else if (rendering->remaining_to_disclose > 1)
|
||||||
|
{
|
||||||
|
progress_text = format_string(L"and %lu more rows", (unsigned long)rendering->remaining_to_disclose);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The +1 here is because we are zero indexed, but want to present things as 1-indexed. We do not add 1 to stop_row or row_count because these are the "past the last value" */
|
||||||
|
progress_text = format_string(L"rows %lu to %lu of %lu", start_row + 1, stop_row, row_count);
|
||||||
|
}
|
||||||
|
line_t &line = rendering->screen_data.add_line();
|
||||||
|
print_max(progress_text.c_str(), highlight_spec_pager_progress | highlight_make_background(highlight_spec_pager_progress), term_width, true /* has_more */, &line);
|
||||||
|
|
||||||
return PAGER_DONE;
|
return PAGER_DONE;
|
||||||
|
|
||||||
res=PAGER_DONE;
|
res=PAGER_DONE;
|
||||||
@ -905,8 +941,8 @@ page_rendering_t pager_t::render() const
|
|||||||
column never fails.
|
column never fails.
|
||||||
*/
|
*/
|
||||||
page_rendering_t rendering;
|
page_rendering_t rendering;
|
||||||
rendering.term_width = this->term_width;
|
rendering.term_width = this->available_term_width;
|
||||||
rendering.term_height = this->term_height;
|
rendering.term_height = this->available_term_height;
|
||||||
|
|
||||||
if (! this->empty())
|
if (! this->empty())
|
||||||
{
|
{
|
||||||
@ -927,9 +963,8 @@ page_rendering_t pager_t::render() const
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rendering.cols = (size_t)cols;
|
rendering.cols = (size_t)cols;
|
||||||
rendering.rows = divide_round_up(completion_infos.size(), rendering.cols);
|
rendering.rows = min_rows_required_for_cols;
|
||||||
rendering.selected_completion_idx = this->visual_selected_completion_index(rendering.rows, rendering.cols);
|
rendering.selected_completion_idx = this->visual_selected_completion_index(rendering.rows, rendering.cols);
|
||||||
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
@ -962,13 +997,13 @@ page_rendering_t pager_t::render() const
|
|||||||
|
|
||||||
void pager_t::update_rendering(page_rendering_t *rendering) const
|
void pager_t::update_rendering(page_rendering_t *rendering) const
|
||||||
{
|
{
|
||||||
if (rendering->term_width != this->term_width || rendering->term_height != this->term_height || rendering->selected_completion_idx != this->visual_selected_completion_index(rendering->rows, rendering->cols))
|
if (rendering->term_width != this->available_term_width || rendering->term_height != this->available_term_height || rendering->selected_completion_idx != this->visual_selected_completion_index(rendering->rows, rendering->cols))
|
||||||
{
|
{
|
||||||
*rendering = this->render();
|
*rendering = this->render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pager_t::pager_t() : term_width(0), term_height(0), selected_completion_idx(PAGER_SELECTION_NONE), suggested_row_start(0)
|
pager_t::pager_t() : available_term_width(0), available_term_height(0), selected_completion_idx(PAGER_SELECTION_NONE), suggested_row_start(0), fully_disclosed(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1135,6 +1170,7 @@ const completion_t *pager_t::select_next_completion_in_direction(selection_direc
|
|||||||
{
|
{
|
||||||
size_t row_containing_selection = selected_completion_idx % rendering.rows;
|
size_t row_containing_selection = selected_completion_idx % rendering.rows;
|
||||||
|
|
||||||
|
|
||||||
/* Ensure our suggested row start is not past the selected row */
|
/* Ensure our suggested row start is not past the selected row */
|
||||||
if (suggested_row_start > row_containing_selection)
|
if (suggested_row_start > row_containing_selection)
|
||||||
{
|
{
|
||||||
@ -1144,7 +1180,20 @@ const completion_t *pager_t::select_next_completion_in_direction(selection_direc
|
|||||||
/* Ensure our suggested row start is not too early before it */
|
/* Ensure our suggested row start is not too early before it */
|
||||||
if (suggested_row_start + visible_row_count <= row_containing_selection)
|
if (suggested_row_start + visible_row_count <= row_containing_selection)
|
||||||
{
|
{
|
||||||
|
/* The user moved south past the bottom completion */
|
||||||
|
if (! fully_disclosed && rendering.remaining_to_disclose > 0)
|
||||||
|
{
|
||||||
|
/* Perform disclosure */
|
||||||
|
fully_disclosed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Scroll */
|
||||||
suggested_row_start = row_containing_selection - visible_row_count + 1;
|
suggested_row_start = row_containing_selection - visible_row_count + 1;
|
||||||
|
|
||||||
|
/* Ensure fully_disclosed is set. I think we can hit this case if the user resizes the window - we don't want to drop back to the disclosed style */
|
||||||
|
fully_disclosed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1194,8 +1243,9 @@ void pager_t::clear()
|
|||||||
completion_infos.clear();
|
completion_infos.clear();
|
||||||
prefix.clear();
|
prefix.clear();
|
||||||
selected_completion_idx = PAGER_SELECTION_NONE;
|
selected_completion_idx = PAGER_SELECTION_NONE;
|
||||||
|
fully_disclosed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
page_rendering_t::page_rendering_t() : term_width(-1), term_height(-1), rows(0), cols(0), row_start(0), row_end(0), selected_completion_idx(-1)
|
page_rendering_t::page_rendering_t() : term_width(-1), term_height(-1), rows(0), cols(0), row_start(0), row_end(0), selected_completion_idx(-1), remaining_to_disclose(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
12
pager.h
12
pager.h
@ -18,6 +18,8 @@ class page_rendering_t
|
|||||||
size_t selected_completion_idx;
|
size_t selected_completion_idx;
|
||||||
screen_data_t screen_data;
|
screen_data_t screen_data;
|
||||||
|
|
||||||
|
size_t remaining_to_disclose;
|
||||||
|
|
||||||
/* Returns a rendering with invalid data, useful to indicate "no rendering" */
|
/* Returns a rendering with invalid data, useful to indicate "no rendering" */
|
||||||
page_rendering_t();
|
page_rendering_t();
|
||||||
};
|
};
|
||||||
@ -26,19 +28,25 @@ class page_rendering_t
|
|||||||
#define PAGER_SPACER_STRING L" "
|
#define PAGER_SPACER_STRING L" "
|
||||||
#define PAGER_SPACER_STRING_WIDTH 2
|
#define PAGER_SPACER_STRING_WIDTH 2
|
||||||
|
|
||||||
|
/* How many rows we will show in the "initial" pager */
|
||||||
|
#define PAGER_UNDISCLOSED_MAX_ROWS 4
|
||||||
|
|
||||||
typedef std::vector<completion_t> completion_list_t;
|
typedef std::vector<completion_t> completion_list_t;
|
||||||
page_rendering_t render_completions(const completion_list_t &raw_completions, const wcstring &prefix);
|
page_rendering_t render_completions(const completion_list_t &raw_completions, const wcstring &prefix);
|
||||||
|
|
||||||
class pager_t
|
class pager_t
|
||||||
{
|
{
|
||||||
int term_width;
|
int available_term_width;
|
||||||
int term_height;
|
int available_term_height;
|
||||||
|
|
||||||
completion_list_t completions;
|
completion_list_t completions;
|
||||||
|
|
||||||
size_t selected_completion_idx;
|
size_t selected_completion_idx;
|
||||||
size_t suggested_row_start;
|
size_t suggested_row_start;
|
||||||
|
|
||||||
|
/* Fully disclosed means that we show all completions */
|
||||||
|
bool fully_disclosed;
|
||||||
|
|
||||||
/* Returns the index of the completion that should draw selected, using the given number of columns */
|
/* Returns the index of the completion that should draw selected, using the given number of columns */
|
||||||
size_t visual_selected_completion_index(size_t rows, size_t cols) const;
|
size_t visual_selected_completion_index(size_t rows, size_t cols) const;
|
||||||
|
|
||||||
|
@ -546,7 +546,8 @@ static void reader_repaint()
|
|||||||
indents.resize(len);
|
indents.resize(len);
|
||||||
|
|
||||||
// Re-render our completions page if necessary
|
// Re-render our completions page if necessary
|
||||||
data->pager.set_term_size(common_get_width(), 8 /* common_get_height() */);
|
// We set the term size to 1 less than the true term height. This means we will always show the (bottom) line of the prompt.
|
||||||
|
data->pager.set_term_size(maxi(1, common_get_width()), maxi(1, common_get_height() - 1));
|
||||||
data->pager.update_rendering(&data->current_page_rendering);
|
data->pager.update_rendering(&data->current_page_rendering);
|
||||||
|
|
||||||
s_write(&data->screen,
|
s_write(&data->screen,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user