From 98699b318ccfbbcb636f98d4cb177de2dbaf1339 Mon Sep 17 00:00:00 2001 From: Tim Stack Date: Sun, 6 Aug 2023 23:26:27 -0700 Subject: [PATCH] [tests] more gantt tests --- src/base/time_util.cc | 13 +- src/base/time_util.hh | 2 + src/gantt_source.cc | 12 + src/internals/cmd-ref.rst | 9 +- src/lnav_commands.cc | 270 +++++++++++------- src/logfile_sub_source.hh | 25 +- src/readline_possibilities.cc | 9 +- src/session.export.cc | 11 +- src/session_data.cc | 39 ++- src/view_helpers.cc | 8 + test/expected/expected.am | 8 + ...7b495b95218b7c083951e2dba331cfec6e90be.err | 4 +- ...a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out | 7 +- ...500be50fc6743d8312133e2030cbbc39ca15ff.err | 0 ...500be50fc6743d8312133e2030cbbc39ca15ff.out | 0 ...a94ee9103eac5e8e78ca57bccf49efa3827a9d.err | 0 ...a94ee9103eac5e8e78ca57bccf49efa3827a9d.out | 0 ...13ab41c3cca76cf05a01ca1ba65888be247ada.err | 0 ...13ab41c3cca76cf05a01ca1ba65888be247ada.out | 70 +++++ ...a4681a5a671c84c020dc91d7ce03c9d17fde07.err | 0 ...a4681a5a671c84c020dc91d7ce03c9d17fde07.out | 70 +++++ test/test_gantt.sh | 20 ++ 22 files changed, 431 insertions(+), 146 deletions(-) create mode 100644 test/expected/test_gantt.sh_63500be50fc6743d8312133e2030cbbc39ca15ff.err create mode 100644 test/expected/test_gantt.sh_63500be50fc6743d8312133e2030cbbc39ca15ff.out create mode 100644 test/expected/test_gantt.sh_74a94ee9103eac5e8e78ca57bccf49efa3827a9d.err create mode 100644 test/expected/test_gantt.sh_74a94ee9103eac5e8e78ca57bccf49efa3827a9d.out create mode 100644 test/expected/test_gantt.sh_b013ab41c3cca76cf05a01ca1ba65888be247ada.err create mode 100644 test/expected/test_gantt.sh_b013ab41c3cca76cf05a01ca1ba65888be247ada.out create mode 100644 test/expected/test_gantt.sh_e6a4681a5a671c84c020dc91d7ce03c9d17fde07.err create mode 100644 test/expected/test_gantt.sh_e6a4681a5a671c84c020dc91d7ce03c9d17fde07.out diff --git a/src/base/time_util.cc b/src/base/time_util.cc index 0d461072..c392d176 100644 --- a/src/base/time_util.cc +++ b/src/base/time_util.cc @@ -75,7 +75,7 @@ strftime_rfc3339( return index; } -} +} // namespace lnav static time_t BAD_DATE = -1; @@ -225,6 +225,17 @@ secs2tm(lnav::time64_t tim, struct tm* 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 exttm::to_timeval() const { diff --git a/src/base/time_util.hh b/src/base/time_util.hh index 0c4aa00f..a717a251 100644 --- a/src/base/time_util.hh +++ b/src/base/time_util.hh @@ -104,6 +104,8 @@ enum exttm_flags_t { }; struct exttm { + static exttm from_tv(const timeval& tv); + struct tm et_tm {}; int32_t et_nsec{0}; unsigned int et_flags{0}; diff --git a/src/gantt_source.cc b/src/gantt_source.cc index 82fb168d..19a583cb 100644 --- a/src/gantt_source.cc +++ b/src/gantt_source.cc @@ -321,6 +321,9 @@ gantt_source::rebuild_indexes() this->gs_preview_source.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}; std::map active_opids; @@ -403,6 +406,7 @@ gantt_source::rebuild_indexes() } this->gs_filter_hits = {}; for (auto& pair : time_order_map) { + auto& otr = pair.second.or_value; auto& full_desc = pair.second.or_description; for (auto& desc : pair.second.or_descriptions) { 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) { this->gs_filtered_count += 1; continue; diff --git a/src/internals/cmd-ref.rst b/src/internals/cmd-ref.rst index f428a247..7df65cb8 100644 --- a/src/internals/cmd-ref.rst +++ b/src/internals/cmd-ref.rst @@ -176,10 +176,13 @@ .. _close: -:close -^^^^^^ +:close *path* +^^^^^^^^^^^^^ + + Close the given file(s) or the top file in the view - Close the top file in the view + **Parameters** + * **path** --- A path or glob pattern that specifies the files to close ---- diff --git a/src/lnav_commands.cc b/src/lnav_commands.cc index f214aafe..aebe21f0 100644 --- a/src/lnav_commands.cc +++ b/src/lnav_commands.cc @@ -2867,47 +2867,80 @@ com_close(exec_context& ec, std::string cmdline, std::vector& args) std::string retval; if (args.empty()) { - } else { - textview_curses* tc = *lnav_data.ld_view_stack.top(); - nonstd::optional actual_path; - std::string fn; + args.emplace_back("loaded-files"); + return Ok(retval); + } - if (tc == &lnav_data.ld_views[LNV_TEXT]) { - textfile_sub_source& tss = lnav_data.ld_text_source; + auto* tc = *lnav_data.ld_view_stack.top(); + std::vector> actual_path_v; + std::vector fn_v; - if (tss.empty()) { - return ec.make_error("no text files are opened"); - } else { - fn = tss.current_file()->get_filename(); - lnav_data.ld_active_files.request_close(tss.current_file()); + if (args.size() > 1) { + auto lexer = shlex(cmdline); - if (tss.size() == 1) { - lnav_data.ld_view_stack.pop_back(); - } + 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; } - } else if (tc == &lnav_data.ld_views[LNV_LOG]) { - if (tc->get_inner_height() == 0) { - return ec.make_error("no log files loaded"); - } else { - logfile_sub_source& lss = lnav_data.ld_log_source; - vis_line_t vl = tc->get_selection(); - content_line_t cl = lss.at(vl); - std::shared_ptr lf = lss.find(cl); - actual_path = lf->get_actual_path(); - fn = lf->get_filename(); - if (!ec.ec_dry_run) { - lnav_data.ld_active_files.request_close(lf); - } + 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()) { + return ec.make_error("no text files are opened"); } else { - return ec.make_error( - "close must be run in the log or text file views"); + fn_v.emplace_back(tss.current_file()->get_filename()); + lnav_data.ld_active_files.request_close(tss.current_file()); + + if (tss.size() == 1) { + lnav_data.ld_view_stack.pop_back(); + } } - if (!fn.empty()) { - if (ec.ec_dry_run) { - retval = ""; - } else { + } else if (tc == &lnav_data.ld_views[LNV_LOG]) { + if (tc->get_inner_height() == 0) { + return ec.make_error("no log files loaded"); + } else { + auto& lss = lnav_data.ld_log_source; + auto vl = tc->get_selection(); + auto cl = lss.at(vl); + auto lf = lss.find(cl); + + 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 { + return ec.make_error("close must be run in the log or text file views"); + } + if (!fn_v.empty()) { + if (ec.ec_dry_run) { + retval = ""; + } 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())) { isc::to().send( [fn](auto& clooper) { clooper.close_request(fn); }); @@ -2917,8 +2950,9 @@ com_close(exec_context& ec, std::string cmdline, std::vector& args) actual_path.value().string()); } 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) { - textview_curses* tc = *lnav_data.ld_view_stack.top(); + auto* tc = *lnav_data.ld_view_stack.top(); std::shared_ptr lf; 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()) { return ec.make_error("no text files are opened"); @@ -2981,6 +3015,7 @@ com_file_visibility(exec_context& ec, make_visible ? "showing" : "hiding", lf->get_filename()); } else { + auto* top_tc = *lnav_data.ld_view_stack.top(); int text_file_count = 0, log_file_count = 0; auto lexer = shlex(cmdline); @@ -3023,6 +3058,11 @@ com_file_visibility(exec_context& ec, lnav_data.ld_views[LNV_LOG] .get_sub_source() ->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) { lnav_data.ld_views[LNV_TEXT] @@ -3879,10 +3919,10 @@ com_export_session_to(exec_context& ec, tcsetattr(1, TCSANOW, &curr_termios); setvbuf(stdout, nullptr, _IONBF, 0); to_term = true; - fprintf( - outfile, - "\n---------------- Press any key to exit lo-fi display " - "----------------\n\n"); + fprintf(outfile, + "\n---------------- Press any key to exit lo-fi " + "display " + "----------------\n\n"); } else { outfile = auto_mem::leak(ec_out.value()); } @@ -4039,30 +4079,31 @@ com_hide_line(exec_context& ec, if (args.empty()) { args.emplace_back("move-time"); } else if (args.size() == 1) { - textview_curses* tc = *lnav_data.ld_view_stack.top(); - logfile_sub_source& lss = lnav_data.ld_log_source; + auto* tc = *lnav_data.ld_view_stack.top(); + auto& lss = lnav_data.ld_log_source; if (tc == &lnav_data.ld_views[LNV_LOG]) { - struct timeval min_time, max_time; - bool have_min_time = lss.get_min_log_time(min_time); - bool have_max_time = lss.get_max_log_time(max_time); + auto min_time_opt = lss.get_min_log_time(); + auto max_time_opt = lss.get_max_log_time(); char min_time_str[32], max_time_str[32]; - if (have_min_time) { - sql_strftime(min_time_str, sizeof(min_time_str), min_time); + if (min_time_opt) { + sql_strftime( + min_time_str, sizeof(min_time_str), min_time_opt.value()); } - if (have_max_time) { - sql_strftime(max_time_str, sizeof(max_time_str), max_time); + if (max_time_opt) { + 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( FMT_STRING("info: hiding lines before {} and after {}"), min_time_str, max_time_str); - } else if (have_min_time) { + } else if (min_time_opt) { retval = fmt::format(FMT_STRING("info: hiding lines before {}"), min_time_str); - } else if (have_max_time) { + } else if (max_time_opt) { retval = fmt::format(FMT_STRING("info: hiding lines after {}"), max_time_str); } else { @@ -4076,55 +4117,54 @@ com_hide_line(exec_context& ec, } } else if (args.size() >= 2) { std::string all_args = remaining_args(cmdline, args); - textview_curses* tc = *lnav_data.ld_view_stack.top(); - logfile_sub_source& lss = lnav_data.ld_log_source; + auto* tc = *lnav_data.ld_view_stack.top(); + auto* ttt = dynamic_cast(tc->get_sub_source()); + auto& lss = lnav_data.ld_log_source; date_time_scanner dts; - struct timeval tv; - bool tv_set = false; + struct timeval tv_abs; + nonstd::optional tv_opt; auto parse_res = relative_time::from_str(all_args); if (parse_res.isOk()) { - if (tc == &lnav_data.ld_views[LNV_LOG]) { + if (ttt != nullptr) { if (tc->get_inner_height() > 0) { - content_line_t cl; struct exttm tm; - vis_line_t vl; - logline* ll; - vl = tc->get_selection(); - cl = lnav_data.ld_log_source.at(vl); - ll = lnav_data.ld_log_source.find_line(cl); - ll->to_exttm(tm); - tv = parse_res.unwrap().adjust(tm).to_timeval(); - - tv_set = true; + auto vl = tc->get_selection(); + auto log_tv = ttt->time_for_row(vl); + if (log_tv) { + tm = exttm::from_tv(log_tv.value()); + tv_opt = parse_res.unwrap().adjust(tm).to_timeval(); + } } } else { return ec.make_error( - "relative time values only work in the log 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"); + "relative time values only work in a time-based 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]; 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") { - lss.set_min_log_time(tv); + lss.set_min_log_time(tv_opt.value()); relation = "before"; } else { - lss.set_max_log_time(tv); + lss.set_max_log_time(tv_opt.value()); 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") .optional()) .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 '", }) .with_example({ @@ -5263,8 +5304,8 @@ readline_context::command_t STD_COMMANDS[] = { com_mark, help_text(":mark") - .with_summary( - "Toggle the bookmark state for the top line in the current view") + .with_summary("Toggle the bookmark state for the top line in the " + "current view") .with_tags({"bookmarks"})}, { "mark-expr", @@ -5296,8 +5337,8 @@ readline_context::command_t STD_COMMANDS[] = { com_goto_mark, help_text(":next-mark") - .with_summary( - "Move to the next bookmark of the given type in the current view") + .with_summary("Move to the next bookmark of the given type in the " + "current view") .with_parameter(help_text("type", "The type of bookmark -- error, warning, " "search, user, file, meta") @@ -5464,9 +5505,9 @@ readline_context::command_t STD_COMMANDS[] = { help_text("pattern", "The regular expression to match")) .with_opposites({"filter-in", "filter-out"}) .with_tags({"filtering"}) - .with_example( - {"To delete the filter with the pattern 'last message repeated'", - "last message repeated"})}, + .with_example({"To delete the filter with the pattern 'last " + "message repeated'", + "last message repeated"})}, { "filter-expr", com_filter_expr, @@ -5484,8 +5525,10 @@ readline_context::command_t STD_COMMANDS[] = { "messages from 'syslogd'", ":log_procname = 'syslogd'"}) .with_example( - {"To set a filter expression that matches log messages where " - "'id' is followed by a number and contains the string 'foo'", + {"To set a filter expression that matches log messages " + "where " + "'id' is followed by a number and contains the string " + "'foo'", ":log_body REGEXP 'id\\d+' AND :log_body REGEXP 'foo'"}), com_filter_expr_prompt, @@ -5505,9 +5548,9 @@ readline_context::command_t STD_COMMANDS[] = { "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_tags({"io"}) - .with_example( - {"To append marked lines to the file /tmp/interesting-lines.txt", - "/tmp/interesting-lines.txt"})}, + .with_example({"To append marked lines to the file " + "/tmp/interesting-lines.txt", + "/tmp/interesting-lines.txt"})}, {"write-to", com_save_to, @@ -5518,9 +5561,9 @@ readline_context::command_t STD_COMMANDS[] = { help_text("--anonymize", "Anonymize the lines").optional()) .with_parameter(help_text("path", "The path to the file to write")) .with_tags({"io", "scripting"}) - .with_example( - {"To write marked lines to the file /tmp/interesting-lines.txt", - "/tmp/interesting-lines.txt"})}, + .with_example({"To write marked lines to the file " + "/tmp/interesting-lines.txt", + "/tmp/interesting-lines.txt"})}, {"write-csv-to", com_save_to, @@ -5667,9 +5710,9 @@ readline_context::command_t STD_COMMANDS[] = { "pattern", "The regular expression used in the filter command")) .with_tags({"filtering"}) .with_opposites({"filter-out", "filter-in"}) - .with_example( - {"To disable the filter with the pattern 'last message repeated'", - "last message repeated"})}, + .with_example({"To disable the filter with the pattern 'last " + "message repeated'", + "last message repeated"})}, {"enable-word-wrap", com_enable_word_wrap, @@ -5714,10 +5757,10 @@ readline_context::command_t STD_COMMANDS[] = { .with_parameter( help_text("table-name", "The name of the table to create")) .with_parameter( - help_text( - "pattern", - "The regular expression used to capture the table columns. " - "If not given, the current search pattern is used.") + help_text("pattern", + "The regular expression used to capture the table " + "columns. " + "If not given, the current search pattern is used.") .optional()) .with_tags({"vtables", "sql"}) .with_example( @@ -5779,18 +5822,23 @@ readline_context::command_t STD_COMMANDS[] = { com_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"})}, { "comment", com_comment, help_text(":comment") - .with_summary( - "Attach a comment to the top log line. The comment will be " - "displayed right below the log message it is associated with. " - "The comment can be formatted using markdown and you can add " - "new-lines with '\\n'.") + .with_summary("Attach a comment to the top log line. The " + "comment will be " + "displayed right below the log message it is " + "associated with. " + "The comment can be formatted using markdown and " + "you can add " + "new-lines with '\\n'.") .with_parameter(help_text("text", "The comment text")) .with_example({"To add the comment 'This is where it all went " "wrong' to the top line", @@ -5875,9 +5923,9 @@ readline_context::command_t STD_COMMANDS[] = { "of the values in the given column") .with_parameter( help_text("column-name", "The name of the column to analyze.")) - .with_example( - {"To get a summary of the sc_bytes column in the access_log table", - "sc_bytes"})}, + .with_example({"To get a summary of the sc_bytes column in the " + "access_log table", + "sc_bytes"})}, {"switch-to-view", com_switch_to_view, diff --git a/src/logfile_sub_source.hh b/src/logfile_sub_source.hh index 3e94537b..888acf26 100644 --- a/src/logfile_sub_source.hh +++ b/src/logfile_sub_source.hh @@ -240,11 +240,15 @@ public: } } - bool get_min_log_time(struct timeval& tv_out) const + nonstd::optional get_min_log_time() const { - tv_out = this->lss_min_log_time; - return (this->lss_min_log_time.tv_sec != 0 - || this->lss_min_log_time.tv_usec != 0); + if (this->lss_min_log_time.tv_sec == 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) @@ -255,12 +259,15 @@ public: } } - bool get_max_log_time(struct timeval& tv_out) const + nonstd::optional get_max_log_time() const { - tv_out = this->lss_max_log_time; - return (this->lss_max_log_time.tv_sec - != std::numeric_limits::max() - || this->lss_max_log_time.tv_usec != 0); + if (this->lss_max_log_time.tv_sec == std::numeric_limits::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) diff --git a/src/readline_possibilities.cc b/src/readline_possibilities.cc index a2e8191b..7e759237 100644 --- a/src/readline_possibilities.cc +++ b/src/readline_possibilities.cc @@ -377,15 +377,18 @@ add_file_possibilities() 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, "loaded-files"); for (const auto& lf : lnav_data.ld_active_files.fc_files) { if (lf.get() == nullptr) { continue; } - lnav_data.ld_log_source.find_data(lf) | [&lf, rc](auto ld) { - auto escaped_fn - = std::regex_replace(lf->get_filename(), sh_escape, R"(\\\1)"); + auto escaped_fn + = 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( ln_mode_t::COMMAND, ld->is_visible() ? "visible-files" : "hidden-files", diff --git a/src/session.export.cc b/src/session.export.cc index d408c506..292280e5 100644 --- a/src/session.export.cc +++ b/src/session.export.cc @@ -431,14 +431,15 @@ SELECT content_id, format, time_offset FROM lnav_file level_names[min_level]); } - struct timeval min_time, max_time; char tsbuf[128]; - if (lss->get_min_log_time(min_time)) { - sql_strftime(tsbuf, sizeof(tsbuf), min_time, 'T'); + auto min_time_opt = lss->get_min_log_time(); + if (min_time_opt) { + sql_strftime(tsbuf, sizeof(tsbuf), min_time_opt.value(), 'T'); fmt::print(file, FMT_STRING(":hide-lines-before {}\n"), tsbuf); } - if (lss->get_max_log_time(max_time)) { - sql_strftime(tsbuf, sizeof(tsbuf), max_time, 'T'); + auto max_time_opt = lss->get_max_log_time(); + if (max_time_opt) { + sql_strftime(tsbuf, sizeof(tsbuf), max_time_opt.value(), 'T'); fmt::print(file, FMT_STRING(":hide-lines-after {}\n"), tsbuf); } for (const auto& ld : *lss) { diff --git a/src/session_data.cc b/src/session_data.cc index 203461a3..96fd777d 100644 --- a/src/session_data.cc +++ b/src/session_data.cc @@ -1535,20 +1535,21 @@ save_session_with_id(const std::string& session_id) auto& lss = lnav_data.ld_log_source; - struct timeval min_time, max_time; - bool have_min_time = lss.get_min_log_time(min_time); - bool have_max_time = lss.get_max_log_time(max_time); + auto min_time_opt = lss.get_min_log_time(); + auto max_time_opt = lss.get_max_log_time(); char min_time_str[32], max_time_str[32]; - sql_strftime( - min_time_str, sizeof(min_time_str), min_time); - if (have_min_time) { + if (min_time_opt) { + sql_strftime(min_time_str, + sizeof(min_time_str), + min_time_opt.value()); cmd_array.gen("hide-lines-before " + std::string(min_time_str)); } - if (have_max_time) { - sql_strftime( - max_time_str, sizeof(max_time_str), max_time); + if (max_time_opt) { + sql_strftime(max_time_str, + sizeof(max_time_str), + max_time_opt.value()); cmd_array.gen("hide-lines-after " + std::string(max_time_str)); } @@ -1703,9 +1704,27 @@ lnav::session::restore_view_states() } for (const auto& cmdline : vs.vs_commands) { 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) { 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(); + } + }; } } } diff --git a/src/view_helpers.cc b/src/view_helpers.cc index 3a279f2e..49626cfa 100644 --- a/src/view_helpers.cc +++ b/src/view_helpers.cc @@ -959,6 +959,14 @@ toggle_view(textview_curses* toggle_tc) } lnav_data.ld_last_view = tc; 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 { if (toggle_tc == &lnav_data.ld_views[LNV_LOG] || toggle_tc == &lnav_data.ld_views[LNV_TEXT]) diff --git a/test/expected/expected.am b/test/expected/expected.am index 77fefc11..e8776b7a 100644 --- a/test/expected/expected.am +++ b/test/expected/expected.am @@ -276,12 +276,20 @@ EXPECTED_FILES = \ $(srcdir)/%reldir%/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.out \ $(srcdir)/%reldir%/test_gantt.sh_3af11588ee36bab7e2caea0f7a24d3c9cafd2310.err \ $(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.out \ $(srcdir)/%reldir%/test_gantt.sh_8fed8a7400042814ba13e50be5e3bd1741d82119.err \ $(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.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.out \ $(srcdir)/%reldir%/test_json_format.sh_1bb0fd243e916546aea22029245ac590dae17a86.err \ diff --git a/test/expected/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.err b/test/expected/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.err index 0d53487d..8ecc11d1 100644 --- a/test/expected/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.err +++ b/test/expected/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.err @@ -1,6 +1,6 @@ ✘ error: no log files loaded  --> command-option:2  | :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 diff --git a/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out b/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out index 1e67260c..d3d65c5e 100644 --- a/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out +++ b/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out @@ -774,9 +774,12 @@ For support questions, email: 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 diff --git a/test/expected/test_gantt.sh_63500be50fc6743d8312133e2030cbbc39ca15ff.err b/test/expected/test_gantt.sh_63500be50fc6743d8312133e2030cbbc39ca15ff.err new file mode 100644 index 00000000..e69de29b diff --git a/test/expected/test_gantt.sh_63500be50fc6743d8312133e2030cbbc39ca15ff.out b/test/expected/test_gantt.sh_63500be50fc6743d8312133e2030cbbc39ca15ff.out new file mode 100644 index 00000000..e69de29b diff --git a/test/expected/test_gantt.sh_74a94ee9103eac5e8e78ca57bccf49efa3827a9d.err b/test/expected/test_gantt.sh_74a94ee9103eac5e8e78ca57bccf49efa3827a9d.err new file mode 100644 index 00000000..e69de29b diff --git a/test/expected/test_gantt.sh_74a94ee9103eac5e8e78ca57bccf49efa3827a9d.out b/test/expected/test_gantt.sh_74a94ee9103eac5e8e78ca57bccf49efa3827a9d.out new file mode 100644 index 00000000..e69de29b diff --git a/test/expected/test_gantt.sh_b013ab41c3cca76cf05a01ca1ba65888be247ada.err b/test/expected/test_gantt.sh_b013ab41c3cca76cf05a01ca1ba65888be247ada.err new file mode 100644 index 00000000..e69de29b diff --git a/test/expected/test_gantt.sh_b013ab41c3cca76cf05a01ca1ba65888be247ada.out b/test/expected/test_gantt.sh_b013ab41c3cca76cf05a01ca1ba65888be247ada.out new file mode 100644 index 00000000..03a51269 --- /dev/null +++ b/test/expected/test_gantt.sh_b013ab41c3cca76cf05a01ca1ba65888be247ada.out @@ -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 diff --git a/test/expected/test_gantt.sh_e6a4681a5a671c84c020dc91d7ce03c9d17fde07.err b/test/expected/test_gantt.sh_e6a4681a5a671c84c020dc91d7ce03c9d17fde07.err new file mode 100644 index 00000000..e69de29b diff --git a/test/expected/test_gantt.sh_e6a4681a5a671c84c020dc91d7ce03c9d17fde07.out b/test/expected/test_gantt.sh_e6a4681a5a671c84c020dc91d7ce03c9d17fde07.out new file mode 100644 index 00000000..9b167955 --- /dev/null +++ b/test/expected/test_gantt.sh_e6a4681a5a671c84c020dc91d7ce03c9d17fde07.out @@ -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 diff --git a/test/test_gantt.sh b/test/test_gantt.sh index 9b035440..b64c1307 100644 --- a/test/test_gantt.sh +++ b/test/test_gantt.sh @@ -21,3 +21,23 @@ run_cap_test ${lnav_test} -n \ -c ':switch-to-view gantt' \ -c ':filter-out CdysLK1XpcrXOpVDuh' \ ${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