diff --git a/src/command_executor.cc b/src/command_executor.cc index 6d6e3138..edd26d54 100644 --- a/src/command_executor.cc +++ b/src/command_executor.cc @@ -352,18 +352,6 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg) bool done = false; auto bound_values = TRY(bind_sql_parameters(ec, stmt.in())); - if (lnav_data.ld_rl_view != nullptr) { - if (lnav_data.ld_rl_view) { - lnav_data.ld_rl_view->set_attr_value( - lnav::console::user_message::info( - attr_line_t("executing SQL statement, press ") - .append("CTRL+]"_hotkey) - .append(" to cancel")) - .to_attr_line()); - lnav_data.ld_rl_view->do_update(); - } - } - ec.ec_sql_callback(ec, stmt.in()); while (!done) { retcode = sqlite3_step(stmt.in()); @@ -887,7 +875,8 @@ execute_init_commands( lnav_data.ld_active_files.fc_file_names[OUTPUT_NAME] .with_piper(create_piper_res.unwrap()) .with_include_in_session(false) - .with_detect_format(false); + .with_detect_format(false) + .with_init_location(0_vl); lnav_data.ld_files_to_front.emplace_back(OUTPUT_NAME, 0_vl); if (lnav_data.ld_rl_view != nullptr) { @@ -1048,7 +1037,8 @@ pipe_callback(exec_context& ec, const std::string& cmdline, auto_fd& fd) lnav_data.ld_active_files.fc_file_names[tmp_pair.first] .with_filename(desc) .with_include_in_session(false) - .with_detect_format(false); + .with_detect_format(false) + .with_init_location(0_vl); lnav_data.ld_files_to_front.emplace_back(desc, 0_vl); if (lnav_data.ld_rl_view != nullptr) { lnav_data.ld_rl_view->set_alt_value(HELP_MSG_1(X, "to close the file")); diff --git a/src/file_collection.cc b/src/file_collection.cc index 252ed1a4..6cacb9e5 100644 --- a/src/file_collection.cc +++ b/src/file_collection.cc @@ -35,6 +35,7 @@ #include +#include "base/fs_util.hh" #include "base/humanize.network.hh" #include "base/isc.hh" #include "base/itertools.hh" @@ -607,7 +608,8 @@ file_collection::expand_filename( } auto filename_key = loo.loo_filename.empty() ? path : loo.loo_filename; - if (glob(path.c_str(), GLOB_NOCHECK, nullptr, gl.inout()) == 0) { + auto glob_flags = lnav::filesystem::is_glob(path) ? 0 : GLOB_NOCHECK; + if (glob(path.c_str(), glob_flags, nullptr, gl.inout()) == 0) { int lpc; if (gl->gl_pathc == 1 /*&& gl.gl_matchc == 0*/) { @@ -676,15 +678,20 @@ file_collection::expand_filename( file_collection retval; if (gl->gl_pathc == 1) { - log_error("failed to find path: %s -- %s", - filename_key.c_str(), - errmsg); - retval.fc_name_to_errors->writeAccess()->emplace( - filename_key, - file_error_info{ - time(nullptr), - errmsg, - }); + if (this->fc_name_to_errors->readAccess()->count( + filename_key) + == 0) + { + log_error("failed to find path: %s -- %s", + filename_key.c_str(), + errmsg); + retval.fc_name_to_errors->writeAccess() + ->emplace(filename_key, + file_error_info{ + time(nullptr), + errmsg, + }); + } } else { log_error("failed to find path: %s -- %s", path_str.c_str(), diff --git a/src/file_vtab.cc b/src/file_vtab.cc index 67a70cfb..d73b7a95 100644 --- a/src/file_vtab.cc +++ b/src/file_vtab.cc @@ -108,6 +108,10 @@ CREATE TABLE lnav_file ( break; } case 8: { + if (sqlite3_vtab_nochange(ctx)) { + return SQLITE_OK; + } + auto& cfg = injector::get(); auto lf_stat = lf->get_stat(); diff --git a/src/hotkeys.cc b/src/hotkeys.cc index b9fcd2e0..a27c20ac 100644 --- a/src/hotkeys.cc +++ b/src/hotkeys.cc @@ -159,6 +159,8 @@ handle_keyseq(const char* keyseq) ec.ec_error_callback_stack = lnav_data.ld_exec_context.ec_error_callback_stack; var_stack.push(std::map()); + // XXX push another so it doesn't look like interactive use + var_stack.push(std::map()); auto& vars = var_stack.top(); vars["keyseq"] = keyseq; const auto& kc = iter->second; diff --git a/src/keymaps/default-keymap.json b/src/keymaps/default-keymap.json index 8b38f616..2fac4b1d 100644 --- a/src/keymaps/default-keymap.json +++ b/src/keymaps/default-keymap.json @@ -77,7 +77,7 @@ "command": ";UPDATE lnav_views SET top = top + (height / 2), selection = (CASE movement WHEN 'top' THEN selection ELSE top + (height / 2) + (selection - top) END) WHERE name = (SELECT name FROM lnav_top_view)" }, "x15": { - "command": ";UPDATE lnav_views SET top = top - (height / 2), selection = (CASE movement WHEN 'top' THEN selection ELSE top - (height / 2) + (selection - top) END) WHERE name = (SELECT name FROM lnav_top_view)" + "command": ";UPDATE lnav_views SET top = max(0, top - (height / 2)), selection = (CASE movement WHEN 'top' THEN selection ELSE max(0, top - (height / 2) + (selection - top)) END) WHERE name = (SELECT name FROM lnav_top_view)" }, "x3d": { "command": ";UPDATE lnav_views SET paused = 1 - paused" diff --git a/src/lnav.cc b/src/lnav.cc index 1d324678..0da2e134 100644 --- a/src/lnav.cc +++ b/src/lnav.cc @@ -409,7 +409,9 @@ setup_logline_table(exec_context& ec) } } - walk_sqlite_metadata(lnav_data.ld_db.in(), lnav_sql_meta_callbacks); + if (update_possibilities) { + walk_sqlite_metadata(lnav_data.ld_db.in(), lnav_sql_meta_callbacks); + } for (const auto& iter : *lnav_data.ld_vtab_manager) { iter.second->get_foreign_keys(db_key_names); @@ -1901,6 +1903,7 @@ looper() || lnav_data.ld_text_source.text_line_count() > 0 || !lnav_data.ld_active_files.fc_other_files.empty())) { + log_debug("initial build completed"); lnav_data.ld_initial_build = true; } @@ -3016,7 +3019,8 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%' dir_wild + "/*", logfile_open_options()); } else { lnav_data.ld_active_files.fc_file_names.emplace( - abspath.in(), logfile_open_options()); + abspath.in(), + logfile_open_options().with_init_location(file_loc)); if (file_loc.valid()) { lnav_data.ld_files_to_front.emplace_back(abspath.in(), file_loc); diff --git a/src/lnav.hh b/src/lnav.hh index 3571ac1f..eedc651d 100644 --- a/src/lnav.hh +++ b/src/lnav.hh @@ -146,8 +146,6 @@ struct key_repeat_history { }; }; -using file_location_t = mapbox::util::variant; - struct lnav_data_t { std::map> ld_session_id; time_t ld_session_time; diff --git a/src/lnav.indexing.cc b/src/lnav.indexing.cc index ad15beb7..220e662d 100644 --- a/src/lnav.indexing.cc +++ b/src/lnav.indexing.cc @@ -260,8 +260,10 @@ rebuild_indexes(nonstd::optional deadline) if (new_top_opt) { log_info(" setting requested top line: %d", (int) new_top_opt.value()); - text_view.set_top(new_top_opt.value()); + text_view.set_selection(new_top_opt.value()); log_info(" actual top is now: %d", (int) text_view.get_top()); + log_info(" actual selection is now: %d", + (int) text_view.get_selection()); scroll_downs[LNV_TEXT] = false; } else { log_warning("could not jump to requested line"); diff --git a/src/lnav_commands.cc b/src/lnav_commands.cc index b7fb8cfd..e44c6493 100644 --- a/src/lnav_commands.cc +++ b/src/lnav_commands.cc @@ -2611,6 +2611,7 @@ com_open(exec_context& ec, std::string cmdline, std::vector& args) file_loc = fn.substr(hash_index); fn = fn.substr(0, hash_index); } + loo.with_init_location(file_loc); } auto file_iter = lnav_data.ld_active_files.fc_files.begin(); @@ -2642,7 +2643,8 @@ com_open(exec_context& ec, std::string cmdline, std::vector& args) auto ul = std::make_shared(fn); lnav_data.ld_active_files.fc_file_names[ul->get_path()] - .with_filename(fn); + .with_filename(fn) + .with_init_location(file_loc); isc::to().send( [ul](auto& clooper) { clooper.add_request(ul); }); lnav_data.ld_files_to_front.emplace_back(fn, file_loc); diff --git a/src/log_format_impls.cc b/src/log_format_impls.cc index cff53278..bc2e43a9 100644 --- a/src/log_format_impls.cc +++ b/src/log_format_impls.cc @@ -52,7 +52,7 @@ class generic_log_format : public log_format { pcre_format( "^(?:\\*\\*\\*\\s+)?(?@[0-9a-zA-Z]{16,24})(.*)"), pcre_format( - R"(^(?:\*\*\*\s+)?(?(?:\s|\d{4}[\-\/]\d{2}[\-\/]\d{2}|T|\d{1,2}:\d{2}(?::\d{2}(?:[\.,]\d{1,6})?)?|Z|[+\-]\d{2}:?\d{2}|(?!ERR|INFO|WARN)[A-Z]{3,4})+)(?:\s+|:)([^:]+))"), + R"(^(?:\*\*\*\s+)?(?(?:\s|\d{4}[\-\/]\d{2}[\-\/]\d{2}|T|\d{1,2}:\d{2}(?::\d{2}(?:[\.,]\d{1,6})?)?|Z|[+\-]\d{2}:?\d{2}|(?!ERR|INFO|WARN)[A-Z]{3,4})+)(?:\s+|[:|])([^:]+))"), pcre_format( "^(?:\\*\\*\\*\\s+)?(?[\\w:+/\\.-]+) \\[\\w (.*)"), pcre_format("^(?:\\*\\*\\*\\s+)?(?[\\w:,/\\.-]+) (.*)"), diff --git a/src/log_vtab_impl.cc b/src/log_vtab_impl.cc index 90a5520d..918239d5 100644 --- a/src/log_vtab_impl.cc +++ b/src/log_vtab_impl.cc @@ -775,6 +775,10 @@ vt_column(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int col) } case VT_COL_LOG_ANNOTATIONS: { + if (sqlite3_vtab_nochange(ctx)) { + return SQLITE_OK; + } + auto line_meta_opt = vt->lss->find_bookmark_metadata(vc->log_cursor.lc_curr_line); if (!line_meta_opt @@ -2026,7 +2030,9 @@ vt_update(sqlite3_vtab* tab, } if (log_annos) { line_meta.bm_annotations = std::move(tmp_bm.bm_annotations); - } else { + } else if (!sqlite3_value_nochange( + argv[2 + VT_COL_LOG_ANNOTATIONS])) + { line_meta.bm_annotations.la_pairs.clear(); } diff --git a/src/logfile_fwd.hh b/src/logfile_fwd.hh index 6c00949b..afd45249 100644 --- a/src/logfile_fwd.hh +++ b/src/logfile_fwd.hh @@ -38,6 +38,7 @@ #include "base/auto_fd.hh" #include "file_format.hh" #include "piper.looper.hh" +#include "vis_line.hh" using ui_clock = std::chrono::steady_clock; @@ -53,6 +54,8 @@ enum class logfile_name_source { REMOTE, }; +using file_location_t = mapbox::util::variant; + struct logfile_open_options_base { std::string loo_filename; logfile_name_source loo_source{logfile_name_source::USER}; @@ -68,6 +71,7 @@ struct logfile_open_options_base { file_format_t loo_file_format{file_format_t::UNKNOWN}; nonstd::optional loo_format_name; nonstd::optional loo_piper; + file_location_t loo_init_location; }; struct logfile_open_options : public logfile_open_options_base { @@ -156,6 +160,13 @@ struct logfile_open_options : public logfile_open_options_base { return *this; } + + logfile_open_options& with_init_location(file_location_t fl) + { + this->loo_init_location = fl; + + return *this; + } }; #endif diff --git a/src/plain_text_source.cc b/src/plain_text_source.cc index 90245545..d931f640 100644 --- a/src/plain_text_source.cc +++ b/src/plain_text_source.cc @@ -263,7 +263,7 @@ plain_text_source::text_crumbs_for_line(int line, } this->line_for_offset(sib_iter->second->hn_start) | [this](const auto new_top) { - this->tss_view->set_top(new_top); + this->tss_view->set_selection(new_top); }; }, [this, parent_node](size_t index) { @@ -300,7 +300,7 @@ plain_text_source::text_crumbs_for_line(int line, if (child_iter != curr_node->hn_named_children.end()) { this->line_for_offset(child_iter->second->hn_start) | [this](const auto new_top) { - this->tss_view->set_top(new_top); + this->tss_view->set_selection(new_top); }; } }, @@ -308,7 +308,7 @@ plain_text_source::text_crumbs_for_line(int line, auto* child = curr_node->hn_children[index].get(); this->line_for_offset(child->hn_start) | [this](const auto new_top) { - this->tss_view->set_top(new_top); + this->tss_view->set_selection(new_top); }; }); }; diff --git a/src/readline_callbacks.cc b/src/readline_callbacks.cc index ba5ec1e0..bbb43d58 100644 --- a/src/readline_callbacks.cc +++ b/src/readline_callbacks.cc @@ -49,6 +49,7 @@ #include "yajlpp/yajlpp.hh" using namespace std::chrono_literals; +using namespace lnav::roles::literals; #define ABORT_MSG "(Press " ANSI_BOLD("CTRL+]") " to abort)" @@ -702,6 +703,18 @@ rl_callback_int(readline_curses* rc, bool is_alt) readline_lnav_highlighter(ec.ec_source.back().s_content, -1); ec.ec_source.back().s_content.with_attr_for_all( VC_ROLE.value(role_t::VCR_QUOTED_CODE)); + + if (lnav_data.ld_rl_view != nullptr) { + if (lnav_data.ld_rl_view) { + lnav_data.ld_rl_view->set_attr_value( + lnav::console::user_message::info( + attr_line_t("executing SQL statement, press ") + .append("CTRL+]"_hotkey) + .append(" to cancel")) + .to_attr_line()); + lnav_data.ld_rl_view->do_update(); + } + } auto result = execute_sql(ec, rc->get_value().get_string(), alt_msg); auto& dls = lnav_data.ld_db_row_source; @@ -789,7 +802,8 @@ rl_callback_int(readline_curses* rc, bool is_alt) lnav_data.ld_active_files.fc_file_names[tmp_pair.first] .with_filename(desc) .with_include_in_session(false) - .with_detect_format(false); + .with_detect_format(false) + .with_init_location(0_vl); lnav_data.ld_files_to_front.emplace_back(desc, 0_vl); if (lnav_data.ld_rl_view != nullptr) { diff --git a/src/session_data.cc b/src/session_data.cc index fc80e7e4..69fe2b32 100644 --- a/src/session_data.cc +++ b/src/session_data.cc @@ -1685,8 +1685,16 @@ lnav::session::restore_view_states() for (size_t view_index = 0; view_index < LNV__MAX; view_index++) { const auto& vs = session_data.sd_view_states[view_index]; auto& tview = lnav_data.ld_views[view_index]; + bool has_loc = false; - if (vs.vs_top >= 0 + if (view_index == LNV_TEXT) { + auto lf = lnav_data.ld_text_source.current_file(); + if (lf != nullptr) { + has_loc = lf->get_open_options().loo_init_location.valid(); + } + } + + if (!has_loc && vs.vs_top >= 0 && (view_index == LNV_LOG || tview.get_top() == 0_vl || tview.get_top() == tview.get_top_for_last_row())) { @@ -1695,7 +1703,7 @@ lnav::session::restore_view_states() vs.vs_top); lnav_data.ld_views[view_index].set_top(vis_line_t(vs.vs_top), true); } - if (vs.vs_selection) { + if (!has_loc && vs.vs_selection) { log_info("restoring %s view selection: %d", lnav_view_strings[view_index], vs.vs_selection.value()); diff --git a/src/view_helpers.cc b/src/view_helpers.cc index 49626cfa..2f1e9d49 100644 --- a/src/view_helpers.cc +++ b/src/view_helpers.cc @@ -202,7 +202,7 @@ public: sib_iter->second->hn_start) | [](const auto new_top) { lnav_data.ld_views[LNV_PRETTY] - .set_top(new_top); + .set_selection(new_top); }; } }, @@ -214,8 +214,8 @@ public: = parent_node->hn_children[index].get(); this->line_for_offset(sib->hn_start) | [](const auto new_top) { - lnav_data.ld_views[LNV_PRETTY].set_top( - new_top); + lnav_data.ld_views[LNV_PRETTY] + .set_selection(new_top); }; }); }; @@ -266,8 +266,8 @@ public: if (child_iter != curr_node->hn_named_children.end()) { this->line_for_offset(child_iter->second->hn_start) | [](const auto new_top) { - lnav_data.ld_views[LNV_PRETTY].set_top( - new_top); + lnav_data.ld_views[LNV_PRETTY] + .set_selection(new_top); }; } }, @@ -275,7 +275,8 @@ public: auto* child = curr_node->hn_children[index].get(); this->line_for_offset(child->hn_start) | [](const auto new_top) { - lnav_data.ld_views[LNV_PRETTY].set_top(new_top); + lnav_data.ld_views[LNV_PRETTY].set_selection( + new_top); }; }); }; diff --git a/src/views_vtab.cc b/src/views_vtab.cc index 64a7a0f2..ba19fec3 100644 --- a/src/views_vtab.cc +++ b/src/views_vtab.cc @@ -355,6 +355,10 @@ CREATE TABLE lnav_views ( case 11: { static const size_t MAX_POSSIBILITIES = 128; + if (sqlite3_vtab_nochange(ctx)) { + return SQLITE_OK; + } + auto* tss = tc.get_sub_source(); if (tss != nullptr && tss->text_line_count() > 0) { @@ -412,6 +416,10 @@ CREATE TABLE lnav_views ( sqlite3_result_int(ctx, (int) tc.get_selection()); break; case 13: { + if (sqlite3_vtab_nochange(ctx)) { + return SQLITE_OK; + } + auto* text_accel_p = dynamic_cast(tc.get_sub_source()); auto vo = view_options{}; diff --git a/test/expected/test_cli.sh_0b3639753916f71254e8c9cce4ebb8bfd9978d3e.out b/test/expected/test_cli.sh_0b3639753916f71254e8c9cce4ebb8bfd9978d3e.out index ca7cae71..79f80e0f 100644 --- a/test/expected/test_cli.sh_0b3639753916f71254e8c9cce4ebb8bfd9978d3e.out +++ b/test/expected/test_cli.sh_0b3639753916f71254e8c9cce4ebb8bfd9978d3e.out @@ -4479,7 +4479,7 @@ "alt-msg": "" }, "x15": { - "command": ";UPDATE lnav_views SET top = top - (height / 2), selection = (CASE movement WHEN 'top' THEN selection ELSE top - (height / 2) + (selection - top) END) WHERE name = (SELECT name FROM lnav_top_view)", + "command": ";UPDATE lnav_views SET top = max(0, top - (height / 2)), selection = (CASE movement WHEN 'top' THEN selection ELSE max(0, top - (height / 2) + (selection - top)) END) WHERE name = (SELECT name FROM lnav_top_view)", "alt-msg": "" }, "x17": {