[tests] more gantt tests

This commit is contained in:
Tim Stack 2023-08-06 23:26:27 -07:00
parent b791c573e1
commit 98699b318c
22 changed files with 432 additions and 147 deletions

View File

@ -75,7 +75,7 @@ strftime_rfc3339(
return index; return index;
} }
} } // namespace lnav
static time_t BAD_DATE = -1; static time_t BAD_DATE = -1;
@ -225,6 +225,17 @@ secs2tm(lnav::time64_t tim, struct tm* res)
return (res); return (res);
} }
exttm
exttm::from_tv(const timeval& tv)
{
auto retval = exttm{};
retval.et_tm = *gmtime(&tv.tv_sec);
retval.et_nsec = tv.tv_usec * 1000;
return retval;
}
struct timeval struct timeval
exttm::to_timeval() const exttm::to_timeval() const
{ {

View File

@ -104,6 +104,8 @@ enum exttm_flags_t {
}; };
struct exttm { struct exttm {
static exttm from_tv(const timeval& tv);
struct tm et_tm {}; struct tm et_tm {};
int32_t et_nsec{0}; int32_t et_nsec{0};
unsigned int et_flags{0}; unsigned int et_flags{0};

View File

@ -321,6 +321,9 @@ gantt_source::rebuild_indexes()
this->gs_preview_source.clear(); this->gs_preview_source.clear();
this->gs_preview_status_source.get_description().clear(); this->gs_preview_status_source.get_description().clear();
auto min_log_time_opt = this->gs_lss.get_min_log_time();
auto max_log_time_opt = this->gs_lss.get_max_log_time();
auto max_desc_width = size_t{0}; auto max_desc_width = size_t{0};
std::map<string_fragment, opid_row> active_opids; std::map<string_fragment, opid_row> active_opids;
@ -403,6 +406,7 @@ gantt_source::rebuild_indexes()
} }
this->gs_filter_hits = {}; this->gs_filter_hits = {};
for (auto& pair : time_order_map) { for (auto& pair : time_order_map) {
auto& otr = pair.second.or_value;
auto& full_desc = pair.second.or_description; auto& full_desc = pair.second.or_description;
for (auto& desc : pair.second.or_descriptions) { for (auto& desc : pair.second.or_descriptions) {
const auto& format_desc_defs const auto& format_desc_defs
@ -450,6 +454,14 @@ gantt_source::rebuild_indexes()
} }
} }
} }
if (min_log_time_opt && otr.otr_end < min_log_time_opt.value()) {
filtered_out = true;
}
if (max_log_time_opt && max_log_time_opt.value() < otr.otr_begin) {
filtered_out = true;
}
if ((filtered_in_count > 0 && !filtered_in) || filtered_out) { if ((filtered_in_count > 0 && !filtered_in) || filtered_out) {
this->gs_filtered_count += 1; this->gs_filtered_count += 1;
continue; continue;

View File

@ -176,10 +176,13 @@
.. _close: .. _close:
:close :close *path*
^^^^^^ ^^^^^^^^^^^^^
Close the top file in the view Close the given file(s) or the top file in the view
**Parameters**
* **path** --- A path or glob pattern that specifies the files to close
---- ----

View File

@ -2867,18 +2867,48 @@ com_close(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
std::string retval; std::string retval;
if (args.empty()) { if (args.empty()) {
} else { args.emplace_back("loaded-files");
textview_curses* tc = *lnav_data.ld_view_stack.top(); return Ok(retval);
nonstd::optional<ghc::filesystem::path> actual_path; }
std::string fn;
if (tc == &lnav_data.ld_views[LNV_TEXT]) { auto* tc = *lnav_data.ld_view_stack.top();
textfile_sub_source& tss = lnav_data.ld_text_source; std::vector<nonstd::optional<ghc::filesystem::path>> actual_path_v;
std::vector<std::string> fn_v;
if (args.size() > 1) {
auto lexer = shlex(cmdline);
lexer.split(args, ec.create_resolver());
args.erase(args.begin());
for (const auto& lf : lnav_data.ld_active_files.fc_files) {
if (lf.get() == nullptr) {
continue;
}
auto find_iter
= find_if(args.begin(), args.end(), [&lf](const auto& arg) {
return fnmatch(arg.c_str(), lf->get_filename().c_str(), 0)
== 0;
});
if (find_iter == args.end()) {
continue;
}
actual_path_v.push_back(lf->get_actual_path());
fn_v.emplace_back(lf->get_filename());
if (!ec.ec_dry_run) {
lnav_data.ld_active_files.request_close(lf);
}
}
} else if (tc == &lnav_data.ld_views[LNV_TEXT]) {
auto& tss = lnav_data.ld_text_source;
if (tss.empty()) { if (tss.empty()) {
return ec.make_error("no text files are opened"); return ec.make_error("no text files are opened");
} else { } else {
fn = tss.current_file()->get_filename(); fn_v.emplace_back(tss.current_file()->get_filename());
lnav_data.ld_active_files.request_close(tss.current_file()); lnav_data.ld_active_files.request_close(tss.current_file());
if (tss.size() == 1) { if (tss.size() == 1) {
@ -2889,25 +2919,28 @@ com_close(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
if (tc->get_inner_height() == 0) { if (tc->get_inner_height() == 0) {
return ec.make_error("no log files loaded"); return ec.make_error("no log files loaded");
} else { } else {
logfile_sub_source& lss = lnav_data.ld_log_source; auto& lss = lnav_data.ld_log_source;
vis_line_t vl = tc->get_selection(); auto vl = tc->get_selection();
content_line_t cl = lss.at(vl); auto cl = lss.at(vl);
std::shared_ptr<logfile> lf = lss.find(cl); auto lf = lss.find(cl);
actual_path = lf->get_actual_path(); actual_path_v.push_back(lf->get_actual_path());
fn = lf->get_filename(); fn_v.emplace_back(lf->get_filename());
if (!ec.ec_dry_run) { if (!ec.ec_dry_run) {
lnav_data.ld_active_files.request_close(lf); lnav_data.ld_active_files.request_close(lf);
} }
} }
} else { } else {
return ec.make_error( return ec.make_error("close must be run in the log or text file views");
"close must be run in the log or text file views");
} }
if (!fn.empty()) { if (!fn_v.empty()) {
if (ec.ec_dry_run) { if (ec.ec_dry_run) {
retval = ""; retval = "";
} else { } else {
for (size_t lpc = 0; lpc < actual_path_v.size(); lpc++) {
const auto& fn = fn_v[lpc];
const auto& actual_path = actual_path_v[lpc];
if (is_url(fn.c_str())) { if (is_url(fn.c_str())) {
isc::to<curl_looper&, services::curl_streamer_t>().send( isc::to<curl_looper&, services::curl_streamer_t>().send(
[fn](auto& clooper) { clooper.close_request(fn); }); [fn](auto& clooper) { clooper.close_request(fn); });
@ -2917,8 +2950,9 @@ com_close(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
actual_path.value().string()); actual_path.value().string());
} }
lnav_data.ld_active_files.fc_closed_files.insert(fn); lnav_data.ld_active_files.fc_closed_files.insert(fn);
retval = "info: closed -- " + fn;
} }
retval = fmt::format(FMT_STRING("info: closed -- {}"),
fmt::join(fn_v, ", "));
} }
} }
@ -2944,11 +2978,11 @@ com_file_visibility(exec_context& ec,
} }
if (args.size() == 1 || only_this_file) { if (args.size() == 1 || only_this_file) {
textview_curses* tc = *lnav_data.ld_view_stack.top(); auto* tc = *lnav_data.ld_view_stack.top();
std::shared_ptr<logfile> lf; std::shared_ptr<logfile> lf;
if (tc == &lnav_data.ld_views[LNV_TEXT]) { if (tc == &lnav_data.ld_views[LNV_TEXT]) {
textfile_sub_source& tss = lnav_data.ld_text_source; const auto& tss = lnav_data.ld_text_source;
if (tss.empty()) { if (tss.empty()) {
return ec.make_error("no text files are opened"); return ec.make_error("no text files are opened");
@ -2981,6 +3015,7 @@ com_file_visibility(exec_context& ec,
make_visible ? "showing" : "hiding", make_visible ? "showing" : "hiding",
lf->get_filename()); lf->get_filename());
} else { } else {
auto* top_tc = *lnav_data.ld_view_stack.top();
int text_file_count = 0, log_file_count = 0; int text_file_count = 0, log_file_count = 0;
auto lexer = shlex(cmdline); auto lexer = shlex(cmdline);
@ -3023,6 +3058,11 @@ com_file_visibility(exec_context& ec,
lnav_data.ld_views[LNV_LOG] lnav_data.ld_views[LNV_LOG]
.get_sub_source() .get_sub_source()
->text_filters_changed(); ->text_filters_changed();
if (top_tc == &lnav_data.ld_views[LNV_GANTT]) {
lnav_data.ld_views[LNV_GANTT]
.get_sub_source()
->text_filters_changed();
}
} }
if (!ec.ec_dry_run && text_file_count > 0) { if (!ec.ec_dry_run && text_file_count > 0) {
lnav_data.ld_views[LNV_TEXT] lnav_data.ld_views[LNV_TEXT]
@ -3879,9 +3919,9 @@ com_export_session_to(exec_context& ec,
tcsetattr(1, TCSANOW, &curr_termios); tcsetattr(1, TCSANOW, &curr_termios);
setvbuf(stdout, nullptr, _IONBF, 0); setvbuf(stdout, nullptr, _IONBF, 0);
to_term = true; to_term = true;
fprintf( fprintf(outfile,
outfile, "\n---------------- Press any key to exit lo-fi "
"\n---------------- Press any key to exit lo-fi display " "display "
"----------------\n\n"); "----------------\n\n");
} else { } else {
outfile = auto_mem<FILE>::leak(ec_out.value()); outfile = auto_mem<FILE>::leak(ec_out.value());
@ -4039,30 +4079,31 @@ com_hide_line(exec_context& ec,
if (args.empty()) { if (args.empty()) {
args.emplace_back("move-time"); args.emplace_back("move-time");
} else if (args.size() == 1) { } else if (args.size() == 1) {
textview_curses* tc = *lnav_data.ld_view_stack.top(); auto* tc = *lnav_data.ld_view_stack.top();
logfile_sub_source& lss = lnav_data.ld_log_source; auto& lss = lnav_data.ld_log_source;
if (tc == &lnav_data.ld_views[LNV_LOG]) { if (tc == &lnav_data.ld_views[LNV_LOG]) {
struct timeval min_time, max_time; auto min_time_opt = lss.get_min_log_time();
bool have_min_time = lss.get_min_log_time(min_time); auto max_time_opt = lss.get_max_log_time();
bool have_max_time = lss.get_max_log_time(max_time);
char min_time_str[32], max_time_str[32]; char min_time_str[32], max_time_str[32];
if (have_min_time) { if (min_time_opt) {
sql_strftime(min_time_str, sizeof(min_time_str), min_time); sql_strftime(
min_time_str, sizeof(min_time_str), min_time_opt.value());
} }
if (have_max_time) { if (max_time_opt) {
sql_strftime(max_time_str, sizeof(max_time_str), max_time); sql_strftime(
max_time_str, sizeof(max_time_str), max_time_opt.value());
} }
if (have_min_time && have_max_time) { if (min_time_opt && max_time_opt) {
retval = fmt::format( retval = fmt::format(
FMT_STRING("info: hiding lines before {} and after {}"), FMT_STRING("info: hiding lines before {} and after {}"),
min_time_str, min_time_str,
max_time_str); max_time_str);
} else if (have_min_time) { } else if (min_time_opt) {
retval = fmt::format(FMT_STRING("info: hiding lines before {}"), retval = fmt::format(FMT_STRING("info: hiding lines before {}"),
min_time_str); min_time_str);
} else if (have_max_time) { } else if (max_time_opt) {
retval = fmt::format(FMT_STRING("info: hiding lines after {}"), retval = fmt::format(FMT_STRING("info: hiding lines after {}"),
max_time_str); max_time_str);
} else { } else {
@ -4076,55 +4117,54 @@ com_hide_line(exec_context& ec,
} }
} else if (args.size() >= 2) { } else if (args.size() >= 2) {
std::string all_args = remaining_args(cmdline, args); std::string all_args = remaining_args(cmdline, args);
textview_curses* tc = *lnav_data.ld_view_stack.top(); auto* tc = *lnav_data.ld_view_stack.top();
logfile_sub_source& lss = lnav_data.ld_log_source; auto* ttt = dynamic_cast<text_time_translator*>(tc->get_sub_source());
auto& lss = lnav_data.ld_log_source;
date_time_scanner dts; date_time_scanner dts;
struct timeval tv; struct timeval tv_abs;
bool tv_set = false; nonstd::optional<timeval> tv_opt;
auto parse_res = relative_time::from_str(all_args); auto parse_res = relative_time::from_str(all_args);
if (parse_res.isOk()) { if (parse_res.isOk()) {
if (tc == &lnav_data.ld_views[LNV_LOG]) { if (ttt != nullptr) {
if (tc->get_inner_height() > 0) { if (tc->get_inner_height() > 0) {
content_line_t cl;
struct exttm tm; struct exttm tm;
vis_line_t vl;
logline* ll;
vl = tc->get_selection(); auto vl = tc->get_selection();
cl = lnav_data.ld_log_source.at(vl); auto log_tv = ttt->time_for_row(vl);
ll = lnav_data.ld_log_source.find_line(cl); if (log_tv) {
ll->to_exttm(tm); tm = exttm::from_tv(log_tv.value());
tv = parse_res.unwrap().adjust(tm).to_timeval(); tv_opt = parse_res.unwrap().adjust(tm).to_timeval();
}
tv_set = true;
} }
} else { } else {
return ec.make_error( return ec.make_error(
"relative time values only work in the log view"); "relative time values only work in a time-based view");
}
} else if (dts.convert_to_timeval(all_args, tv)) {
if (tc == &lnav_data.ld_views[LNV_LOG]) {
tv_set = true;
} else {
return ec.make_error("time values only work in the log view");
} }
} else if (dts.convert_to_timeval(all_args, tv_abs)) {
tv_opt = tv_abs;
} }
if (tv_set && !ec.ec_dry_run) { if (tv_opt && !ec.ec_dry_run) {
char time_text[256]; char time_text[256];
std::string relation; std::string relation;
sql_strftime(time_text, sizeof(time_text), tv); sql_strftime(time_text, sizeof(time_text), tv_opt.value());
if (args[0] == "hide-lines-before") { if (args[0] == "hide-lines-before") {
lss.set_min_log_time(tv); lss.set_min_log_time(tv_opt.value());
relation = "before"; relation = "before";
} else { } else {
lss.set_max_log_time(tv); lss.set_max_log_time(tv_opt.value());
relation = "after"; relation = "after";
} }
retval = "info: hiding lines " + relation + " " + time_text; if (ttt != nullptr && tc != &lnav_data.ld_views[LNV_LOG]) {
tc->get_sub_source()->text_filters_changed();
tc->reload_data();
}
retval = fmt::format(
FMT_STRING("info: hiding lines {} {}"), relation, time_text);
} }
} }
@ -5185,7 +5225,8 @@ readline_context::command_t STD_COMMANDS[] = {
"The initial value to fill in for the prompt") "The initial value to fill in for the prompt")
.optional()) .optional())
.with_example({ .with_example({
"To open the command prompt with 'filter-in' already filled in", "To open the command prompt with 'filter-in' already filled "
"in",
"command : 'filter-in '", "command : 'filter-in '",
}) })
.with_example({ .with_example({
@ -5263,8 +5304,8 @@ readline_context::command_t STD_COMMANDS[] = {
com_mark, com_mark,
help_text(":mark") help_text(":mark")
.with_summary( .with_summary("Toggle the bookmark state for the top line in the "
"Toggle the bookmark state for the top line in the current view") "current view")
.with_tags({"bookmarks"})}, .with_tags({"bookmarks"})},
{ {
"mark-expr", "mark-expr",
@ -5296,8 +5337,8 @@ readline_context::command_t STD_COMMANDS[] = {
com_goto_mark, com_goto_mark,
help_text(":next-mark") help_text(":next-mark")
.with_summary( .with_summary("Move to the next bookmark of the given type in the "
"Move to the next bookmark of the given type in the current view") "current view")
.with_parameter(help_text("type", .with_parameter(help_text("type",
"The type of bookmark -- error, warning, " "The type of bookmark -- error, warning, "
"search, user, file, meta") "search, user, file, meta")
@ -5464,8 +5505,8 @@ readline_context::command_t STD_COMMANDS[] = {
help_text("pattern", "The regular expression to match")) help_text("pattern", "The regular expression to match"))
.with_opposites({"filter-in", "filter-out"}) .with_opposites({"filter-in", "filter-out"})
.with_tags({"filtering"}) .with_tags({"filtering"})
.with_example( .with_example({"To delete the filter with the pattern 'last "
{"To delete the filter with the pattern 'last message repeated'", "message repeated'",
"last message repeated"})}, "last message repeated"})},
{ {
"filter-expr", "filter-expr",
@ -5484,8 +5525,10 @@ readline_context::command_t STD_COMMANDS[] = {
"messages from 'syslogd'", "messages from 'syslogd'",
":log_procname = 'syslogd'"}) ":log_procname = 'syslogd'"})
.with_example( .with_example(
{"To set a filter expression that matches log messages where " {"To set a filter expression that matches log messages "
"'id' is followed by a number and contains the string 'foo'", "where "
"'id' is followed by a number and contains the string "
"'foo'",
":log_body REGEXP 'id\\d+' AND :log_body REGEXP 'foo'"}), ":log_body REGEXP 'id\\d+' AND :log_body REGEXP 'foo'"}),
com_filter_expr_prompt, com_filter_expr_prompt,
@ -5505,8 +5548,8 @@ readline_context::command_t STD_COMMANDS[] = {
"Append marked lines in the current view to the given file") "Append marked lines in the current view to the given file")
.with_parameter(help_text("path", "The path to the file to append to")) .with_parameter(help_text("path", "The path to the file to append to"))
.with_tags({"io"}) .with_tags({"io"})
.with_example( .with_example({"To append marked lines to the file "
{"To append marked lines to the file /tmp/interesting-lines.txt", "/tmp/interesting-lines.txt",
"/tmp/interesting-lines.txt"})}, "/tmp/interesting-lines.txt"})},
{"write-to", {"write-to",
com_save_to, com_save_to,
@ -5518,8 +5561,8 @@ readline_context::command_t STD_COMMANDS[] = {
help_text("--anonymize", "Anonymize the lines").optional()) help_text("--anonymize", "Anonymize the lines").optional())
.with_parameter(help_text("path", "The path to the file to write")) .with_parameter(help_text("path", "The path to the file to write"))
.with_tags({"io", "scripting"}) .with_tags({"io", "scripting"})
.with_example( .with_example({"To write marked lines to the file "
{"To write marked lines to the file /tmp/interesting-lines.txt", "/tmp/interesting-lines.txt",
"/tmp/interesting-lines.txt"})}, "/tmp/interesting-lines.txt"})},
{"write-csv-to", {"write-csv-to",
com_save_to, com_save_to,
@ -5667,8 +5710,8 @@ readline_context::command_t STD_COMMANDS[] = {
"pattern", "The regular expression used in the filter command")) "pattern", "The regular expression used in the filter command"))
.with_tags({"filtering"}) .with_tags({"filtering"})
.with_opposites({"filter-out", "filter-in"}) .with_opposites({"filter-out", "filter-in"})
.with_example( .with_example({"To disable the filter with the pattern 'last "
{"To disable the filter with the pattern 'last message repeated'", "message repeated'",
"last message repeated"})}, "last message repeated"})},
{"enable-word-wrap", {"enable-word-wrap",
com_enable_word_wrap, com_enable_word_wrap,
@ -5714,9 +5757,9 @@ readline_context::command_t STD_COMMANDS[] = {
.with_parameter( .with_parameter(
help_text("table-name", "The name of the table to create")) help_text("table-name", "The name of the table to create"))
.with_parameter( .with_parameter(
help_text( help_text("pattern",
"pattern", "The regular expression used to capture the table "
"The regular expression used to capture the table columns. " "columns. "
"If not given, the current search pattern is used.") "If not given, the current search pattern is used.")
.optional()) .optional())
.with_tags({"vtables", "sql"}) .with_tags({"vtables", "sql"})
@ -5779,17 +5822,22 @@ readline_context::command_t STD_COMMANDS[] = {
com_close, com_close,
help_text(":close") help_text(":close")
.with_summary("Close the top file in the view") .with_summary("Close the given file(s) or the top file in the view")
.with_parameter(help_text{
"path", "A path or glob pattern that specifies the files to close"}
.zero_or_more())
.with_opposites({"open"})}, .with_opposites({"open"})},
{ {
"comment", "comment",
com_comment, com_comment,
help_text(":comment") help_text(":comment")
.with_summary( .with_summary("Attach a comment to the top log line. The "
"Attach a comment to the top log line. The comment will be " "comment will be "
"displayed right below the log message it is associated with. " "displayed right below the log message it is "
"The comment can be formatted using markdown and you can add " "associated with. "
"The comment can be formatted using markdown and "
"you can add "
"new-lines with '\\n'.") "new-lines with '\\n'.")
.with_parameter(help_text("text", "The comment text")) .with_parameter(help_text("text", "The comment text"))
.with_example({"To add the comment 'This is where it all went " .with_example({"To add the comment 'This is where it all went "
@ -5875,8 +5923,8 @@ readline_context::command_t STD_COMMANDS[] = {
"of the values in the given column") "of the values in the given column")
.with_parameter( .with_parameter(
help_text("column-name", "The name of the column to analyze.")) help_text("column-name", "The name of the column to analyze."))
.with_example( .with_example({"To get a summary of the sc_bytes column in the "
{"To get a summary of the sc_bytes column in the access_log table", "access_log table",
"sc_bytes"})}, "sc_bytes"})},
{"switch-to-view", {"switch-to-view",
com_switch_to_view, com_switch_to_view,

View File

@ -240,11 +240,15 @@ public:
} }
} }
bool get_min_log_time(struct timeval& tv_out) const nonstd::optional<timeval> get_min_log_time() const
{ {
tv_out = this->lss_min_log_time; if (this->lss_min_log_time.tv_sec == 0
return (this->lss_min_log_time.tv_sec != 0 && this->lss_min_log_time.tv_usec == 0)
|| this->lss_min_log_time.tv_usec != 0); {
return nonstd::nullopt;
}
return this->lss_min_log_time;
} }
void set_min_log_time(const struct timeval& tv) void set_min_log_time(const struct timeval& tv)
@ -255,12 +259,15 @@ public:
} }
} }
bool get_max_log_time(struct timeval& tv_out) const nonstd::optional<timeval> get_max_log_time() const
{ {
tv_out = this->lss_max_log_time; if (this->lss_max_log_time.tv_sec == std::numeric_limits<time_t>::max()
return (this->lss_max_log_time.tv_sec && this->lss_max_log_time.tv_usec == 0)
!= std::numeric_limits<time_t>::max() {
|| this->lss_max_log_time.tv_usec != 0); return nonstd::nullopt;
}
return this->lss_max_log_time;
} }
void set_max_log_time(struct timeval& tv) void set_max_log_time(struct timeval& tv)

View File

@ -377,15 +377,18 @@ add_file_possibilities()
rc->clear_possibilities(ln_mode_t::COMMAND, "visible-files"); rc->clear_possibilities(ln_mode_t::COMMAND, "visible-files");
rc->clear_possibilities(ln_mode_t::COMMAND, "hidden-files"); rc->clear_possibilities(ln_mode_t::COMMAND, "hidden-files");
rc->clear_possibilities(ln_mode_t::COMMAND, "loaded-files");
for (const auto& lf : lnav_data.ld_active_files.fc_files) { for (const auto& lf : lnav_data.ld_active_files.fc_files) {
if (lf.get() == nullptr) { if (lf.get() == nullptr) {
continue; continue;
} }
lnav_data.ld_log_source.find_data(lf) | [&lf, rc](auto ld) {
auto escaped_fn auto escaped_fn
= std::regex_replace(lf->get_filename(), sh_escape, R"(\\\1)"); = std::regex_replace(lf->get_filename(), sh_escape, R"(\\\1)");
rc->add_possibility(ln_mode_t::COMMAND, "loaded-files", escaped_fn);
lnav_data.ld_log_source.find_data(lf) | [&escaped_fn, rc](auto ld) {
rc->add_possibility( rc->add_possibility(
ln_mode_t::COMMAND, ln_mode_t::COMMAND,
ld->is_visible() ? "visible-files" : "hidden-files", ld->is_visible() ? "visible-files" : "hidden-files",

View File

@ -431,14 +431,15 @@ SELECT content_id, format, time_offset FROM lnav_file
level_names[min_level]); level_names[min_level]);
} }
struct timeval min_time, max_time;
char tsbuf[128]; char tsbuf[128];
if (lss->get_min_log_time(min_time)) { auto min_time_opt = lss->get_min_log_time();
sql_strftime(tsbuf, sizeof(tsbuf), min_time, 'T'); if (min_time_opt) {
sql_strftime(tsbuf, sizeof(tsbuf), min_time_opt.value(), 'T');
fmt::print(file, FMT_STRING(":hide-lines-before {}\n"), tsbuf); fmt::print(file, FMT_STRING(":hide-lines-before {}\n"), tsbuf);
} }
if (lss->get_max_log_time(max_time)) { auto max_time_opt = lss->get_max_log_time();
sql_strftime(tsbuf, sizeof(tsbuf), max_time, 'T'); if (max_time_opt) {
sql_strftime(tsbuf, sizeof(tsbuf), max_time_opt.value(), 'T');
fmt::print(file, FMT_STRING(":hide-lines-after {}\n"), tsbuf); fmt::print(file, FMT_STRING(":hide-lines-after {}\n"), tsbuf);
} }
for (const auto& ld : *lss) { for (const auto& ld : *lss) {

View File

@ -1535,20 +1535,21 @@ save_session_with_id(const std::string& session_id)
auto& lss = lnav_data.ld_log_source; auto& lss = lnav_data.ld_log_source;
struct timeval min_time, max_time; auto min_time_opt = lss.get_min_log_time();
bool have_min_time = lss.get_min_log_time(min_time); auto max_time_opt = lss.get_max_log_time();
bool have_max_time = lss.get_max_log_time(max_time);
char min_time_str[32], max_time_str[32]; char min_time_str[32], max_time_str[32];
sql_strftime( if (min_time_opt) {
min_time_str, sizeof(min_time_str), min_time); sql_strftime(min_time_str,
if (have_min_time) { sizeof(min_time_str),
min_time_opt.value());
cmd_array.gen("hide-lines-before " cmd_array.gen("hide-lines-before "
+ std::string(min_time_str)); + std::string(min_time_str));
} }
if (have_max_time) { if (max_time_opt) {
sql_strftime( sql_strftime(max_time_str,
max_time_str, sizeof(max_time_str), max_time); sizeof(max_time_str),
max_time_opt.value());
cmd_array.gen("hide-lines-after " cmd_array.gen("hide-lines-after "
+ std::string(max_time_str)); + std::string(max_time_str));
} }
@ -1703,9 +1704,27 @@ lnav::session::restore_view_states()
} }
for (const auto& cmdline : vs.vs_commands) { for (const auto& cmdline : vs.vs_commands) {
auto active = ensure_view(&tview); auto active = ensure_view(&tview);
execute_command(lnav_data.ld_exec_context, cmdline); auto exec_cmd_res
= execute_command(lnav_data.ld_exec_context, cmdline);
if (exec_cmd_res.isOk()) {
log_info("Result: %s", exec_cmd_res.unwrap().c_str());
} else {
log_error("Result: %s",
exec_cmd_res.unwrapErr()
.to_attr_line()
.get_string()
.c_str());
}
if (!active) { if (!active) {
lnav_data.ld_view_stack.pop_back(); lnav_data.ld_view_stack.pop_back();
lnav_data.ld_view_stack.top() | [](auto* tc) {
// XXX
if (tc == &lnav_data.ld_views[LNV_GANTT]) {
auto tss = tc->get_sub_source();
tss->text_filters_changed();
tc->reload_data();
}
};
} }
} }
} }

View File

@ -959,6 +959,14 @@ toggle_view(textview_curses* toggle_tc)
} }
lnav_data.ld_last_view = tc; lnav_data.ld_last_view = tc;
lnav_data.ld_view_stack.pop_back(); lnav_data.ld_view_stack.pop_back();
lnav_data.ld_view_stack.top() | [](auto* tc) {
// XXX
if (tc == &lnav_data.ld_views[LNV_GANTT]) {
auto tss = tc->get_sub_source();
tss->text_filters_changed();
tc->reload_data();
}
};
} else { } else {
if (toggle_tc == &lnav_data.ld_views[LNV_LOG] if (toggle_tc == &lnav_data.ld_views[LNV_LOG]
|| toggle_tc == &lnav_data.ld_views[LNV_TEXT]) || toggle_tc == &lnav_data.ld_views[LNV_TEXT])

View File

@ -276,12 +276,20 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.out \ $(srcdir)/%reldir%/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.out \
$(srcdir)/%reldir%/test_gantt.sh_3af11588ee36bab7e2caea0f7a24d3c9cafd2310.err \ $(srcdir)/%reldir%/test_gantt.sh_3af11588ee36bab7e2caea0f7a24d3c9cafd2310.err \
$(srcdir)/%reldir%/test_gantt.sh_3af11588ee36bab7e2caea0f7a24d3c9cafd2310.out \ $(srcdir)/%reldir%/test_gantt.sh_3af11588ee36bab7e2caea0f7a24d3c9cafd2310.out \
$(srcdir)/%reldir%/test_gantt.sh_63500be50fc6743d8312133e2030cbbc39ca15ff.err \
$(srcdir)/%reldir%/test_gantt.sh_63500be50fc6743d8312133e2030cbbc39ca15ff.out \
$(srcdir)/%reldir%/test_gantt.sh_74a94ee9103eac5e8e78ca57bccf49efa3827a9d.err \
$(srcdir)/%reldir%/test_gantt.sh_74a94ee9103eac5e8e78ca57bccf49efa3827a9d.out \
$(srcdir)/%reldir%/test_gantt.sh_83db753dd2669f801810f311e2d7d74397e10f26.err \ $(srcdir)/%reldir%/test_gantt.sh_83db753dd2669f801810f311e2d7d74397e10f26.err \
$(srcdir)/%reldir%/test_gantt.sh_83db753dd2669f801810f311e2d7d74397e10f26.out \ $(srcdir)/%reldir%/test_gantt.sh_83db753dd2669f801810f311e2d7d74397e10f26.out \
$(srcdir)/%reldir%/test_gantt.sh_8fed8a7400042814ba13e50be5e3bd1741d82119.err \ $(srcdir)/%reldir%/test_gantt.sh_8fed8a7400042814ba13e50be5e3bd1741d82119.err \
$(srcdir)/%reldir%/test_gantt.sh_8fed8a7400042814ba13e50be5e3bd1741d82119.out \ $(srcdir)/%reldir%/test_gantt.sh_8fed8a7400042814ba13e50be5e3bd1741d82119.out \
$(srcdir)/%reldir%/test_gantt.sh_b013ab41c3cca76cf05a01ca1ba65888be247ada.err \
$(srcdir)/%reldir%/test_gantt.sh_b013ab41c3cca76cf05a01ca1ba65888be247ada.out \
$(srcdir)/%reldir%/test_gantt.sh_cde7947f361e5f3d4cd1bbc3f7458f426b6a8eb4.err \ $(srcdir)/%reldir%/test_gantt.sh_cde7947f361e5f3d4cd1bbc3f7458f426b6a8eb4.err \
$(srcdir)/%reldir%/test_gantt.sh_cde7947f361e5f3d4cd1bbc3f7458f426b6a8eb4.out \ $(srcdir)/%reldir%/test_gantt.sh_cde7947f361e5f3d4cd1bbc3f7458f426b6a8eb4.out \
$(srcdir)/%reldir%/test_gantt.sh_e6a4681a5a671c84c020dc91d7ce03c9d17fde07.err \
$(srcdir)/%reldir%/test_gantt.sh_e6a4681a5a671c84c020dc91d7ce03c9d17fde07.out \
$(srcdir)/%reldir%/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.err \ $(srcdir)/%reldir%/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.err \
$(srcdir)/%reldir%/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.out \ $(srcdir)/%reldir%/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.out \
$(srcdir)/%reldir%/test_json_format.sh_1bb0fd243e916546aea22029245ac590dae17a86.err \ $(srcdir)/%reldir%/test_json_format.sh_1bb0fd243e916546aea22029245ac590dae17a86.err \

View File

@ -1,6 +1,6 @@
✘ error: no log files loaded ✘ error: no log files loaded
 --> command-option:2  --> command-option:2
 | :close   | :close 
 = help: :close  = help: :close path
══════════════════════════════════════════════════════════════════════ ══════════════════════════════════════════════════════════════════════
Close the top file in the view Close the given file(s) or the top file in the view

View File

@ -774,9 +774,12 @@ For support questions, email:
Clear the partition the top line is a part of Clear the partition the top line is a part of
:close :close path
══════════════════════════════════════════════════════════════════════ ══════════════════════════════════════════════════════════════════════
Close the top file in the view Close the given file(s) or the top file in the view
Parameter
path A path or glob pattern that specifies the files to
close
:comment text :comment text

View File

@ -0,0 +1,70 @@
2011-11-03T00:19:26.452 2011-11-03T00:21:13.204
2011-11-03T00:17:00.000 2011-11-03T00:22:00.000
 Duration | ✘▲ | Operation
 23s044    CN5hnY3x51j6Hr1v4 192.168.2.76
 32s388    CmWpC33jXuKpXNLcie 192.168.2.76
     CEh6Ka2HInkNSH01L2 192.168.2.76
 4s840    CjPGiy13ncXKxU765j 192.168.2.76
 6s895    CPoz7NUpXISemlNSd 192.168.2.76
 6s837    Ct6ixh35y9AEr7J7o9 192.168.2.76
 6s889    CaEFHq2HVQ5iGJQiD9 192.168.2.76
 6s875    CjinlH2fzDtvzI9637 192.168.2.76
 6s884    Cedw7H3ddE2yLiLoXc 192.168.2.76
 6s917    CAUlC249svUfE6q0g3 192.168.2.76
     CIJIDL1ULo4HpT24Gl 192.168.2.76
 016    CLsqp41RLUd83arUQb 192.168.2.76
 166    CbCciH11995WKkobR1 192.168.2.76
 457    ClcvKE1dqsEFQu46m9 192.168.2.76
     CaP2LpLGvsmX7yJO 192.168.2.76
 043    CNbPns4mOMGgjI8Ele 192.168.2.76
 557    C185u7u9Q4qhJPhzl 192.168.2.76
 129    CKzjfhsJ8vrn2rrfg 192.168.2.76
 562    CiIjAe1n5MnPOVpQ9f 192.168.2.76
     CGv2Tp4Ngt8MmKmVRd 192.168.2.76
 7s071    C5DisEMFU77Wk9Kae 192.168.2.76
     Cs5yEZ3ELZTeuTOsP4 192.168.2.76
 4s667    Cu4gIx1BDNtGOl7Ht2 192.168.2.76
 1s288    CRgW2I2zo3SInm6iT8 192.168.2.76
     CWJhMU2cTLEnseTmCb 192.168.2.76
 042    CejI402rKGtdBXij4f 192.168.2.76
     C2KnU34GcVV6amo8va 192.168.2.76
     C5vx4911iSMAJuShFd 192.168.2.76
     CbUCgw1DrIGcXzONB7 192.168.2.76
 502    C96j2X1DixgLTj2Oi8 192.168.2.76
     CYYyja3FFNEnftw3K6 192.168.2.76
  █  CBHHuR1xFnm5C5CQBc 192.168.2.76
     CD1jfU3p9abEm77mzf 192.168.2.76
     C0K9DaoPFkfnzwlZa 192.168.2.76
 616    CbQAWi3GX2bCmX5L56 192.168.2.76
 298    Cd8s2R3OGDgkhnvSu9 192.168.2.76
 205    CBeaXe4Iyj1gXd2Iq 192.168.2.76
     CmWpSw3VtjiAceBCwf 192.168.2.76
 1m12s201    CbNCgO1MzloHRNeY4f 192.168.2.76
 315    CX1GjC4vn52UY1uDv6 192.168.2.76
     CaPClb1Bf0RrRGtyWi 192.168.2.76
 35s642    CibfNy1QQW4ImDWRq5 192.168.2.76
 1m11s547    CTRXSR3blXJE5ZE7Ij 192.168.2.76
 1m11s536    CnGze54kQWWpKqrrZ4 192.168.2.76
 12s337    C3TZMB4CrUwYfkGJy1 192.168.2.76
     CK957ERTz8lBycly4 192.168.2.76
 1s309    CO5QKYQkcSdxQFA35 192.168.2.76
     CurHpb1TGZOktTRNP1 192.168.2.76
     CuUKOQ1R3CqKBgeTdf 192.168.2.76
     C3xkHgJnzZszVSTpi 192.168.2.76
     CMrjgF2XLmRh9C9TR4 192.168.2.76
     C2vQ8sVgyADHjtEda 192.168.2.76
     CD69521bDXIAb4IkW 192.168.2.76
 6s648    CC3vUI3gFB04zLvWRa 192.168.2.76
 2s666    C7Krri4g9tZfHniGXh 192.168.2.76
     CmxyBl2c8XAMTuHEk4 192.168.2.76
 499    CSvs6v26bQqFylkk6l 192.168.2.76
     C4pHul1H3OeWYz7o7i 192.168.2.76
     C7Lcvr4vsTf6eYpBva 192.168.2.76
     CV8faD4L1sLL5kDwN9 192.168.2.76
     CxyAKs10ppnHFP6O8i 192.168.2.76
     C6MrHk2C7rLuJqhjsg 192.168.2.76
     CvfUrT2DgYXXoZw9Ah 192.168.2.76
     CBX0254QJoklXNbvv2 192.168.2.76
     C6Ym6jvMgikT0xTTc 192.168.2.76
     CRNn9f1zKNlzHSM5pa 192.168.2.76
     CJLgi92kpp2gLgGTE5 192.168.2.76

View File

@ -0,0 +1,70 @@
2011-11-03T00:19:26.452 2011-11-03T00:21:13.204
2011-11-03T00:17:00.000 2011-11-03T00:22:00.000
 Duration | ✘▲ | Operation
 844    CwFs1P2UcUdlSxD2La 192.168.2.76
     CoX7zA3OJKGUOSCBY2 192.168.2.76
     CdrfXZ1NOFPEawF218 192.168.2.76
     CJwUi9bdB9c1lLW44 192.168.2.76
     CJxSUgkInyKSHiju1 192.168.2.76
     CT0JIh479jXIGt0Po1 192.168.2.76
     C6Q4Vm14ZJIlZhsXqk 192.168.2.76
 1s070    CtgxRAqDLvrRUQdqe 192.168.2.76
     CdysLK1XpcrXOpVDuh 192.168.2.76
 200    C6nSoj1Qco9PGyslz6 192.168.2.76
 23s044    CN5hnY3x51j6Hr1v4 192.168.2.76
     CdZUPH2DKOE7zzCLE3 192.168.2.76
 32s388    CmWpC33jXuKpXNLcie 192.168.2.76
     CsBgiE1WmGP4Yo749h 192.168.2.76
 657    CYfHyC28tAhkLYkXB7 192.168.2.76
     CtANmVrHYMtkWqPE5 192.168.2.76
 647    CSTH8n1O1nv0ztxNQd 192.168.2.76
     C4uDKU5tpeRU9Su19 192.168.2.76
     CEh6Ka2HInkNSH01L2 192.168.2.76
 4s840    CjPGiy13ncXKxU765j 192.168.2.76
 6s895    CPoz7NUpXISemlNSd 192.168.2.76
 6s837    Ct6ixh35y9AEr7J7o9 192.168.2.76
 6s889    CaEFHq2HVQ5iGJQiD9 192.168.2.76
 6s875    CjinlH2fzDtvzI9637 192.168.2.76
 6s884    Cedw7H3ddE2yLiLoXc 192.168.2.76
 6s917    CAUlC249svUfE6q0g3 192.168.2.76
     CIJIDL1ULo4HpT24Gl 192.168.2.76
 016    CLsqp41RLUd83arUQb 192.168.2.76
 166    CbCciH11995WKkobR1 192.168.2.76
 457    ClcvKE1dqsEFQu46m9 192.168.2.76
     CaP2LpLGvsmX7yJO 192.168.2.76
 043    CNbPns4mOMGgjI8Ele 192.168.2.76
 557    C185u7u9Q4qhJPhzl 192.168.2.76
 129    CKzjfhsJ8vrn2rrfg 192.168.2.76
 562    CiIjAe1n5MnPOVpQ9f 192.168.2.76
     CGv2Tp4Ngt8MmKmVRd 192.168.2.76
 7s071    C5DisEMFU77Wk9Kae 192.168.2.76
     Cs5yEZ3ELZTeuTOsP4 192.168.2.76
 4s667    Cu4gIx1BDNtGOl7Ht2 192.168.2.76
 1s288    CRgW2I2zo3SInm6iT8 192.168.2.76
     CWJhMU2cTLEnseTmCb 192.168.2.76
 042    CejI402rKGtdBXij4f 192.168.2.76
     C2KnU34GcVV6amo8va 192.168.2.76
     C5vx4911iSMAJuShFd 192.168.2.76
     CbUCgw1DrIGcXzONB7 192.168.2.76
 502    C96j2X1DixgLTj2Oi8 192.168.2.76
     CYYyja3FFNEnftw3K6 192.168.2.76
  █  CBHHuR1xFnm5C5CQBc 192.168.2.76
     CD1jfU3p9abEm77mzf 192.168.2.76
     C0K9DaoPFkfnzwlZa 192.168.2.76
 616    CbQAWi3GX2bCmX5L56 192.168.2.76
 298    Cd8s2R3OGDgkhnvSu9 192.168.2.76
 205    CBeaXe4Iyj1gXd2Iq 192.168.2.76
     CmWpSw3VtjiAceBCwf 192.168.2.76
 1m12s201    CbNCgO1MzloHRNeY4f 192.168.2.76
 315    CX1GjC4vn52UY1uDv6 192.168.2.76
     CaPClb1Bf0RrRGtyWi 192.168.2.76
 35s642    CibfNy1QQW4ImDWRq5 192.168.2.76
 1m11s547    CTRXSR3blXJE5ZE7Ij 192.168.2.76
 1m11s536    CnGze54kQWWpKqrrZ4 192.168.2.76
 12s337    C3TZMB4CrUwYfkGJy1 192.168.2.76
     CK957ERTz8lBycly4 192.168.2.76
 1s309    CO5QKYQkcSdxQFA35 192.168.2.76
     CurHpb1TGZOktTRNP1 192.168.2.76
     CuUKOQ1R3CqKBgeTdf 192.168.2.76
     C3xkHgJnzZszVSTpi 192.168.2.76
     CMrjgF2XLmRh9C9TR4 192.168.2.76

View File

@ -21,3 +21,23 @@ run_cap_test ${lnav_test} -n \
-c ':switch-to-view gantt' \ -c ':switch-to-view gantt' \
-c ':filter-out CdysLK1XpcrXOpVDuh' \ -c ':filter-out CdysLK1XpcrXOpVDuh' \
${test_dir}/logfile_bro_http.log.0 ${test_dir}/logfile_bro_http.log.0
run_cap_test ${lnav_test} -n \
-c ':switch-to-view gantt' \
-c ':hide-file *' \
${test_dir}/logfile_bro_http.log.0
run_cap_test ${lnav_test} -n \
-c ':switch-to-view gantt' \
-c ':close *' \
${test_dir}/logfile_bro_http.log.0
run_cap_test ${lnav_test} -n \
-c ':switch-to-view gantt' \
-c ':hide-lines-before 2011-11-03 00:19:37' \
${test_dir}/logfile_bro_http.log.0
run_cap_test ${lnav_test} -n \
-c ':switch-to-view gantt' \
-c ':hide-lines-after 2011-11-03 00:20:30' \
${test_dir}/logfile_bro_http.log.0