Support for correctly resizing pager contents.

This commit is contained in:
ridiculousfish 2014-01-19 23:52:35 -08:00
parent d9d65577f4
commit 998ce1fe89
2 changed files with 42 additions and 47 deletions

View file

@ -937,7 +937,7 @@ void pager_t::update_rendering(page_rendering_t *rendering) const
}
}
pager_t::pager_t() : term_width(0), term_height(0), selected_completion_idx(-1)
pager_t::pager_t() : term_width(0), term_height(0), selected_completion_idx(PAGER_SELECTION_NONE)
{
}
@ -978,7 +978,7 @@ const completion_t *pager_t::select_next_completion_in_direction(selection_direc
if (direction == direction_next)
{
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;
}
@ -1128,6 +1128,7 @@ void pager_t::clear()
completions.clear();
completion_infos.clear();
prefix.clear();
selected_completion_idx = PAGER_SELECTION_NONE;
}
page_rendering_t::page_rendering_t() : term_width(-1), term_height(-1), rows(0), cols(0), selected_completion_idx(-1)

View file

@ -199,7 +199,7 @@ public:
wcstring autosuggestion;
/** Current pager */
pager_t current_pager;
pager_t pager;
/** Current page rendering */
page_rendering_t current_page_rendering;
@ -543,8 +543,8 @@ static void reader_repaint()
indents.resize(len);
// Re-render our completions page if necessary
data->current_pager.set_term_size(common_get_width(), common_get_height());
data->current_pager.update_rendering(&data->current_page_rendering);
data->pager.set_term_size(common_get_width(), common_get_height());
data->pager.update_rendering(&data->current_page_rendering);
s_write(&data->screen,
data->left_prompt_buff,
@ -1527,12 +1527,22 @@ static void accept_autosuggestion(bool full)
static bool is_navigating_pager_contents()
{
return data && data->current_pager.selected_completion(data->current_page_rendering) != NULL;
return data && data->pager.selected_completion(data->current_page_rendering) != NULL;
}
/* Ensure we have no pager contents */
static void clear_pager()
{
if (data)
{
data->pager.clear();
data->current_page_rendering = page_rendering_t();
}
}
static void select_completion_in_direction(enum selection_direction_t dir, const wcstring &cycle_command_line, size_t cycle_cursor_pos)
{
const completion_t *next_comp = data->current_pager.select_next_completion_in_direction(dir, data->current_page_rendering);
const completion_t *next_comp = data->pager.select_next_completion_in_direction(dir, data->current_page_rendering);
if (next_comp != NULL)
{
size_t cursor_pos = cycle_cursor_pos;
@ -1665,40 +1675,6 @@ static void prioritize_completions(std::vector<completion_t> &comp)
sort(comp.begin(), comp.end(), compare_completions_by_match_type);
}
/* Given a list of completions, get the completion at an index past *inout_idx, and then increment it. inout_idx should be initialized to (size_t)(-1) for the first call. */
static const completion_t *cycle_competions(const std::vector<completion_t> &comp, const wcstring &command_line, size_t *inout_idx)
{
const size_t size = comp.size();
if (size == 0)
return NULL;
// note start_idx will be set to -1 initially, so that when it gets incremented we start at 0
const size_t start_idx = *inout_idx;
size_t idx = start_idx;
const completion_t *result = NULL;
size_t remaining = comp.size();
while (remaining--)
{
/* Bump the index */
idx = (idx + 1) % size;
/* Get the completion */
const completion_t &c = comp.at(idx);
/* Try this completion */
if (!(c.flags & COMPLETE_REPLACES_TOKEN) || reader_can_replace(command_line, c.flags))
{
/* Success */
result = &c;
break;
}
}
*inout_idx = idx;
return result;
}
/**
Handle the list of completions. This means the following:
@ -1887,8 +1863,8 @@ static bool handle_completions(const std::vector<completion_t> &comp)
if (1)
{
data->current_pager.set_prefix(prefix);
data->current_pager.set_completions(surviving_completions);
data->pager.set_prefix(prefix);
data->pager.set_completions(surviving_completions);
/* Invalidate our rendering */
data->current_page_rendering = page_rendering_t();
@ -3083,7 +3059,25 @@ const wchar_t *reader_readline(void)
if (last_char != R_YANK && last_char != R_YANK_POP)
yank_len=0;
const wchar_t *buff = data->command_line.c_str();
/* We clear pager contents for most events, except for a few */
switch (c)
{
case R_COMPLETE:
case R_BACKWARD_CHAR:
case R_FORWARD_CHAR:
case R_UP_LINE:
case R_DOWN_LINE:
case R_NULL:
case R_REPAINT:
case R_SUPPRESS_AUTOSUGGESTION:
break;
default:
clear_pager();
break;
}
const wchar_t * const buff = data->command_line.c_str();
switch (c)
{
@ -3170,7 +3164,7 @@ const wchar_t *reader_readline(void)
if (!data->complete_func)
break;
if (! comp_empty && last_char == R_COMPLETE)
if (is_navigating_pager_contents() || (! comp_empty && last_char == R_COMPLETE))
{
/* The user typed R_COMPLETE more than once in a row. Cycle through our available completions. */
select_completion_in_direction(direction_next, cycle_command_line, cycle_cursor_pos);
@ -3852,11 +3846,11 @@ const wchar_t *reader_readline(void)
writestr(L"\n");
/* Ensure we have no pager contents when we exit */
if (! data->current_pager.empty())
if (! data->pager.empty())
{
/* Clear to end of screen to erase the pager contents. TODO: this may fail if eos doesn't exist, in which case we should emit newlines */
screen_force_clear_to_end();
data->current_pager.clear();
data->pager.clear();
}
if (!reader_exit_forced())