• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tstack / lnav / 20114321350-2741

10 Dec 2025 09:41PM UTC coverage: 68.836% (-0.07%) from 68.908%
20114321350-2741

push

github

tstack
[filters] add level filter

41 of 135 new or added lines in 10 files covered. (30.37%)

447 existing lines in 8 files now uncovered.

51534 of 74865 relevant lines covered (68.84%)

434761.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

25.0
/src/filter_sub_source.hh
1
/**
2
 * Copyright (c) 2018, Timothy Stack
3
 *
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 * * Redistributions of source code must retain the above copyright notice, this
10
 * list of conditions and the following disclaimer.
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 * this list of conditions and the following disclaimer in the documentation
13
 * and/or other materials provided with the distribution.
14
 * * Neither the name of Timothy Stack nor the names of its contributors
15
 * may be used to endorse or promote products derived from this software
16
 * without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
19
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
22
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29

30
#ifndef filter_sub_source_hh
31
#define filter_sub_source_hh
32

33
#include <memory>
34
#include <optional>
35
#include <string>
36
#include <unordered_set>
37
#include <utility>
38
#include <vector>
39

40
#include "base/attr_line.hh"
41
#include "textinput.history.hh"
42
#include "textinput_curses.hh"
43
#include "textview_curses.hh"
44
#include "view_curses.hh"
45

46
class textinput_curses;
47

48
class filter_sub_source
49
    : public text_sub_source
50
    , public list_input_delegate
51
    , public text_delegate {
52
public:
53
    explicit filter_sub_source(std::shared_ptr<textinput_curses> editor);
54

55
    using injectable
56
        = filter_sub_source(std::shared_ptr<textinput_curses> editor);
57

58
    filter_sub_source(const filter_sub_source&) = delete;
59
    filter_sub_source(filter_sub_source&&) = delete;
60
    filter_sub_source& operator=(const filter_sub_source&) = delete;
61
    filter_sub_source& operator=(filter_sub_source&&) = delete;
62

63
    ~filter_sub_source() override = default;
2✔
64

65
    bool empty() const override { return false; }
×
66

67
    bool list_input_handle_key(listview_curses& lv, const ncinput& ch) override;
68

69
    void list_input_handle_scroll_out(listview_curses& lv) override;
70

71
    void register_view(textview_curses* tc) override;
72

73
    size_t text_line_count() override;
74

75
    size_t text_line_width(textview_curses& curses) override;
76

77
    line_info text_value_for_line(textview_curses& tc,
78
                                  int line,
79
                                  std::string& value_out,
80
                                  line_flags_t flags) override;
81

82
    void text_attrs_for_line(textview_curses& tc,
83
                             int line,
84
                             string_attrs_t& value_out) override;
85

86
    size_t text_size_for_line(textview_curses& tc,
87
                              int line,
88
                              line_flags_t raw) override;
89

90
    bool text_handle_mouse(textview_curses& tc,
91
                           const listview_curses::display_line_content_t&,
92
                           mouse_event& me) override;
93

94
    void rl_blur(textinput_curses& tc);
95

96
    void rl_change(textinput_curses& rc);
97

98
    void rl_history(textinput_curses& tc);
99

100
    enum class completion_request_type_t {
101
        partial,
102
        full,
103
    };
104

105
    void rl_completion_request_int(textinput_curses& tc,
106
                                   completion_request_type_t crt);
107

108
    void rl_completion_request(textinput_curses& tc);
109

110
    void rl_completion(textinput_curses& rc);
111

112
    void rl_perform(textinput_curses& rc);
113

114
    void rl_abort(textinput_curses& rc);
115

116
    struct render_state {
117
        textview_curses* rs_top_view;
118
        bool rs_editing{false};
119
    };
120

121
    struct filter_row {
122
        filter_row() = default;
57✔
123
        virtual ~filter_row() = default;
57✔
124

125
        filter_row(const filter_row&) = delete;
126
        filter_row(filter_row&&) = delete;
127

128
        virtual void value_for(const render_state& rs, attr_line_t& al) = 0;
129
        virtual bool handle_key(textview_curses* top_view, const ncinput& ch)
130
            = 0;
131
        virtual bool prime_text_input(textview_curses* top_view,
132
                                      textinput_curses& ti,
133
                                      filter_sub_source& parent) = 0;
134
        virtual void ti_change(textview_curses* top_view, textinput_curses& rc)
135
            = 0;
136
        virtual void ti_completion_request(textview_curses* top_view,
137
                                           textinput_curses& tc,
138
                                           completion_request_type_t crt) = 0;
139
        virtual void ti_perform(textview_curses* top_view,
140
                                textinput_curses& tc,
141
                                filter_sub_source& parent) = 0;
142
        virtual void ti_abort(textview_curses* top_view,
143
                              textinput_curses& tc,
144
                              filter_sub_source& parent) = 0;
145
    };
146

147
    struct level_filter_row : filter_row {
148
        void value_for(const render_state& rs, attr_line_t& al) override;
149
        bool handle_key(textview_curses* top_view, const ncinput& ch) override;
150
        bool prime_text_input(textview_curses* top_view,
151
                              textinput_curses& ti,
152
                              filter_sub_source& parent) override;
153
        void ti_change(textview_curses* top_view,
154
                       textinput_curses& rc) override;
155
        void ti_completion_request(textview_curses* top_view,
156
                                   textinput_curses& tc,
157
                                   completion_request_type_t crt) override;
158
        void ti_perform(textview_curses* top_view,
159
                        textinput_curses& tc,
160
                        filter_sub_source& parent) override;
161
        void ti_abort(textview_curses* top_view,
162
                      textinput_curses& tc,
163
                      filter_sub_source& parent) override;
164
    };
165

166
    struct time_filter_row : filter_row {
167
        explicit time_filter_row(const timeval& tv) : tfr_time(tv) {}
×
168
        bool prime_text_input(textview_curses* top_view,
169
                              textinput_curses& ti,
170
                              filter_sub_source& parent) override;
171
        void ti_completion_request(textview_curses* top_view,
172
                                   textinput_curses& tc,
173
                                   completion_request_type_t crt) override;
174

175
        Result<timeval, std::string> parse_time(textview_curses* top_view,
176
                                                textinput_curses& tc);
177

178
        timeval tfr_time;
179
    };
180

181
    struct min_time_filter_row : time_filter_row {
182
        explicit min_time_filter_row(const timeval& tv) : time_filter_row(tv) {}
×
183
        bool prime_text_input(textview_curses* top_view,
×
184
                              textinput_curses& ti,
185
                              filter_sub_source& parent) override
186
        {
187
            parent.fss_min_time = this->tfr_time;
×
188
            return time_filter_row::prime_text_input(top_view, ti, parent);
×
189
        }
190
        bool handle_key(textview_curses* top_view, const ncinput& ch) override;
191
        void value_for(const render_state& rs, attr_line_t& al) override;
192
        void ti_change(textview_curses* top_view,
193
                       textinput_curses& rc) override;
194
        void ti_perform(textview_curses* top_view,
195
                        textinput_curses& tc,
196
                        filter_sub_source& parent) override;
197
        void ti_abort(textview_curses* top_view,
198
                      textinput_curses& tc,
199
                      filter_sub_source& parent) override;
200
    };
201

202
    struct max_time_filter_row : time_filter_row {
203
        explicit max_time_filter_row(const timeval& tv) : time_filter_row(tv) {}
×
204
        bool prime_text_input(textview_curses* top_view,
×
205
                              textinput_curses& ti,
206
                              filter_sub_source& parent) override
207
        {
208
            parent.fss_max_time = this->tfr_time;
×
209
            return time_filter_row::prime_text_input(top_view, ti, parent);
×
210
        }
211
        bool handle_key(textview_curses* top_view, const ncinput& ch) override;
212
        void value_for(const render_state& rs, attr_line_t& al) override;
213
        void ti_change(textview_curses* top_view,
214
                       textinput_curses& rc) override;
215
        void ti_perform(textview_curses* top_view,
216
                        textinput_curses& tc,
217
                        filter_sub_source& parent) override;
218
        void ti_abort(textview_curses* top_view,
219
                      textinput_curses& tc,
220
                      filter_sub_source& parent) override;
221
    };
222

223
    struct text_filter_row : filter_row {
224
        explicit text_filter_row(const std::shared_ptr<text_filter>& tf)
57✔
225
            : tfr_filter(tf)
57✔
226
        {
227
        }
57✔
228

229
        void value_for(const render_state& rs, attr_line_t& al) override;
230
        bool handle_key(textview_curses* top_view, const ncinput& ch) override;
231
        bool prime_text_input(textview_curses* top_view,
232
                              textinput_curses& ti,
233
                              filter_sub_source& parent) override;
234
        void ti_change(textview_curses* top_view,
235
                       textinput_curses& rc) override;
236
        void ti_completion_request(textview_curses* top_view,
237
                                   textinput_curses& tc,
238
                                   completion_request_type_t crt) override;
239
        void ti_perform(textview_curses* top_view,
240
                        textinput_curses& tc,
241
                        filter_sub_source& parent) override;
242
        void ti_abort(textview_curses* top_view,
243
                      textinput_curses& tc,
244
                      filter_sub_source& parent) override;
245

246
        std::shared_ptr<text_filter> tfr_filter;
247
    };
248

249
    using row_vector = std::vector<std::unique_ptr<filter_row>>;
250

251
    row_vector rows_for(textview_curses* tc) const;
252

253
    template<typename T>
NEW
254
    std::pair<vis_line_t, std::unique_ptr<filter_row>> find_row(
×
255
        textview_curses* tc)
256
    {
NEW
257
        auto rows = this->rows_for(tc);
×
NEW
258
        auto index = 0_vl;
×
NEW
259
        for (auto& row : rows) {
×
NEW
260
            if (dynamic_cast<T*>(row.get()) != nullptr) {
×
NEW
261
                return {index, std::move(row)};
×
262
            }
NEW
263
            index += 1_vl;
×
264
        }
NEW
265
        ensure(false);
×
266
    }
267

268
    std::shared_ptr<textinput_curses> fss_editor;
269
    lnav::textinput::history fss_regexp_history;
270
    lnav::textinput::history fss_sql_history;
271
    std::unordered_set<std::string> fss_view_text_possibilities;
272
    attr_line_t fss_curr_line;
273
    log_level_t fss_curr_level;
274
    std::optional<timeval> fss_min_time;
275
    std::optional<timeval> fss_max_time;
276

277
    bool fss_editing{false};
278
    bool fss_filter_state{false};
279
};
280

281
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc