mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-25 20:33:08 +00:00
Clean up pager on exit from interactive read
This commit is contained in:
parent
54689f6087
commit
0627ae82fb
5 changed files with 111 additions and 19 deletions
41
pager.cpp
41
pager.cpp
|
@ -270,7 +270,7 @@ static int print_max(const wcstring &str, highlight_spec_t color, int max, bool
|
|||
/**
|
||||
Print the specified item using at the specified amount of space
|
||||
*/
|
||||
line_t pager_t::completion_print_item(const wcstring &prefix, const comp_t *c, size_t row, size_t column, int width, bool secondary, page_rendering_t *rendering) const
|
||||
line_t pager_t::completion_print_item(const wcstring &prefix, const comp_t *c, size_t row, size_t column, int width, bool secondary, bool selected, page_rendering_t *rendering) const
|
||||
{
|
||||
int comp_width=0, desc_width=0;
|
||||
int written=0;
|
||||
|
@ -302,6 +302,10 @@ line_t pager_t::completion_print_item(const wcstring &prefix, const comp_t *c, s
|
|||
}
|
||||
|
||||
int bg_color = secondary ? highlight_spec_pager_secondary : highlight_spec_normal;
|
||||
if (selected)
|
||||
{
|
||||
bg_color = highlight_spec_search_match;
|
||||
}
|
||||
|
||||
for (size_t i=0; i<c->comp.size(); i++)
|
||||
{
|
||||
|
@ -356,8 +360,6 @@ void pager_t::completion_print(int cols, int *width_per_column, int row_start, i
|
|||
|
||||
size_t rows = (lst.size()-1)/cols+1;
|
||||
|
||||
fprintf(stderr, "prefix: %ls\n", prefix.c_str());
|
||||
|
||||
for (size_t row = row_start; row < row_stop; row++)
|
||||
{
|
||||
for (size_t col = 0; col < cols; col++)
|
||||
|
@ -367,10 +369,12 @@ void pager_t::completion_print(int cols, int *width_per_column, int row_start, i
|
|||
if (lst.size() <= col * rows + row)
|
||||
continue;
|
||||
|
||||
const comp_t *el = &lst.at(col * rows + row);
|
||||
size_t idx = col * rows + row;
|
||||
const comp_t *el = &lst.at(idx);
|
||||
bool is_selected = (idx == this->selected_completion_idx);
|
||||
|
||||
/* Print this completion on its own "line" */
|
||||
line_t line = completion_print_item(prefix, el, row, col, width_per_column[col] - (is_last?0:2), row%2, rendering);
|
||||
line_t line = completion_print_item(prefix, el, row, col, width_per_column[col] - (is_last?0:2), row%2, is_selected, rendering);
|
||||
|
||||
/* If there's more to come, append two spaces */
|
||||
if (col + 1 < cols)
|
||||
|
@ -586,6 +590,11 @@ void pager_t::set_completions(const completion_list_t &raw_completions)
|
|||
measure_completion_infos(&completion_infos, prefix);
|
||||
}
|
||||
|
||||
void pager_t::set_prefix(const wcstring &pref)
|
||||
{
|
||||
prefix = pref;
|
||||
}
|
||||
|
||||
void pager_t::set_term_size(int w, int h)
|
||||
{
|
||||
assert(w > 0);
|
||||
|
@ -882,3 +891,25 @@ page_rendering_t pager_t::render() const
|
|||
}
|
||||
return rendering;
|
||||
}
|
||||
|
||||
pager_t::pager_t() : term_width(0), term_height(0), selected_completion_idx(-1)
|
||||
{
|
||||
}
|
||||
|
||||
bool pager_t::empty() const
|
||||
{
|
||||
return completions.empty();
|
||||
}
|
||||
|
||||
void pager_t::set_selected_completion(size_t idx)
|
||||
{
|
||||
this->selected_completion_idx = idx;
|
||||
}
|
||||
|
||||
|
||||
void pager_t::clear()
|
||||
{
|
||||
completions.clear();
|
||||
completion_infos.clear();
|
||||
prefix.clear();
|
||||
}
|
||||
|
|
31
pager.h
31
pager.h
|
@ -21,6 +21,8 @@ class pager_t
|
|||
|
||||
completion_list_t completions;
|
||||
|
||||
size_t selected_completion_idx;
|
||||
|
||||
/** Data structure describing one or a group of related completions */
|
||||
public:
|
||||
struct comp_t
|
||||
|
@ -52,19 +54,40 @@ class pager_t
|
|||
typedef std::vector<comp_t> comp_info_list_t;
|
||||
comp_info_list_t completion_infos;
|
||||
|
||||
wcstring prefix;
|
||||
|
||||
int completion_try_print(int cols, const wcstring &prefix, const comp_info_list_t &lst, page_rendering_t *rendering) const;
|
||||
|
||||
void recalc_min_widths(comp_info_list_t * lst) const;
|
||||
void measure_completion_infos(std::vector<comp_t> *infos, const wcstring &prefix) const;
|
||||
|
||||
void completion_print(int cols, int *width_per_column, int row_start, int row_stop, const wcstring &prefix, const comp_info_list_t &lst, page_rendering_t *rendering) const;
|
||||
line_t completion_print_item(const wcstring &prefix, const comp_t *c, size_t row, size_t column, int width, bool secondary, page_rendering_t *rendering) const;
|
||||
line_t completion_print_item(const wcstring &prefix, const comp_t *c, size_t row, size_t column, int width, bool secondary, bool selected, page_rendering_t *rendering) const;
|
||||
|
||||
|
||||
public:
|
||||
void set_completions(const completion_list_t &comp);
|
||||
void set_term_size(int w, int h);
|
||||
wcstring prefix;
|
||||
|
||||
/* Sets the set of completions */
|
||||
void set_completions(const completion_list_t &comp);
|
||||
|
||||
/* Sets the prefix */
|
||||
void set_prefix(const wcstring &pref);
|
||||
|
||||
/* Sets the terminal width and height */
|
||||
void set_term_size(int w, int h);
|
||||
|
||||
/* Sets the index of the selected completion */
|
||||
void set_selected_completion(size_t completion_idx);
|
||||
|
||||
/* Produces a rendering of the completions, at the given term size */
|
||||
page_rendering_t render() const;
|
||||
|
||||
/* Indicates if there are no completions, and therefore nothing to render */
|
||||
bool empty() const;
|
||||
|
||||
/* Clears all completions and the prefix */
|
||||
void clear();
|
||||
|
||||
/* Constructor */
|
||||
pager_t();
|
||||
};
|
||||
|
|
25
reader.cpp
25
reader.cpp
|
@ -198,8 +198,11 @@ public:
|
|||
/** String containing the autosuggestion */
|
||||
wcstring autosuggestion;
|
||||
|
||||
/** Current completions */
|
||||
page_rendering_t completion_page_rendering;
|
||||
/** Current pager */
|
||||
pager_t current_pager;
|
||||
|
||||
/** Whether we are navigating the pager */
|
||||
bool is_navigating_pager;
|
||||
|
||||
/** Whether autosuggesting is allowed at all */
|
||||
bool allow_autosuggestion;
|
||||
|
@ -334,6 +337,7 @@ public:
|
|||
|
||||
/** Constructor */
|
||||
reader_data_t() :
|
||||
is_navigating_pager(0),
|
||||
allow_autosuggestion(0),
|
||||
suppress_autosuggestion(0),
|
||||
expand_abbreviations(0),
|
||||
|
@ -543,7 +547,7 @@ static void reader_repaint()
|
|||
&colors[0],
|
||||
&indents[0],
|
||||
data->buff_pos,
|
||||
&data->completion_page_rendering.screen_data);
|
||||
data->current_pager);
|
||||
|
||||
data->repaint_needed = false;
|
||||
}
|
||||
|
@ -1859,9 +1863,9 @@ static bool handle_completions(const std::vector<completion_t> &comp)
|
|||
{
|
||||
pager_t pager;
|
||||
pager.set_term_size(common_get_width(), common_get_height());
|
||||
pager.prefix = prefix;
|
||||
pager.set_prefix(prefix);
|
||||
pager.set_completions(surviving_completions);
|
||||
data->completion_page_rendering = pager.render();
|
||||
data->current_pager = pager;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3143,6 +3147,9 @@ const wchar_t *reader_readline(void)
|
|||
{
|
||||
/* The user typed R_COMPLETE more than once in a row. Cycle through our available completions */
|
||||
const completion_t *next_comp = cycle_competions(comp, cycle_command_line, &completion_cycle_idx);
|
||||
|
||||
data->current_pager.set_selected_completion(completion_cycle_idx);
|
||||
|
||||
if (next_comp != NULL)
|
||||
{
|
||||
size_t cursor_pos = cycle_cursor_pos;
|
||||
|
@ -3815,6 +3822,14 @@ const wchar_t *reader_readline(void)
|
|||
}
|
||||
|
||||
writestr(L"\n");
|
||||
|
||||
/* Ensure we have no pager contents when we exit */
|
||||
if (! data->current_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();
|
||||
}
|
||||
|
||||
if (!reader_exit_forced())
|
||||
{
|
||||
|
|
26
screen.cpp
26
screen.cpp
|
@ -45,6 +45,7 @@ efficient way for transforming that to the desired screen content.
|
|||
#include "highlight.h"
|
||||
#include "screen.h"
|
||||
#include "env.h"
|
||||
#include "pager.h"
|
||||
|
||||
/** The number of characters to indent new blocks */
|
||||
#define INDENT_STEP 4
|
||||
|
@ -1027,7 +1028,7 @@ static void s_update(screen_t *scr, const wchar_t *left_prompt, const wchar_t *r
|
|||
|
||||
if (! output.empty())
|
||||
{
|
||||
write_loop(1, &output.at(0), output.size());
|
||||
write_loop(STDOUT_FILENO, &output.at(0), output.size());
|
||||
}
|
||||
|
||||
/* We have now synced our actual screen against our desired screen. Note that this is a big assignment! */
|
||||
|
@ -1236,7 +1237,7 @@ void s_write(screen_t *s,
|
|||
const highlight_spec_t *colors,
|
||||
const int *indent,
|
||||
size_t cursor_pos,
|
||||
const screen_data_t *pager_data)
|
||||
const pager_t &pager)
|
||||
{
|
||||
screen_data_t::cursor_t cursor_arr;
|
||||
|
||||
|
@ -1325,9 +1326,10 @@ void s_write(screen_t *s,
|
|||
s->desired.cursor = cursor_arr;
|
||||
|
||||
/* append pager_data */
|
||||
if (pager_data != NULL)
|
||||
if (! pager.empty())
|
||||
{
|
||||
s->desired.append_lines(*pager_data);
|
||||
const page_rendering_t rendering = pager.render();
|
||||
s->desired.append_lines(rendering.screen_data);
|
||||
}
|
||||
|
||||
s_update(s, layout.left_prompt.c_str(), layout.right_prompt.c_str());
|
||||
|
@ -1435,6 +1437,22 @@ void s_reset(screen_t *s, screen_reset_mode_t mode)
|
|||
fstat(2, &s->prev_buff_2);
|
||||
}
|
||||
|
||||
bool screen_force_clear_to_end()
|
||||
{
|
||||
bool result = false;
|
||||
if (clr_eos)
|
||||
{
|
||||
data_buffer_t output;
|
||||
s_write_mbs(&output, clr_eos);
|
||||
if (! output.empty())
|
||||
{
|
||||
write_loop(STDOUT_FILENO, &output.at(0), output.size());
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
screen_t::screen_t() :
|
||||
desired(),
|
||||
actual(),
|
||||
|
|
7
screen.h
7
screen.h
|
@ -16,6 +16,8 @@
|
|||
#include <sys/stat.h>
|
||||
#include "highlight.h"
|
||||
|
||||
class pager_t;
|
||||
|
||||
/**
|
||||
A class representing a single line of a screen.
|
||||
*/
|
||||
|
@ -203,7 +205,7 @@ void s_write(screen_t *s,
|
|||
const highlight_spec_t *colors,
|
||||
const int *indent,
|
||||
size_t cursor_pos,
|
||||
const screen_data_t *pager_data);
|
||||
const pager_t &pager_data);
|
||||
|
||||
/**
|
||||
This function resets the screen buffers internal knowledge about
|
||||
|
@ -241,6 +243,9 @@ enum screen_reset_mode_t
|
|||
|
||||
void s_reset(screen_t *s, screen_reset_mode_t mode);
|
||||
|
||||
/* Issues an immediate clr_eos, returning if it existed */
|
||||
bool screen_force_clear_to_end();
|
||||
|
||||
/* Returns the length of an escape code. Exposed for testing purposes only. */
|
||||
size_t escape_code_length(const wchar_t *code);
|
||||
|
||||
|
|
Loading…
Reference in a new issue