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

tstack / lnav / 20281835752-2752

16 Dec 2025 08:31PM UTC coverage: 68.903% (+0.03%) from 68.87%
20281835752-2752

push

github

tstack
[tests] update test data

51677 of 75000 relevant lines covered (68.9%)

434192.37 hits per line

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

91.78
/src/cmds.display.cc
1
/**
2
 * Copyright (c) 2025, 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 "base/intern_string.hh"
31
#include "lnav.hh"
32
#include "readline_context.hh"
33

34
static Result<std::string, lnav::console::user_message>
35
com_set_text_view_mode(exec_context& ec,
4✔
36
                       std::string cmdline,
37
                       std::vector<std::string>& args)
38
{
39
    std::string retval;
4✔
40
    std::optional<textfile_sub_source::view_mode> vm_opt;
4✔
41

42
    if (args.size() > 1) {
4✔
43
        if (args[1] == "raw") {
3✔
44
            vm_opt = textfile_sub_source::view_mode::raw;
2✔
45
        } else if (args[1] == "rendered") {
1✔
46
            vm_opt = textfile_sub_source::view_mode::rendered;
×
47
        }
48
    }
49

50
    if (!vm_opt) {
4✔
51
        return ec.make_error("expecting a view mode of 'raw' or 'rendered'");
2✔
52
    }
53

54
    if (!ec.ec_dry_run) {
2✔
55
        lnav_data.ld_text_source.set_view_mode(vm_opt.value());
2✔
56
    }
57

58
    return Ok(retval);
2✔
59
}
4✔
60

61
static Result<std::string, lnav::console::user_message>
62
com_toggle_field(exec_context& ec,
16✔
63
                 std::string cmdline,
64
                 std::vector<std::string>& args)
65
{
66
    std::string retval;
16✔
67

68
    if (args.size() < 2) {
16✔
69
        return ec.make_error("Expecting a log message field name");
×
70
    }
71
    auto* tc = *lnav_data.ld_view_stack.top();
16✔
72
    const auto hide = args[0] == "hide-fields";
16✔
73
    std::vector<std::string> found_fields, missing_fields;
16✔
74

75
    if (tc != &lnav_data.ld_views[LNV_LOG] && tc != &lnav_data.ld_views[LNV_DB])
16✔
76
    {
77
        retval = "error: hiding fields only works in the log view";
×
78
    } else if (ec.ec_dry_run) {
16✔
79
        // TODO: highlight the fields to be hidden.
80
        retval = "";
×
81
    } else {
82
        if (tc == &lnav_data.ld_views[LNV_DB]) {
16✔
83
            auto& dls = *ec.ec_label_source_stack.back();
2✔
84

85
            for (size_t lpc = 1; lpc < args.size(); lpc++) {
4✔
86
                const auto& name = args[lpc];
2✔
87

88
                auto col_opt = dls.column_name_to_index(name);
2✔
89
                if (col_opt.has_value()) {
2✔
90
                    found_fields.emplace_back(name);
1✔
91

92
                    dls.dls_headers[col_opt.value()].hm_hidden = hide;
1✔
93
                } else {
94
                    missing_fields.emplace_back(name);
1✔
95
                }
96
            }
97
            tc->set_needs_update();
2✔
98
            tc->reload_data();
2✔
99
        } else if (tc == &lnav_data.ld_views[LNV_LOG]) {
14✔
100
            const auto& lss = lnav_data.ld_log_source;
14✔
101

102
            for (int lpc = 1; lpc < (int) args.size(); lpc++) {
30✔
103
                intern_string_t name;
16✔
104
                std::shared_ptr<log_format> format;
16✔
105
                auto sel = tc->get_selection();
16✔
106
                size_t dot;
107

108
                if ((dot = args[lpc].find('.')) != std::string::npos) {
16✔
109
                    const intern_string_t format_name
110
                        = intern_string::lookup(args[lpc].c_str(), dot);
4✔
111

112
                    format = log_format::find_root_format(format_name.get());
4✔
113
                    if (!format) {
4✔
114
                        return ec.make_error("unknown format -- {}",
115
                                             format_name.to_string());
×
116
                    }
117
                    name = intern_string::lookup(&(args[lpc].c_str()[dot + 1]),
4✔
118
                                                 args[lpc].length() - dot - 1);
4✔
119
                } else if (tc->get_inner_height() == 0) {
12✔
120
                    return ec.make_error("no log messages to hide");
×
121
                } else {
122
                    auto cl = lss.at(sel.value_or(0_vl));
12✔
123
                    auto lf = lss.find(cl);
12✔
124
                    format = lf->get_format();
12✔
125
                    name = intern_string::lookup(args[lpc]);
12✔
126
                }
12✔
127

128
                if (format && format->hide_field(name, hide)) {
16✔
129
                    found_fields.push_back(args[lpc]);
15✔
130
                    if (hide) {
131
#if 0
132
                            if (lnav_data.ld_rl_view != nullptr) {
133
                                lnav_data.ld_rl_view->set_alt_value(
134
                                    HELP_MSG_1(x,
135
                                               "to quickly show hidden "
136
                                               "fields"));
137
                            }
138
#endif
139
                    }
140
                    tc->set_needs_update();
15✔
141
                } else {
142
                    missing_fields.push_back(args[lpc]);
1✔
143
                }
144
            }
16✔
145
        }
146
        if (missing_fields.empty()) {
16✔
147
            auto visibility = hide ? "hiding" : "showing";
14✔
148
            retval = fmt::format(FMT_STRING("info: {} field(s) -- {}"),
56✔
149
                                 visibility,
150
                                 fmt::join(found_fields, ", "));
42✔
151
        } else {
152
            return ec.make_error("unknown field(s) -- {}",
153
                                 fmt::join(missing_fields, ", "));
4✔
154
        }
155
    }
156

157
    return Ok(retval);
14✔
158
}
16✔
159

160
static readline_context::command_t DISPLAY_COMMANDS[] = {
161
    {
162
        "set-text-view-mode",
163
        com_set_text_view_mode,
164
        help_text(":set-text-view-mode")
165
            .with_summary("Set the display mode for text files")
166
            .with_parameter(help_text{"mode"}
167
                                .with_summary("The display mode")
168
                                .with_enum_values({
169
                                    "raw"_frag,
170
                                    "rendered"_frag,
171
                                }))
172
            .with_tags({"display"}),
173
    },
174
    {
175
        "hide-fields",
176
        com_toggle_field,
177

178
        help_text(":hide-fields")
179
            .with_summary("Hide log message fields by replacing them "
180
                          "with an ellipsis")
181
            .with_parameter(
182
                help_text("field-name",
183
                          "The name of the field to hide in the format for "
184
                          "the focused log line.  A qualified name can be used "
185
                          "where the field name is prefixed by the format name "
186
                          "and a dot to hide any field.")
187
                    .one_or_more()
188
                    .with_format(help_parameter_format_t::HPF_FORMAT_FIELD))
189
            .with_example({"To hide the log_procname fields in all formats",
190
                           "log_procname"})
191
            .with_example({"To hide only the log_procname field in "
192
                           "the syslog format",
193
                           "syslog_log.log_procname"})
194
            .with_tags({"display"}),
195
    },
196
    {
197
        "show-fields",
198
        com_toggle_field,
199

200
        help_text(":show-fields")
201
            .with_summary("Show log message fields that were previously hidden")
202
            .with_parameter(
203
                help_text("field-name", "The name of the field to show")
204
                    .one_or_more()
205
                    .with_format(help_parameter_format_t::HPF_FORMAT_FIELD))
206
            .with_example({"To show all the log_procname fields in all formats",
207
                           "log_procname"})
208
            .with_opposites({"hide-fields"})
209
            .with_tags({"display"}),
210
    },
211
};
212

213
void
214
init_lnav_display_commands(readline_context::command_map_t& cmd_map)
623✔
215
{
216
    for (auto& cmd : DISPLAY_COMMANDS) {
2,492✔
217
        cmd.c_help.index_tags();
1,869✔
218
        cmd_map[cmd.c_name] = &cmd;
1,869✔
219
    }
220
}
623✔
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