Skip to content

Commit 1694119

Browse files
committed
[overlay] tweak the File: line
1 parent b94ffdb commit 1694119

19 files changed

Lines changed: 206 additions & 72 deletions

NEWS.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,17 @@ Features:
3838
BACKSPACE and DELETE.
3939
- `CTRL-t` transposes the two characters before
4040
the cursor.
41+
* In the log message details (opened by pressing `p`),
42+
a `File:` row has been added that lists the file and
43+
line number the log message is from. Also, for JSON
44+
logs, you can focus on the `JSON fields:` row and
45+
press `c` to copy the raw log message to the
46+
clipboard.
4147
* The `measure_with_units` collator now recognizes
4248
(KiB, MiB, ...).
49+
* Added `disfavors` to `external-editor` configuration
50+
to express file names that the editor is not interested
51+
in handling.
4352

4453
Breaking changes:
4554
* The `humanize_file_size()` SQLite function now

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ however, they do not understand log messages. Tail can watch
4747
multiple files at a time, but it won't display messages in order by
4848
time and you can't scroll backwards. Grep will only find matching
4949
lines, but won't return a full multi-line log message. Less can only
50-
display a single file at a time. Also, none of these basic tools
50+
display a single file at a time. Also, none of these basic tools
5151
handle compressed files.
5252

5353
## Try online before installing
@@ -59,7 +59,7 @@ an example:
5959

6060
[`$ ssh playground@demo.lnav.org`](ssh://playground@demo.lnav.org)
6161

62-
The "tutorial 1" account is an interactive tutorial that can teach
62+
The "tutorial 1" account is an interactive tutorial that can teach
6363
you the basics of operation:
6464

6565
[`$ ssh tutorial1@demo.lnav.org`](ssh://tutorial1@demo.lnav.org)
@@ -89,17 +89,17 @@ monitor, it will figure out the rest:
8989
$ lnav /path/to/file1 /path/to/dir ...
9090
```
9191

92-
The **lnav** TUI will pop up right away and begin indexing the
93-
files. Progress is displayed in the "Files" panel at the
94-
bottom. Once the indexing has finished, the LOG view will display
95-
the log messages that were recognized[^1]. You can then use the
92+
The **lnav** TUI will pop up right away and begin indexing the
93+
files. Progress is displayed in the "Files" panel at the
94+
bottom. Once the indexing has finished, the LOG view will display
95+
the log messages that were recognized[^1]. You can then use the
9696
usual hotkeys to move around the view (arrow keys or
9797
`j`/`k`/`h`/`l` to move down/up/left/right).
9898

9999
See the [Usage section](https://docs.lnav.org/en/latest/usage.html)
100100
of the online documentation for more information.
101101

102-
[^1]: Files that do not contain log messages can be seen in the
102+
[^1]: Files that do not contain log messages can be seen in the
103103
TEXT view (reachable by pressing `t`).
104104

105105
### Usage with `systemd-journald`

docs/schemas/config-v1.schema.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,15 @@
325325
},
326326
"prefers": {
327327
"title": "/tuning/external-editor/impls/<editor_impl_name>/prefers",
328+
"description": "Regular expression that matches file names preferred by this editor",
329+
"type": "string",
330+
"examples": [
331+
"^.*(?:\\.cpp)$"
332+
]
333+
},
334+
"disfavors": {
335+
"title": "/tuning/external-editor/impls/<editor_impl_name>/disfavors",
336+
"description": "Regular expression that matches file names not favored by this editor",
328337
"type": "string",
329338
"examples": [
330339
"^.*(?:\\.cpp)$"

src/column_namer.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,13 @@ column_namer::add_column(const string_fragment& in_name)
110110

111111
fmt::format_to(
112112
std::back_inserter(buf), FMT_STRING("{}_{}"), base_name, num);
113+
#if 0
113114
log_trace("column name already exists (%.*s), trying (%.*s)",
114115
retval.length(),
115116
retval.data(),
116117
(int) buf.size(),
117118
buf.data());
119+
#endif
118120
retval = string_fragment::from_memory_buffer(buf);
119121
num += 1;
120122
}

src/external_editor.cc

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ get_config_dir_mtime(const std::filesystem::path& path,
8080
return retval;
8181
}
8282

83-
for (const auto& sib : std::filesystem::directory_iterator(parent)) {
83+
for (const auto& sib : std::filesystem::directory_iterator(parent, ec))
84+
{
8485
if (!sib.is_directory()) {
8586
continue;
8687
}
@@ -110,7 +111,7 @@ static std::optional<std::string>
110111
get_impl(const std::filesystem::path& path)
111112
{
112113
const auto& cfg = injector::get<const config&>();
113-
std::vector<std::tuple<time64_t, bool, const impl*>> candidates;
114+
std::vector<std::tuple<time64_t, bool, bool, const impl*>> candidates;
114115

115116
log_debug("editor impl count: %zu", cfg.c_impls.size());
116117
for (const auto& [name, impl] : cfg.c_impls) {
@@ -127,25 +128,60 @@ get_impl(const std::filesystem::path& path)
127128
.ignore_error()
128129
.has_value()
129130
: false;
131+
auto disfavors = impl.i_disfavors.pp_value
132+
? impl.i_disfavors.pp_value->find_in(path.string())
133+
.ignore_error()
134+
.has_value()
135+
: false;
136+
auto config_dir_mtime
137+
= get_config_dir_mtime(path, impl.i_config_dir);
138+
log_info(" config-dir-mtime: %llu, prefers: %s, disfavors: %s",
139+
config_dir_mtime,
140+
prefers ? "yes" : "no",
141+
disfavors ? "yes" : "no");
130142
candidates.emplace_back(
131-
get_config_dir_mtime(path, impl.i_config_dir), prefers, &impl);
143+
config_dir_mtime, prefers, disfavors, &impl);
132144
}
133145
}
134146

135147
std::sort(candidates.begin(),
136148
candidates.end(),
137149
[](const auto& lhs, const auto& rhs) {
138-
const auto& [lmtime, lprefers, limpl] = lhs;
139-
const auto& [rmtime, rprefers, rimpl] = rhs;
150+
const auto& [lmtime, lprefers, ldisfavors, limpl] = lhs;
151+
const auto& [rmtime, rprefers, rdisfavors, rimpl] = rhs;
152+
153+
if (lmtime > rmtime) {
154+
return true;
155+
}
156+
157+
if (lmtime < rmtime) {
158+
return false;
159+
}
160+
161+
if (lprefers && !rprefers) {
162+
return true;
163+
}
164+
165+
if (!lprefers && rprefers) {
166+
return false;
167+
}
168+
169+
if (ldisfavors && !rdisfavors) {
170+
return false;
171+
}
172+
173+
if (!ldisfavors && rdisfavors) {
174+
return true;
175+
}
140176

141-
return lmtime > rmtime || (lmtime == rmtime && lprefers);
177+
return limpl->i_command < rimpl->i_command;
142178
});
143179

144180
if (candidates.empty()) {
145181
return std::nullopt;
146182
}
147183

148-
return std::get<2>(candidates.front())->i_command;
184+
return std::get<3>(candidates.front())->i_command;
149185
}
150186

151187
Result<void, std::string>

src/external_editor.cfg.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct impl {
4646
std::string i_command;
4747
std::filesystem::path i_config_dir;
4848
factory_container<lnav::pcre2pp::code> i_prefers;
49+
factory_container<lnav::pcre2pp::code> i_disfavors;
4950
};
5051

5152
struct config {

src/field_overlay_source.cc

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -325,15 +325,31 @@ field_overlay_source::build_field_lines(const listview_curses& lv,
325325
}
326326

327327
{
328-
const auto& filename
329-
= this->fos_log_helper.ldh_file->get_filename_as_string();
330-
auto file_al = attr_line_t(" ")
331-
.append("File:"_h2)
332-
.pad_to(15)
333-
.append(lnav::roles::file(filename));
334-
335-
this->fos_row_to_field_meta.emplace(this->fos_lines.size(),
336-
row_info{std::nullopt, filename});
328+
const auto& actual_path
329+
= this->fos_log_helper.ldh_file->get_actual_path();
330+
const auto& filename = actual_path
331+
? actual_path->string()
332+
: this->fos_log_helper.ldh_file->get_filename_as_string();
333+
auto file_line_number
334+
= fmt::to_string(this->fos_log_helper.ldh_file->get_line_number(
335+
this->fos_log_helper.ldh_line));
336+
auto file_link
337+
= attr_line_t()
338+
.append(lnav::roles::file(filename))
339+
.append(":")
340+
.append(lnav::roles::number(file_line_number))
341+
.with_attr_for_all(VC_ROLE.value(role_t::VCR_HYPERLINK))
342+
.with_attr_for_all(VC_HYPERLINK.value(
343+
fmt::format(FMT_STRING("file://{}#L{}"),
344+
filename,
345+
file_line_number)));
346+
auto file_al
347+
= attr_line_t(" ").append("File:"_h2).pad_to(15).append(file_link);
348+
349+
auto file_line_pair
350+
= fmt::format(FMT_STRING("{}:{}"), filename, file_line_number);
351+
this->fos_row_to_field_meta.emplace(
352+
this->fos_lines.size(), row_info{std::nullopt, file_line_pair});
337353
this->fos_lines.emplace_back(file_al);
338354
}
339355

@@ -558,7 +574,19 @@ field_overlay_source::build_field_lines(const listview_curses& lv,
558574
if (!this->fos_log_helper.ldh_extra_json.empty()
559575
|| !this->fos_log_helper.ldh_json_pairs.empty())
560576
{
561-
this->fos_lines.emplace_back(" JSON fields:");
577+
auto read_res = this->fos_log_helper.ldh_file->read_raw_message(
578+
this->fos_log_helper.ldh_line);
579+
if (read_res.isOk()) {
580+
auto sbr = read_res.unwrap();
581+
this->fos_row_to_field_meta.emplace(this->fos_lines.size(),
582+
row_info{
583+
std::nullopt,
584+
to_string(sbr),
585+
});
586+
}
587+
this->fos_lines.emplace_back(
588+
attr_line_t(" JSON fields: ")
589+
.append("(press 'c' to copy raw JSON log message)"_comment));
562590
}
563591

564592
for (const auto& extra_pair : this->fos_log_helper.ldh_extra_json) {

src/lnav_config.cc

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,7 +1134,8 @@ static const struct json_path_container theme_status_styles_handlers = {
11341134
.for_child(&lnav_theme::lt_style_status_title)
11351135
.with_children(style_config_handlers),
11361136
yajlpp::property_handler("alert-title")
1137-
.with_description("Styling for title sections of status bars with alerts")
1137+
.with_description(
1138+
"Styling for title sections of status bars with alerts")
11381139
.for_child(&lnav_theme::lt_style_status_alert_title)
11391140
.with_children(style_config_handlers),
11401141
yajlpp::property_handler("disabled-title")
@@ -1664,9 +1665,15 @@ static const json_path_container editor_impl_handlers = {
16641665
.with_example(".idea"_frag)
16651666
.for_field(&lnav::external_editor::impl::i_config_dir),
16661667
yajlpp::property_handler("prefers")
1667-
.with_description("")
1668+
.with_description("Regular expression that matches file names "
1669+
"preferred by this editor")
16681670
.with_example("^.*(?:\\.cpp)$"_frag)
16691671
.for_field(&lnav::external_editor::impl::i_prefers),
1672+
yajlpp::property_handler("disfavors")
1673+
.with_description("Regular expression that matches file names not "
1674+
"favored by this editor")
1675+
.with_example("^.*(?:\\.cpp)$"_frag)
1676+
.for_field(&lnav::external_editor::impl::i_disfavors),
16701677
};
16711678

16721679
static const json_path_container editor_impls_handlers = {

src/logfile.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,6 +2111,24 @@ logfile::read_range(const file_range& fr)
21112111
return this->lf_line_buffer.read_range(fr);
21122112
}
21132113

2114+
size_t
2115+
logfile::get_line_number(const_iterator ll) const
2116+
{
2117+
size_t retval = 1;
2118+
2119+
if (this->lf_format != nullptr && this->lf_format->lf_formatted_lines) {
2120+
for (auto iter = this->begin(); iter != ll; ++iter) {
2121+
if (iter->get_sub_offset() == 0) {
2122+
retval += 1;
2123+
}
2124+
}
2125+
} else {
2126+
retval += std::distance(this->begin(), ll);
2127+
}
2128+
2129+
return retval;
2130+
}
2131+
21142132
void
21152133
logfile::read_full_message(const_iterator ll,
21162134
shared_buffer_ref& msg_out,

src/logfile.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,8 @@ public:
357357
return ll->get_offset() + (this->lf_line_buffer.is_piper() ? 22 : 0);
358358
}
359359

360+
size_t get_line_number(const_iterator ll) const;
361+
360362
void read_full_message(const_iterator ll,
361363
shared_buffer_ref& msg_out,
362364
line_buffer::scan_direction dir

0 commit comments

Comments
 (0)