diff --git a/src/base/intern_string.hh b/src/base/intern_string.hh index 3505663e..4d390fa0 100644 --- a/src/base/intern_string.hh +++ b/src/base/intern_string.hh @@ -202,6 +202,12 @@ struct string_fragment { return memcmp(this->data(), sf.data(), sf.length()) == 0; } + int operator<(const string_fragment& rhs) const + { + return strncmp( + this->data(), rhs.data(), std::min(this->length(), rhs.length())); + } + bool iequal(const string_fragment& sf) const { if (this->length() != sf.length()) { diff --git a/src/lnav_config.cc b/src/lnav_config.cc index ce41e583..5de72871 100644 --- a/src/lnav_config.cc +++ b/src/lnav_config.cc @@ -1430,6 +1430,8 @@ const json_path_container lnav_config_handlers = json_path_container { class active_key_map_listener : public lnav_config_listener { public: + active_key_map_listener() : lnav_config_listener(__FILE__) {} + void reload_config(error_reporter& reporter) override { lnav_config.lc_active_keymap = lnav_config.lc_ui_keymaps["default"]; diff --git a/src/lnav_config_fwd.hh b/src/lnav_config_fwd.hh index 0b371a33..0f7df3f5 100644 --- a/src/lnav_config_fwd.hh +++ b/src/lnav_config_fwd.hh @@ -42,10 +42,17 @@ public: using error_reporter = const std::function; - lnav_config_listener() + template + lnav_config_listener(const T (&src_file)[N]) + : lcl_name(string_fragment::from_const(src_file)) { - this->lcl_next = LISTENER_LIST; - LISTENER_LIST = this; + auto** curr = &LISTENER_LIST; + + while (*curr != nullptr && (*curr)->lcl_name < this->lcl_name) { + curr = &(*curr)->lcl_next; + } + this->lcl_next = *curr; + *curr = this; } virtual ~lnav_config_listener() = default; @@ -54,7 +61,8 @@ public: virtual void unload_config() {} - static void unload_all() { + static void unload_all() + { auto* lcl = LISTENER_LIST; while (lcl != nullptr) { lcl->unload_config(); @@ -65,6 +73,7 @@ public: static lnav_config_listener* LISTENER_LIST; lnav_config_listener* lcl_next; + string_fragment lcl_name; }; #endif diff --git a/src/log.annotate.cc b/src/log.annotate.cc index 1faba19a..cc52fca2 100644 --- a/src/log.annotate.cc +++ b/src/log.annotate.cc @@ -52,6 +52,8 @@ struct compiled_cond_expr { }; struct expressions : public lnav_config_listener { + expressions() : lnav_config_listener(__FILE__) {} + void reload_config(error_reporter& reporter) override { auto& lnav_db = injector::get(); diff --git a/src/log.watch.cc b/src/log.watch.cc index e90b2eb5..84b0a2bb 100644 --- a/src/log.watch.cc +++ b/src/log.watch.cc @@ -50,6 +50,8 @@ struct compiled_watch_expr { }; struct expressions : public lnav_config_listener { + expressions() : lnav_config_listener(__FILE__) {} + void reload_config(error_reporter& reporter) override { auto& lnav_db = injector::get(); @@ -98,9 +100,7 @@ struct expressions : public lnav_config_listener { } } - void unload_config() override { - this->e_watch_exprs.clear(); - } + void unload_config() override { this->e_watch_exprs.clear(); } std::map e_watch_exprs; }; diff --git a/src/log_format.cc b/src/log_format.cc index 9a9ed66f..1b8cb6f3 100644 --- a/src/log_format.cc +++ b/src/log_format.cc @@ -1845,6 +1845,8 @@ struct compiled_header_expr { }; struct format_header_expressions : public lnav_config_listener { + format_header_expressions() : lnav_config_listener(__FILE__) {} + auto_sqlite3 e_db; std::map> e_header_exprs; diff --git a/src/textview_curses.cc b/src/textview_curses.cc index 147ffe16..4cc661ec 100644 --- a/src/textview_curses.cc +++ b/src/textview_curses.cc @@ -182,7 +182,8 @@ const bookmark_type_t textview_curses::BM_USER_EXPR("user-expr"); const bookmark_type_t textview_curses::BM_SEARCH("search"); const bookmark_type_t textview_curses::BM_META("meta"); -textview_curses::textview_curses() : tc_search_action(noop_func{}) +textview_curses::textview_curses() + : lnav_config_listener(__FILE__), tc_search_action(noop_func{}) { this->set_data_source(this); } diff --git a/src/view_curses.cc b/src/view_curses.cc index c4b812ac..6d9b8d6d 100644 --- a/src/view_curses.cc +++ b/src/view_curses.cc @@ -498,6 +498,8 @@ static std::string COLOR_NAMES[] = { class color_listener : public lnav_config_listener { public: + color_listener() : lnav_config_listener(__FILE__) {} + void reload_config(error_reporter& reporter) override { if (!view_colors::initialized) { diff --git a/test/expected/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.err b/test/expected/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.err index e703fcb1..4ef50e41 100644 --- a/test/expected/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.err +++ b/test/expected/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.err @@ -55,6 +55,18 @@ ✘ error: invalid JSON reason: parse error: premature EOF  --> {test_dir}/bad-config2/formats/invalid-config/config.truncated.json:3 +✘ error: invalid value for property “/ui/theme-defs/invalid-theme/styles/text/color” + reason: invalid color -- “InvalidColor” + |  reason: Unknown color: 'InvalidColor'. See https://jonasjacek.github.io/colors/ for a list of supported color names + --> {test_dir}/bad-config2/configs/invalid-theme/config.json:8 + = help: Property Synopsis + /ui/theme-defs/invalid-theme/styles/text/color #hex|color_name + Description + The foreground color value for this style. The value can be the name of an xterm color, the hexadecimal value, or a theme variable reference. + Examples + #fff + Green + $black ✘ error: missing value for property “/log/annotations/org.lnav.test.no-condition/condition” reason: SQL expression is invalid  |  reason: incomplete input @@ -70,15 +82,3 @@ /log/annotations/org.lnav.test.no-handler/handler