aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pager.h
blob: 7694398f4a17008dc5b3ce10b522c188e877f2a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Pager support.
#ifndef FISH_PAGER_H
#define FISH_PAGER_H

#include <stdbool.h>
#include <stddef.h>
#include <memory>
#include <string>
#include <vector>

#include "common.h"
#include "complete.h"
#include "reader.h"
#include "screen.h"

#define PAGER_SELECTION_NONE ((size_t)(-1))

/// Represents rendering from the pager.
class page_rendering_t {
   public:
    int term_width;
    int term_height;
    size_t rows;
    size_t cols;
    size_t row_start;
    size_t row_end;
    size_t selected_completion_idx;
    screen_data_t screen_data;

    size_t remaining_to_disclose;

    bool search_field_shown;
    editable_line_t search_field_line;

    // Returns a rendering with invalid data, useful to indicate "no rendering".
    page_rendering_t();
};

// 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

typedef std::vector<completion_t> completion_list_t;
page_rendering_t render_completions(const completion_list_t &raw_completions,
                                    const wcstring &prefix);

class pager_t {
    int available_term_width;
    int available_term_height;

    size_t selected_completion_idx;
    size_t suggested_row_start;

    // Fully disclosed means that we show all completions.
    bool fully_disclosed;

    // Whether we show the search field.
    bool search_field_shown;

    // 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 completin strings this entry applies to.
        wcstring_list_t comp;
        /// The description.
        wcstring desc;
        /// The representative completion.
        completion_t representative;
        /// On-screen width of the completion string.
        int comp_width;
        /// On-screen width of the description information.
        int desc_width;
        /// Preferred total width.
        int pref_width;
        /// Minimum acceptable width.
        int min_width;

        comp_t()
            : comp(),
              desc(),
              representative(L""),
              comp_width(0),
              desc_width(0),
              pref_width(0),
              min_width(0) {}
    };

   private:
    typedef std::vector<comp_t> comp_info_list_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, int *width_per_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,
                                 int 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 &comp);

    // Sets the prefix.
    void set_prefix(const wcstring &pref);

    // Sets the terminal width and height.
    void set_term_size(int w, int h);

    // 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,
                                             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;

    // Updates the rendering if it's stale.
    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;

    // Constructor
    pager_t();
};

#endif