fish-shell/src/pager.h
Fabian Homborg b9b84e63bf Revert "Attempt to simplify how completions get presented in the pager"
The pager cleanup missed that the existing token could already include active (as in unescaped) expansions, and just escaped them all.

This means things like `ls ~/<TAB>` would escape the `~`, which is obviously wrong and makes it awkward to use.

This reverts commit b38a23a46d.

I fully expect that we'll try again, but there's no use in keeping master broken while that happens.

Fixes #7526.
2020-12-04 16:44:48 +01:00

198 lines
6.1 KiB
C++

// Pager support.
#ifndef FISH_PAGER_H
#define FISH_PAGER_H
#include <stddef.h>
#include <memory>
#include <string>
#include <vector>
#include "common.h"
#include "complete.h"
#include "reader.h"
#include "screen.h"
#include "termsize.h"
#define PAGER_SELECTION_NONE static_cast<size_t>(-1)
/// Represents rendering from the pager.
class page_rendering_t {
public:
size_t term_width{size_t(-1)};
size_t term_height{size_t(-1)};
size_t rows{0};
size_t cols{0};
size_t row_start{0};
size_t row_end{0};
size_t selected_completion_idx{size_t(-1)};
screen_data_t screen_data{};
size_t remaining_to_disclose{0};
bool search_field_shown{false};
editable_line_t search_field_line{};
// Returns a rendering with invalid data, useful to indicate "no rendering".
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
// How many rows we will show in the "initial" pager.
#define PAGER_UNDISCLOSED_MAX_ROWS 4
class pager_t {
size_t available_term_width{0};
size_t available_term_height{0};
size_t selected_completion_idx{PAGER_SELECTION_NONE};
size_t suggested_row_start{0};
// Fully disclosed means that we show all completions.
bool fully_disclosed{false};
// Whether we show the search field.
bool search_field_shown{false};
// 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;
public:
/// Data structure describing one or a group of related completions.
struct comp_t {
/// The list of all completion strings this entry applies to.
wcstring_list_t comp{};
/// The description.
wcstring desc{};
/// The representative completion.
completion_t representative{L""};
/// On-screen width of the completion string.
size_t comp_width{0};
/// On-screen width of the description information.
size_t desc_width{0};
// Our text looks like this:
// completion (description)
// Two spaces separating, plus parens, yields 4 total extra space
// but only if we have a description of course
size_t description_punctuated_width() const {
return this->desc_width + (this->desc_width ? 4 : 0);
}
// Returns the preferred width, containing the sum of the
// width of the completion, separator, description
size_t preferred_width() const {
return this->comp_width + this->description_punctuated_width();
}
};
private:
using comp_info_list_t = std::vector<comp_t>;
// The filtered list of completion infos.
comp_info_list_t completion_infos;
// The unfiltered list. Note there's a lot of duplication here.
comp_info_list_t unfiltered_completion_infos;
wcstring prefix;
bool completion_try_print(size_t cols, const wcstring &prefix, const comp_info_list_t &lst,
page_rendering_t *rendering, size_t suggested_start_row) const;
void recalc_min_widths(comp_info_list_t *lst) const;
void measure_completion_infos(std::vector<comp_t> *infos, const wcstring &prefix) const;
bool completion_info_passes_filter(const comp_t &info) const;
void completion_print(size_t cols, const size_t *width_by_column, size_t row_start,
size_t 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,
size_t width, bool secondary, bool selected,
page_rendering_t *rendering) const;
public:
// The text of the search field.
editable_line_t search_field_line;
// Sets the set of completions.
void set_completions(const completion_list_t &raw_completions);
// Sets the prefix.
void set_prefix(const wcstring &pref);
// Sets the terminal size.
void set_term_size(termsize_t ts);
// 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_motion_t direction,
const page_rendering_t &rendering);
// Returns the currently selected completion for the given rendering.
const completion_t *selected_completion(const page_rendering_t &rendering) const;
// Indicates the row and column for the given rendering. Returns -1 if no selection.
size_t get_selected_row(const page_rendering_t &rendering) const;
size_t get_selected_column(const page_rendering_t &rendering) const;
// Produces a rendering of the completions, at the given term size.
page_rendering_t render() const;
// \return true if the given rendering needs to be updated.
bool rendering_needs_update(const page_rendering_t &rendering) const;
// Updates the rendering.
void update_rendering(page_rendering_t *rendering) const;
// Indicates if there are no completions, and therefore nothing to render.
bool empty() const;
// Clears all completions and the prefix.
void clear();
// Updates the completions list per the filter.
void refilter_completions();
// Sets whether the search field is shown.
void set_search_field_shown(bool flag);
// Gets whether the search field shown.
bool is_search_field_shown() const;
// Indicates if we are navigating our contents.
bool is_navigating_contents() const;
// Become fully disclosed.
void set_fully_disclosed(bool flag);
// Position of the cursor.
size_t cursor_position() const;
pager_t();
~pager_t();
};
#endif