diff --git a/docs/schemas/event-session-loaded-v1.schema.json b/docs/schemas/event-session-loaded-v1.schema.json
new file mode 100644
index 00000000..f64f0511
--- /dev/null
+++ b/docs/schemas/event-session-loaded-v1.schema.json
@@ -0,0 +1,16 @@
+{
+ "$id": "https://lnav.org/event-session-loaded-v1.schema.json",
+ "title": "https://lnav.org/event-session-loaded-v1.schema.json",
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "description": "Event fired when a session is loaded.",
+ "properties": {
+ "$schema": {
+ "title": "/$schema",
+ "type": "string",
+ "examples": [
+ "https://lnav.org/event-session-loaded-v1.schema.json"
+ ]
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/docs/source/events.rst b/docs/source/events.rst
index 54cecdfd..8318abf6 100644
--- a/docs/source/events.rst
+++ b/docs/source/events.rst
@@ -51,3 +51,6 @@ The following tables describe the schema of the event JSON objects.
.. jsonschema:: ../schemas/event-log-msg-detected-v1.schema.json#
:lift_description:
+
+.. jsonschema:: ../schemas/event-session-loaded-v1.schema.json#
+ :lift_description:
diff --git a/docs/tutorials/tutorial-lib/formats/tutorial-lib/tutorial.sql b/docs/tutorials/tutorial-lib/formats/tutorial-lib/tutorial.sql
index 80af3629..28133577 100644
--- a/docs/tutorials/tutorial-lib/formats/tutorial-lib/tutorial.sql
+++ b/docs/tutorials/tutorial-lib/formats/tutorial-lib/tutorial.sql
@@ -1,3 +1,5 @@
+
+-- Tracks the current step in the tutorial
CREATE TABLE lnav_tutorial_step
(
name TEXT NOT NULL PRIMARY KEY,
@@ -7,6 +9,7 @@ CREATE TABLE lnav_tutorial_step
INSERT INTO lnav_tutorial_step
VALUES ('tutorial1', 1);
+-- A description of each step in the tutorial with its achievements
CREATE TABLE lnav_tutorial_steps
(
name TEXT NOT NULL,
@@ -15,6 +18,7 @@ CREATE TABLE lnav_tutorial_steps
PRIMARY KEY (name, step)
);
+-- Tracks the progress through the achievements in a step of the tutorial
CREATE TABLE IF NOT EXISTS lnav_tutorial_progress
(
name TEXT NOT NULL,
@@ -34,6 +38,8 @@ CREATE TABLE IF NOT EXISTS lnav_tutorial_lines
log_comment TEXT
);
+-- Copy the tutorial data from the markdown frontmatter to
+-- the appropriate tables.
CREATE TRIGGER IF NOT EXISTS add_tutorial_data
AFTER INSERT
ON lnav_events
@@ -63,7 +69,14 @@ BEGIN
REPLACE INTO lnav_user_notifications (id, views, message)
SELECT *
FROM lnav_tutorial_log_notification;
+END;
+CREATE TRIGGER IF NOT EXISTS tutorial_move_log_after_load
+ AFTER INSERT
+ ON lnav_events
+ WHEN jget(new.content, '/$schema') = 'https://lnav.org/event-session-loaded-v1.schema.json'
+BEGIN
+ UPDATE lnav_views SET top = 0 WHERE name = 'log';
END;
CREATE TRIGGER IF NOT EXISTS lnav_tutorial_view_listener UPDATE OF top
@@ -122,9 +135,9 @@ SELECT *
FROM (SELECT 'org.lnav.tutorial.log' AS id, '["log"]' AS views, jget(value, '/notification') AS message
FROM lnav_tutorial_remaining_achievements
UNION ALL
- SELECT 'org.lnav.tutorial.log' AS id,
- '["log"]' AS views,
- 'Press y to go to the next step in the tutorial' AS message)
+ SELECT 'org.lnav.tutorial.log' AS id,
+ '["log"]' AS views,
+ 'Press `y` to go to the next step in the tutorial' AS message)
LIMIT 1;
CREATE TRIGGER IF NOT EXISTS lnav_tutorial_progress_listener
@@ -138,4 +151,4 @@ BEGIN
END;
REPLACE INTO lnav_user_notifications (id, views, message)
- VALUES ('org.lnav.tutorial.text', '["text"]', 'Press "q" to go to the log view')
+ VALUES ('org.lnav.tutorial.text', '["text"]', 'Press `q` to go to the log view')
diff --git a/docs/tutorials/tutorial1/index.md b/docs/tutorials/tutorial1/index.md
index 908479bd..1c4da716 100644
--- a/docs/tutorials/tutorial1/index.md
+++ b/docs/tutorials/tutorial1/index.md
@@ -5,7 +5,9 @@ steps:
description: "Move to an error"
view_ptr: /top
view_value: 6
- notification: "Press e/Shift+E to move through the errors"
+ notification: |
+ Press `e`/`Shift+E` to move through the
+ errors
comment: |
You found the error!
[Log formats](https://docs.lnav.org/en/latest/formats.html#format-file-reference)
@@ -14,7 +16,9 @@ steps:
how the levels are displayed.
move-to-warning:
description: "Move to a warning"
- notification: "Press w/Shift+W to move through the warnings"
+ notification: |
+ Press `w`/`Shift+W` to move through the
+ warnings
view_ptr: /top
view_value: 3
comment: |
@@ -25,12 +29,12 @@ steps:
view.
- search-for-term:
description: "Search for something"
- notification: "Press / to search for '1AF9...'"
+ notification: "Press `/` to search for '1AF9...'"
view_ptr: /search
view_value: 1AF9293A-F42D-4318-BCDF-60234B240955
move-to-next-hit:
description: "Move to the next hit"
- notification: "Press n/Shift+N to move through the search hits"
+ notification: "Press `n`/`Shift+N` to move through the search hits"
view_ptr: /top
view_value: 53
comment: |
@@ -43,7 +47,7 @@ steps:
the way back to the start of the line.
move-right:
description: "Move to the right"
- notification: "Press > to move horizontally to view the search hit"
+ notification: "Press `>` to move horizontally to view the search hit"
view_ptr: /left
view_value: 150
---
@@ -71,8 +75,8 @@ can then use the following hotkeys to jump to them in the log view:
To complete this step in the tutorial, you'll need to navigate to the
errors and warnings in the sample log file. You can check the upper-right
-status bar for tips on what you need to do next. Now, press `q` to switch
-to the log view and begin navigating the sample log file.
+↗↗↗ status bar for tips on what you need to do next. Now, press `q` to
+switch to the log view and begin navigating the sample log file.
## Step 2
@@ -87,12 +91,13 @@ Press `q` to switch to the log view and try searching for the UUID.
## Conclusion
-That's all for now, visit https://lnav.org/downloads to find how to
-download/install a copy of lnav for your system. The full documentation
-is available at https://docs.lnav.org.
+That's all for now, thanks for your time! Visit the
+[downloads](https://lnav.org/downloads) page to find out how to
+download or install **lnav** for your system. The full
+documentation is available at https://docs.lnav.org
## Colophon
The source for this tutorial is available here:
-https://github.com/tstack/lnav/tree/master/docs/tutorials/tutorial1
+https://github.com/tstack/lnav/tree/master/docs/tutorials/
diff --git a/src/dump_internals.cc b/src/dump_internals.cc
index 79752d83..83177696 100644
--- a/src/dump_internals.cc
+++ b/src/dump_internals.cc
@@ -49,6 +49,7 @@ dump_internals(const char* internals_dir)
&lnav::events::file::open::handlers,
&lnav::events::file::format_detected::handlers,
&lnav::events::log::msg_detected::handlers,
+ &lnav::events::session::loaded::handlers,
})
{
dump_schema_to(*handlers, internals_dir);
diff --git a/src/help.md b/src/help.md
index d49cefd6..2a7aa21c 100644
--- a/src/help.md
+++ b/src/help.md
@@ -529,5 +529,5 @@ http://lnav.org
For support questions, email:
-lnav@googlegroups.com
-support@lnav.org
+* lnav@googlegroups.com
+* support@lnav.org
diff --git a/src/lnav.cc b/src/lnav.cc
index b62a4b97..b58d9640 100644
--- a/src/lnav.cc
+++ b/src/lnav.cc
@@ -1336,7 +1336,8 @@ looper()
= &lnav_data.ld_exec_context;
lnav_data.ld_status[LNS_TOP].set_top(0);
- lnav_data.ld_status[LNS_TOP].set_enabled(false);
+ lnav_data.ld_status[LNS_TOP].set_default_role(
+ role_t::VCR_INACTIVE_STATUS);
lnav_data.ld_status[LNS_TOP].set_data_source(&lnav_data.ld_top_source);
lnav_data.ld_status[LNS_BOTTOM].set_top(-(rlc->get_height() + 1));
for (auto& stat_bar : lnav_data.ld_status) {
diff --git a/src/lnav.events.cc b/src/lnav.events.cc
index bf04ebd0..d341493b 100644
--- a/src/lnav.events.cc
+++ b/src/lnav.events.cc
@@ -105,6 +105,20 @@ const typed_json_path_container msg_detected::handlers = typed_jso
} // namespace log
+namespace session {
+
+const std::string loaded::SCHEMA_ID
+ = "https://lnav.org/event-session-loaded-v1.schema.json";
+
+const typed_json_path_container loaded::handlers = typed_json_path_container{
+ yajlpp::property_handler("$schema").for_field(&loaded::l_schema)
+ .with_example(loaded::SCHEMA_ID),
+}
+ .with_schema_id2(loaded::SCHEMA_ID)
+ .with_description2("Event fired when a session is loaded.");
+
+} // namespace session
+
int
register_events_tab(sqlite3* db)
{
diff --git a/src/lnav.events.hh b/src/lnav.events.hh
index 1ad71a3d..d4a95266 100644
--- a/src/lnav.events.hh
+++ b/src/lnav.events.hh
@@ -75,6 +75,17 @@ struct msg_detected {
} // namespace log
+namespace session {
+
+struct loaded {
+ std::string l_schema{SCHEMA_ID};
+
+ static const std::string SCHEMA_ID;
+ static const typed_json_path_container handlers;
+};
+
+} // namespace session
+
int register_events_tab(sqlite3* db);
namespace details {
diff --git a/src/md4cpp.cc b/src/md4cpp.cc
index 33a18c9f..40fc2a8b 100644
--- a/src/md4cpp.cc
+++ b/src/md4cpp.cc
@@ -37,254 +37,267 @@
namespace md4cpp {
- static const typed_json_path_container xml_entity_handlers = {
- yajlpp::property_handler("characters").for_field(&xml_entity::xe_chars),
- };
-
- static const typed_json_path_container xml_entity_map_handlers
- = {
- yajlpp::pattern_property_handler("(?\\&\\w+;?)")
- .with_synopsis("")
- .with_path_provider(
- [](struct xml_entity_map *xem,
- std::vector &paths_out) {
- for (const auto &iter: xem->xem_entities) {
- paths_out.emplace_back(iter.first);
- }
- })
- .with_obj_provider(
- [](const yajlpp_provider_context &ypc, xml_entity_map *xem) {
- auto entity_name = ypc.get_substr(0);
- return &xem->xem_entities[entity_name];
- })
- .with_children(xml_entity_handlers),
- };
-
- static const typed_json_path_container emoji_handlers = {
- yajlpp::property_handler("emoji").for_field(&emoji::e_value),
- yajlpp::property_handler("shortname").for_field(&emoji::e_shortname),
- };
-
- static const typed_json_path_container emoji_map_handlers = {
- yajlpp::property_handler("emojis#")
- .for_field(&emoji_map::em_emojis)
- .with_children(emoji_handlers),
- };
-
- static xml_entity_map
- load_xml_entity_map() {
- static const intern_string_t name
- = intern_string::lookup(xml_entities_json.get_name());
- auto parse_res
- = xml_entity_map_handlers.parser_for(name).with_ignore_unused(true).of(
- xml_entities_json.to_string_fragment());
-
- assert(parse_res.isOk());
-
- return parse_res.unwrap();
+static const typed_json_path_container xml_entity_handlers = {
+ yajlpp::property_handler("characters").for_field(&xml_entity::xe_chars),
+};
+
+static const typed_json_path_container xml_entity_map_handlers
+ = {
+ yajlpp::pattern_property_handler("(?\\&\\w+;?)")
+ .with_synopsis("")
+ .with_path_provider(
+ [](struct xml_entity_map* xem,
+ std::vector& paths_out) {
+ for (const auto& iter : xem->xem_entities) {
+ paths_out.emplace_back(iter.first);
+ }
+ })
+ .with_obj_provider(
+ [](const yajlpp_provider_context& ypc, xml_entity_map* xem) {
+ auto entity_name = ypc.get_substr(0);
+ return &xem->xem_entities[entity_name];
+ })
+ .with_children(xml_entity_handlers),
+};
+
+static const typed_json_path_container emoji_handlers = {
+ yajlpp::property_handler("emoji").for_field(&emoji::e_value),
+ yajlpp::property_handler("shortname").for_field(&emoji::e_shortname),
+};
+
+static const typed_json_path_container emoji_map_handlers = {
+ yajlpp::property_handler("emojis#")
+ .for_field(&emoji_map::em_emojis)
+ .with_children(emoji_handlers),
+};
+
+static xml_entity_map
+load_xml_entity_map()
+{
+ static const intern_string_t name
+ = intern_string::lookup(xml_entities_json.get_name());
+ auto parse_res
+ = xml_entity_map_handlers.parser_for(name).with_ignore_unused(true).of(
+ xml_entities_json.to_string_fragment());
+
+ assert(parse_res.isOk());
+
+ return parse_res.unwrap();
+}
+
+const xml_entity_map&
+get_xml_entity_map()
+{
+ static const auto retval = load_xml_entity_map();
+
+ return retval;
+}
+
+static emoji_map
+load_emoji_map()
+{
+ static const intern_string_t name
+ = intern_string::lookup(emojis_json.get_name());
+ auto parse_res
+ = emoji_map_handlers.parser_for(name).with_ignore_unused(true).of(
+ emojis_json.to_string_fragment());
+
+ assert(parse_res.isOk());
+
+ auto retval = parse_res.unwrap();
+ for (auto& em : retval.em_emojis) {
+ retval.em_shortname2emoji.emplace(em.e_shortname, em);
}
- const xml_entity_map &
- get_xml_entity_map() {
- static const auto retval = load_xml_entity_map();
-
- return retval;
+ return retval;
+}
+
+const emoji_map&
+get_emoji_map()
+{
+ static const auto retval = load_emoji_map();
+
+ return retval;
+}
+
+struct parse_userdata {
+ event_handler& pu_handler;
+ std::string pu_error_msg;
+};
+
+static event_handler::block
+build_block(MD_BLOCKTYPE type, void* detail)
+{
+ switch (type) {
+ case MD_BLOCK_DOC:
+ return event_handler::block_doc{};
+ case MD_BLOCK_QUOTE:
+ return event_handler::block_quote{};
+ case MD_BLOCK_UL:
+ return static_cast(detail);
+ case MD_BLOCK_OL:
+ return static_cast(detail);
+ case MD_BLOCK_LI:
+ return static_cast(detail);
+ case MD_BLOCK_HR:
+ return event_handler::block_hr{};
+ case MD_BLOCK_H:
+ return static_cast(detail);
+ case MD_BLOCK_CODE:
+ return static_cast(detail);
+ case MD_BLOCK_HTML:
+ return event_handler::block_html{};
+ case MD_BLOCK_P:
+ return event_handler::block_p{};
+ case MD_BLOCK_TABLE:
+ return static_cast(detail);
+ case MD_BLOCK_THEAD:
+ return event_handler::block_thead{};
+ case MD_BLOCK_TBODY:
+ return event_handler::block_tbody{};
+ case MD_BLOCK_TR:
+ return event_handler::block_tr{};
+ case MD_BLOCK_TH:
+ return event_handler::block_th{};
+ case MD_BLOCK_TD:
+ return static_cast(detail);
}
- static emoji_map
- load_emoji_map() {
- static const intern_string_t name
- = intern_string::lookup(emojis_json.get_name());
- auto parse_res
- = emoji_map_handlers.parser_for(name).with_ignore_unused(true).of(
- emojis_json.to_string_fragment());
+ return {};
+}
+
+static event_handler::span
+build_span(MD_SPANTYPE type, void* detail)
+{
+ switch (type) {
+ case MD_SPAN_EM:
+ return event_handler::span_em{};
+ case MD_SPAN_STRONG:
+ return event_handler::span_strong{};
+ case MD_SPAN_A:
+ return static_cast(detail);
+ case MD_SPAN_IMG:
+ return static_cast(detail);
+ case MD_SPAN_CODE:
+ return event_handler::span_code{};
+ case MD_SPAN_DEL:
+ return event_handler::span_del{};
+ case MD_SPAN_U:
+ return event_handler::span_u{};
+ default:
+ break;
+ }
- assert(parse_res.isOk());
+ return {};
+}
- auto retval = parse_res.unwrap();
- for (auto &em: retval.em_emojis) {
- retval.em_shortname2emoji.emplace(em.e_shortname, em);
- }
+static int
+md4cpp_enter_block(MD_BLOCKTYPE type, void* detail, void* userdata)
+{
+ auto* pu = static_cast(userdata);
- return retval;
+ auto enter_res = pu->pu_handler.enter_block(build_block(type, detail));
+ if (enter_res.isErr()) {
+ pu->pu_error_msg = enter_res.unwrapErr();
+ return 1;
}
- const emoji_map &
- get_emoji_map() {
- static const auto retval = load_emoji_map();
+ return 0;
+}
- return retval;
- }
-
- struct parse_userdata {
- event_handler &pu_handler;
- std::string pu_error_msg;
- };
-
- static event_handler::block
- build_block(MD_BLOCKTYPE type, void *detail) {
- switch (type) {
- case MD_BLOCK_DOC:
- return event_handler::block_doc{};
- case MD_BLOCK_QUOTE:
- return event_handler::block_quote{};
- case MD_BLOCK_UL:
- return static_cast(detail);
- case MD_BLOCK_OL:
- return static_cast(detail);
- case MD_BLOCK_LI:
- return static_cast(detail);
- case MD_BLOCK_HR:
- return event_handler::block_hr{};
- case MD_BLOCK_H:
- return static_cast(detail);
- case MD_BLOCK_CODE:
- return static_cast(detail);
- case MD_BLOCK_HTML:
- return event_handler::block_html{};
- case MD_BLOCK_P:
- return event_handler::block_p{};
- case MD_BLOCK_TABLE:
- return static_cast(detail);
- case MD_BLOCK_THEAD:
- return event_handler::block_thead{};
- case MD_BLOCK_TBODY:
- return event_handler::block_tbody{};
- case MD_BLOCK_TR:
- return event_handler::block_tr{};
- case MD_BLOCK_TH:
- return event_handler::block_th{};
- case MD_BLOCK_TD:
- return static_cast(detail);
- }
-
- return {};
- }
+static int
+md4cpp_leave_block(MD_BLOCKTYPE type, void* detail, void* userdata)
+{
+ auto* pu = static_cast(userdata);
- static event_handler::span
- build_span(MD_SPANTYPE type, void *detail) {
- switch (type) {
- case MD_SPAN_EM:
- return event_handler::span_em{};
- case MD_SPAN_STRONG:
- return event_handler::span_strong{};
- case MD_SPAN_A:
- return static_cast(detail);
- case MD_SPAN_IMG:
- return static_cast(detail);
- case MD_SPAN_CODE:
- return event_handler::span_code{};
- case MD_SPAN_DEL:
- return event_handler::span_del{};
- case MD_SPAN_U:
- return event_handler::span_u{};
- default:
- break;
- }
-
- return {};
+ auto leave_res = pu->pu_handler.leave_block(build_block(type, detail));
+ if (leave_res.isErr()) {
+ pu->pu_error_msg = leave_res.unwrapErr();
+ return 1;
}
- static int
- md4cpp_enter_block(MD_BLOCKTYPE type, void *detail, void *userdata) {
- auto *pu = static_cast(userdata);
+ return 0;
+}
- auto enter_res = pu->pu_handler.enter_block(build_block(type, detail));
- if (enter_res.isErr()) {
- pu->pu_error_msg = enter_res.unwrapErr();
- return 1;
- }
+static int
+md4cpp_enter_span(MD_SPANTYPE type, void* detail, void* userdata)
+{
+ auto* pu = static_cast(userdata);
- return 0;
+ auto enter_res = pu->pu_handler.enter_span(build_span(type, detail));
+ if (enter_res.isErr()) {
+ pu->pu_error_msg = enter_res.unwrapErr();
+ return 1;
}
- static int
- md4cpp_leave_block(MD_BLOCKTYPE type, void *detail, void *userdata) {
- auto *pu = static_cast(userdata);
+ return 0;
+}
- auto leave_res = pu->pu_handler.leave_block(build_block(type, detail));
- if (leave_res.isErr()) {
- pu->pu_error_msg = leave_res.unwrapErr();
- return 1;
- }
+static int
+md4cpp_leave_span(MD_SPANTYPE type, void* detail, void* userdata)
+{
+ auto* pu = static_cast(userdata);
- return 0;
+ auto leave_res = pu->pu_handler.leave_span(build_span(type, detail));
+ if (leave_res.isErr()) {
+ pu->pu_error_msg = leave_res.unwrapErr();
+ return 1;
}
- static int
- md4cpp_enter_span(MD_SPANTYPE type, void *detail, void *userdata) {
- auto *pu = static_cast(userdata);
-
- auto enter_res = pu->pu_handler.enter_span(build_span(type, detail));
- if (enter_res.isErr()) {
- pu->pu_error_msg = enter_res.unwrapErr();
- return 1;
- }
-
- return 0;
+ return 0;
+}
+
+static int
+md4cpp_text(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* userdata)
+{
+ auto* pu = static_cast(userdata);
+ auto text_res = pu->pu_handler.text(type, string_fragment(text, 0, size));
+ if (text_res.isErr()) {
+ pu->pu_error_msg = text_res.unwrapErr();
+ return 1;
}
- static int
- md4cpp_leave_span(MD_SPANTYPE type, void *detail, void *userdata) {
- auto *pu = static_cast(userdata);
+ return 0;
+}
+
+namespace details {
+Result
+parse(const string_fragment& sf, event_handler& eh)
+{
+ const char* utf8_errmsg = nullptr;
+ int utf8_faulty_bytes = 0;
+
+ auto utf8_erroff = is_utf8((unsigned char*) sf.data(),
+ sf.length(),
+ &utf8_errmsg,
+ &utf8_faulty_bytes);
+ if (utf8_errmsg != nullptr) {
+ return Err(
+ fmt::format(FMT_STRING("file has invalid UTF-8 at offset {}: {}"),
+ utf8_erroff,
+ utf8_errmsg));
+ }
- auto leave_res = pu->pu_handler.leave_span(build_span(type, detail));
- if (leave_res.isErr()) {
- pu->pu_error_msg = leave_res.unwrapErr();
- return 1;
- }
+ MD_PARSER parser = {0};
+ auto pu = parse_userdata{eh};
- return 0;
- }
+ parser.abi_version = 0;
+ parser.flags = (MD_DIALECT_GITHUB | MD_FLAG_UNDERLINE)
+ & ~(MD_FLAG_PERMISSIVEAUTOLINKS);
+ parser.enter_block = md4cpp_enter_block;
+ parser.leave_block = md4cpp_leave_block;
+ parser.enter_span = md4cpp_enter_span;
+ parser.leave_span = md4cpp_leave_span;
+ parser.text = md4cpp_text;
- static int
- md4cpp_text(MD_TEXTTYPE type, const MD_CHAR *text, MD_SIZE size, void *userdata) {
- auto *pu = static_cast(userdata);
- auto text_res = pu->pu_handler.text(type, string_fragment(text, 0, size));
- if (text_res.isErr()) {
- pu->pu_error_msg = text_res.unwrapErr();
- return 1;
- }
+ auto rc = md_parse(sf.data(), sf.length(), &parser, &pu);
- return 0;
+ if (rc == 0) {
+ return Ok();
}
- namespace details {
- Result
- parse(const string_fragment &sf, event_handler &eh) {
- const char *utf8_errmsg = nullptr;
- int utf8_faulty_bytes = 0;
-
- auto utf8_erroff = is_utf8((unsigned char *) sf.data(),
- sf.length(),
- &utf8_errmsg,
- &utf8_faulty_bytes);
- if (utf8_errmsg != nullptr) {
- return Err(
- fmt::format(FMT_STRING("file has invalid UTF-8 at offset {}: {}"),
- utf8_erroff,
- utf8_errmsg));
- }
-
- MD_PARSER parser = {0};
- auto pu = parse_userdata{eh};
-
- parser.abi_version = 0;
- parser.flags = MD_DIALECT_GITHUB | MD_FLAG_UNDERLINE;
- parser.enter_block = md4cpp_enter_block;
- parser.leave_block = md4cpp_leave_block;
- parser.enter_span = md4cpp_enter_span;
- parser.leave_span = md4cpp_leave_span;
- parser.text = md4cpp_text;
-
- auto rc = md_parse(sf.data(), sf.length(), &parser, &pu);
-
- if (rc == 0) {
- return Ok();
- }
-
- return Err(pu.pu_error_msg);
- }
- } // namespace details
+ return Err(pu.pu_error_msg);
+}
+} // namespace details
} // namespace md4cpp
diff --git a/src/session_data.cc b/src/session_data.cc
index a0dbd9cf..e67844cd 100644
--- a/src/session_data.cc
+++ b/src/session_data.cc
@@ -46,6 +46,7 @@
#include "base/paths.hh"
#include "command_executor.hh"
#include "config.h"
+#include "lnav.events.hh"
#include "lnav.hh"
#include "lnav_util.hh"
#include "log_format_ext.hh"
@@ -964,6 +965,9 @@ load_session()
lnav_data.ld_text_source.text_filters_changed();
}
};
+
+ lnav::events::publish(lnav_data.ld_db.in(),
+ lnav::events::session::loaded{});
}
static void
diff --git a/src/statusview_curses.cc b/src/statusview_curses.cc
index c73857f4..f27bff00 100644
--- a/src/statusview_curses.cc
+++ b/src/statusview_curses.cc
@@ -101,7 +101,7 @@ statusview_curses::do_update()
top = this->sc_top < 0 ? height + this->sc_top : this->sc_top;
right = width;
auto attrs = vc.attrs_for_role(
- this->sc_enabled ? role_t::VCR_STATUS : role_t::VCR_INACTIVE_STATUS);
+ this->sc_enabled ? this->sc_default_role : role_t::VCR_INACTIVE_STATUS);
auto pair = vc.ensure_color_pair(attrs.ta_fg_color, attrs.ta_bg_color);
wattr_set(this->sc_window, attrs.ta_attrs, pair, nullptr);
diff --git a/src/statusview_curses.hh b/src/statusview_curses.hh
index 73f8f309..c9c59161 100644
--- a/src/statusview_curses.hh
+++ b/src/statusview_curses.hh
@@ -171,6 +171,9 @@ public:
void set_enabled(bool value) { this->sc_enabled = value; }
bool get_enabled() const { return this->sc_enabled; }
+ void set_default_role(role_t role) { this->sc_default_role = role; }
+ role_t get_default_role() const { return this->sc_default_role; }
+
void window_change();
void do_update() override;
@@ -180,6 +183,7 @@ private:
WINDOW* sc_window{nullptr};
int sc_top{0};
bool sc_enabled{true};
+ role_t sc_default_role{role_t::VCR_STATUS};
};
#endif
diff --git a/src/top_status_source.cc b/src/top_status_source.cc
index 34670cf9..4a0dcaac 100644
--- a/src/top_status_source.cc
+++ b/src/top_status_source.cc
@@ -34,8 +34,13 @@
#include "base/injector.hh"
#include "bound_tags.hh"
#include "config.h"
+#include "lnav.hh"
#include "lnav_config.hh"
#include "logfile_sub_source.hh"
+#include "md2attr_line.hh"
+#include "md4cpp.hh"
+#include "shlex.hh"
+#include "shlex.resolver.hh"
#include "sql_util.hh"
#include "sqlitepp.client.hh"
@@ -107,7 +112,23 @@ top_status_source::update_user_msg()
auto fetch_res = um_stmt.ums_stmt.fetch_row();
fetch_res.match(
[&al](const std::string& value) {
- al.with_ansi_string(value);
+ shlex lexer(value);
+ std::string user_note;
+
+ lexer.with_ignore_quotes(true).eval(
+ user_note, lnav_data.ld_exec_context.ec_global_vars);
+
+ md2attr_line mdal;
+ auto parse_res = md4cpp::parse(user_note, mdal);
+ if (parse_res.isOk()) {
+ al = parse_res.unwrap();
+ } else {
+ log_error("failed to parse user note as markdown: %s",
+ parse_res.unwrapErr().c_str());
+ al = user_note;
+ }
+
+ scrub_ansi_string(al.get_string(), &al.get_attrs());
al.append(" ");
},
[](const prepared_stmt::end_of_rows&) {},
diff --git a/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out b/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out
index 2b5d658f..b6b30316 100644
--- a/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out
+++ b/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out
@@ -664,16 +664,12 @@ commands, which is especially useful when scripting lnav.
For more information, visit the lnav website at:
-[4mhttp://lnav.org[1][0m
-
- ▌[1] - http://lnav.org
+http://lnav.org
For support questions, email:
-[4mlnav@googlegroups.com[1][0m [4msupport@lnav.org[2][0m
-
- ▌[1] - mailto:lnav@googlegroups.com
- ▌[2] - mailto:support@lnav.org
+ [33m•[0m lnav@googlegroups.com
+ [33m•[0m support@lnav.org
[1mCommand Reference[0m