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

tstack / lnav / 11927164159-1768

20 Nov 2024 05:11AM UTC coverage: 70.195% (-0.04%) from 70.233%
11927164159-1768

push

github

tstack
skip parsing really long log messages

3 of 4 new or added lines in 2 files covered. (75.0%)

25 existing lines in 5 files now uncovered.

46296 of 65953 relevant lines covered (70.2%)

467535.34 hits per line

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

86.82
/src/bottom_status_source.cc
1
/**
2
 * Copyright (c) 2019, 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
#include "bottom_status_source.hh"
31

32
#include "base/snippet_highlighters.hh"
33
#include "config.h"
34

35
bottom_status_source::bottom_status_source()
7,147✔
36
{
37
    this->bss_fields[BSF_LINE_NUMBER].set_min_width(10);
1,021✔
38
    this->bss_fields[BSF_LINE_NUMBER].set_share(1000);
1,021✔
39
    this->bss_fields[BSF_PERCENT].set_width(6);
1,021✔
40
    this->bss_fields[BSF_PERCENT].set_left_pad(1);
1,021✔
41
    this->bss_fields[BSF_HITS].set_min_width(10);
1,021✔
42
    this->bss_fields[BSF_HITS].set_share(5);
1,021✔
43
    this->bss_fields[BSF_SEARCH_TERM].set_min_width(10);
1,021✔
44
    this->bss_fields[BSF_SEARCH_TERM].set_share(1);
1,021✔
45
    this->bss_fields[BSF_LOADING].set_width(13);
1,021✔
46
    this->bss_fields[BSF_LOADING].right_justify(true);
1,021✔
47
    this->bss_fields[BSF_HELP].set_width(14);
1,021✔
48
    this->bss_fields[BSF_HELP].set_value("?:View Help");
1,021✔
49
    this->bss_fields[BSF_HELP].right_justify(true);
1,021✔
50
    this->bss_prompt.set_left_pad(1);
1,021✔
51
    this->bss_prompt.set_min_width(35);
1,021✔
52
    this->bss_prompt.set_share(1);
1,021✔
53
    this->bss_error.set_left_pad(1);
1,021✔
54
    this->bss_error.set_min_width(35);
1,021✔
55
    this->bss_error.set_share(1);
1,021✔
56
    this->bss_line_error.set_left_pad(1);
1,021✔
57
    this->bss_line_error.set_min_width(35);
1,021✔
58
    this->bss_line_error.set_share(1);
1,021✔
59
}
1,021✔
60

61
void
62
bottom_status_source::update_line_number(listview_curses* lc)
43✔
63
{
64
    status_field& sf = this->bss_fields[BSF_LINE_NUMBER];
43✔
65

66
    if (lc->get_inner_height() == 0) {
43✔
67
        sf.set_value(" L0");
33✔
68
    } else {
69
        sf.set_value(" L%'d", (int) lc->get_selection());
10✔
70
    }
71

72
    this->bss_line_error.set_value(
43✔
73
        lc->map_top_row([](const attr_line_t& top_row)
43✔
74
                            -> std::optional<std::string> {
75
              const auto& sa = top_row.get_attrs();
10✔
76
              auto error_wrapper = get_string_attr(sa, SA_ERROR);
10✔
77
              if (error_wrapper) {
10✔
78
                  return error_wrapper.value().get();
×
79
              }
80
              return std::nullopt;
10✔
81
          }).value_or(""));
86✔
82
}
43✔
83

84
void
85
bottom_status_source::update_search_term(textview_curses& tc)
12✔
86
{
87
    auto& sf = this->bss_fields[BSF_SEARCH_TERM];
12✔
88
    auto search_term = tc.get_current_search();
12✔
89

90
    sf.clear();
12✔
91
    if (!search_term.empty()) {
12✔
92
        auto search_term_al = attr_line_t(search_term);
×
93

94
        lnav::snippets::regex_highlighter(
×
95
            search_term_al, -1, line_range{0, (int) search_term_al.length()});
×
96
        sf.get_value().append_quoted(search_term_al);
×
97
    }
98

99
    this->bss_paused = tc.is_paused();
12✔
100
    this->update_loading(0, 0);
12✔
101
}
12✔
102

103
void
104
bottom_status_source::update_percent(listview_curses* lc)
43✔
105
{
106
    status_field& sf = this->bss_fields[BSF_PERCENT];
43✔
107
    vis_line_t top = lc->get_top();
43✔
108
    vis_line_t bottom, height;
43✔
109
    unsigned long width;
110
    double percent;
111

112
    lc->get_dimensions(height, width);
43✔
113

114
    if (lc->get_inner_height() > 0) {
43✔
115
        bottom = std::min(top + height - 1_vl, lc->get_inner_height() - 1_vl);
10✔
116
        percent = (double) (bottom + 1);
10✔
117
        percent /= (double) lc->get_inner_height();
10✔
118
        percent *= 100.0;
10✔
119
    } else {
120
        percent = 0.0;
33✔
121
    }
122
    sf.set_value("%3d%% ", (int) percent);
43✔
123
}
43✔
124

125
void
126
bottom_status_source::update_marks(listview_curses* lc)
176✔
127
{
128
    auto* tc = static_cast<textview_curses*>(lc);
176✔
129
    vis_bookmarks& bm = tc->get_bookmarks();
176✔
130
    status_field& sf = this->bss_fields[BSF_HITS];
176✔
131

132
    if (bm.find(&textview_curses::BM_SEARCH) != bm.end()) {
176✔
133
        bookmark_vector<vis_line_t>& bv = bm[&textview_curses::BM_SEARCH];
145✔
134

135
        if (!bv.empty() || !tc->get_current_search().empty()) {
145✔
136
            auto vl = tc->get_selection();
26✔
137
            auto lb = std::lower_bound(bv.begin(), bv.end(), vl);
26✔
138
            if (lb != bv.end() && *lb == vl) {
26✔
139
                sf.set_value("  Hit %'d of %'d for ",
10✔
140
                             std::distance(bv.begin(), lb) + 1,
10✔
141
                             tc->get_match_count());
142
            } else {
143
                sf.set_value("  %'d hits for ", tc->get_match_count());
16✔
144
            }
145
        } else {
146
            sf.clear();
119✔
147
        }
148
    } else {
149
        sf.clear();
31✔
150
    }
151
}
176✔
152

153
void
154
bottom_status_source::update_hits(textview_curses* tc)
133✔
155
{
156
    status_field& sf = this->bss_fields[BSF_HITS];
133✔
157
    role_t new_role;
158

159
    if (tc->is_searching()) {
133✔
160
        this->bss_hit_spinner += 1;
14✔
161
        if (this->bss_hit_spinner % 2) {
14✔
162
            new_role = role_t::VCR_ACTIVE_STATUS;
9✔
163
        } else {
164
            new_role = role_t::VCR_ACTIVE_STATUS2;
5✔
165
        }
166
        sf.set_cylon(true);
14✔
167
    } else {
168
        new_role = role_t::VCR_STATUS;
119✔
169
        sf.set_cylon(false);
119✔
170
    }
171
    // this->bss_error.clear();
172
    sf.set_role(new_role);
133✔
173
    this->update_marks(tc);
133✔
174
}
133✔
175

176
void
177
bottom_status_source::update_loading(file_off_t off, file_ssize_t total)
1,592✔
178
{
179
    auto& sf = this->bss_fields[BSF_LOADING];
1,592✔
180

181
    require(off >= 0);
1,592✔
182
    require(off <= total);
1,592✔
183

184
    if (total == 0) {
1,592✔
185
        sf.set_cylon(false);
1,590✔
186
        sf.set_role(role_t::VCR_STATUS);
1,590✔
187
        if (this->bss_paused) {
1,590✔
188
            sf.set_value("\xE2\x80\x96 Paused");
×
189
        } else {
190
            sf.clear();
1,590✔
191
        }
192
    } else if (off == total) {
2✔
193
        static const std::vector<std::string> DOTS = {
194
            "   ",
195
            ".  ",
196
            ".. ",
197
            "...",
198
            ".. ",
199
            ".  ",
200
        };
201

202
        this->bss_load_percent += 1;
×
203
        sf.set_cylon(true);
×
204
        sf.set_role(role_t::VCR_ACTIVE_STATUS2);
×
205
        sf.set_value(" Working%s  ",
×
206
                     DOTS[this->bss_load_percent % DOTS.size()].c_str());
×
207
    } else {
208
        int pct = (int) (((double) off / (double) total) * 100.0);
2✔
209

210
        if (this->bss_load_percent != pct) {
2✔
UNCOV
211
            this->bss_load_percent = pct;
×
212

UNCOV
213
            sf.set_cylon(true);
×
UNCOV
214
            sf.set_role(role_t::VCR_ACTIVE_STATUS2);
×
UNCOV
215
            sf.set_value(" Loading %2d%% ", pct);
×
216
        }
217
    }
218
}
1,592✔
219

220
size_t
221
bottom_status_source::statusview_fields()
218✔
222
{
223
    size_t retval;
224

225
    if (this->bss_prompt.empty() && this->bss_error.empty()
386✔
226
        && this->bss_line_error.empty())
386✔
227
    {
228
        retval = BSF__MAX;
168✔
229
    } else {
230
        retval = 1;
50✔
231
    }
232

233
    return retval;
218✔
234
}
235

236
status_field&
237
bottom_status_source::statusview_value_for_field(int field)
1,058✔
238
{
239
    if (!this->bss_error.empty()) {
1,058✔
240
        return this->bss_error;
×
241
    }
242
    if (!this->bss_prompt.empty()) {
1,058✔
243
        return this->bss_prompt;
50✔
244
    }
245
    if (!this->bss_line_error.empty()) {
1,008✔
246
        return this->bss_line_error;
×
247
    }
248
    return this->get_field((field_t) field);
1,008✔
249
}
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