[theme] use default styles for cursor-line/selected-text if they are missing from the current theme

Some markdown-related changes as well
pull/1265/head
Tim Stack 2 weeks ago
parent 4fd6b62380
commit 50e895c289

@ -7,23 +7,27 @@ Features:
* The `log_opid` column on log vtables can now by `UPDATE`d
so that you can manually set an opid on log messages that
don't have one. Setting an opid allows messages to show
up in the gantt chart view.
up in the Gantt chart view.
* Add support for GitHub Markdown Alerts.
Interface Changes:
* In the Gantt chart view, pressing `ENTER` will focus on
the preview pane so you can scroll through messages
the preview pane, so you can scroll through messages
with the selected Op ID.
* With mouse mode enabled, `CTRL` can be used as an alternate
to `SHIFT` when clicking/dragging in the main view to
highlight lines. A few terminals capture shift+clicks as a
way to select text and do not pass them to the application.
* Clicking on an internal link in a Markdown document will move
to that section.
Bug Fixes:
* Log messages in formats with custom timestamp formats were
not being converted to the local timezone.
* The timezone offset is now shown in the parser details
overlay for log messages.
* If a theme does not define `cursor-line` or `selected-text`
styles, the styles from the default theme will be used.
Maintenance:
* You can now do an `UPDATE` on the `lnav_top_view` SQL view.

@ -333,6 +333,36 @@ scrub_ws(const char* in, ssize_t len)
return retval;
}
static constexpr const char* const SUPERSCRIPT_NUMS[] = {
"",
"¹",
"²",
"³",
"",
"",
"",
"",
"",
"",
};
std::string
to_superscript(const std::string& in)
{
std::string retval;
for (const auto ch : in) {
if (isdigit(ch)) {
auto index = ch - '0';
retval.append(SUPERSCRIPT_NUMS[index]);
} else {
retval.push_back(ch);
}
}
return retval;
}
namespace fmt {
auto
formatter<lnav::tainted_string>::format(const lnav::tainted_string& ts,

@ -246,6 +246,15 @@ on_blank(const std::string& str, const std::string& def)
return str;
}
std::string to_superscript(const std::string& in);
template<typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
inline std::string
to_superscript(T in)
{
return to_superscript(fmt::to_string(in));
}
namespace lnav {
class tainted_string {
public:
@ -282,8 +291,8 @@ private:
namespace fmt {
template<>
struct formatter<lnav::tainted_string> : formatter<string_view> {
auto format(const lnav::tainted_string& ts,
format_context& ctx) -> decltype(ctx.out()) const;
auto format(const lnav::tainted_string& ts, format_context& ctx)
-> decltype(ctx.out()) const;
};
} // namespace fmt

@ -573,7 +573,7 @@ md2attr_line::leave_span(const md4cpp::event_handler::span& sp)
VC_STYLE.value(text_attrs{A_UNDERLINE}),
});
} else if (sp.is<MD_SPAN_A_DETAIL*>()) {
auto* a_detail = sp.get<MD_SPAN_A_DETAIL*>();
const auto* a_detail = sp.get<MD_SPAN_A_DETAIL*>();
auto href_str = std::string(a_detail->href.text, a_detail->href.size);
line_range lr{
static_cast<int>(this->ml_span_starts.back()),
@ -585,8 +585,9 @@ md2attr_line::leave_span(const md4cpp::event_handler::span& sp)
});
this->append_url_footnote(href_str);
} else if (sp.is<MD_SPAN_IMG_DETAIL*>()) {
auto* img_detail = sp.get<MD_SPAN_IMG_DETAIL*>();
auto src_str = std::string(img_detail->src.text, img_detail->src.size);
const auto* img_detail = sp.get<MD_SPAN_IMG_DETAIL*>();
const auto src_str
= std::string(img_detail->src.text, img_detail->src.size);
this->append_url_footnote(src_str);
}
@ -747,7 +748,7 @@ md2attr_line::to_attr_line(const pugi::xml_node& doc)
.append(" ")
.append(
lnav::string::attrs::href(link_label, src_href.value()))
.appendf(FMT_STRING("[{}]"), this->ml_footnotes.size() + 1);
.append(to_superscript(this->ml_footnotes.size() + 1));
auto href
= attr_line_t()
@ -1014,7 +1015,7 @@ md2attr_line::text(MD_TEXTTYPE tt, const string_fragment& sf)
std::string span_text;
auto loop_res = REPL_RE.capture_from(sf).for_each(
[&span_text](lnav::pcre2pp::match_data& md) {
[&span_text](const lnav::pcre2pp::match_data& md) {
span_text += md.leading();
auto matched = *md[0];
@ -1054,12 +1055,8 @@ md2attr_line::text(MD_TEXTTYPE tt, const string_fragment& sf)
void
md2attr_line::append_url_footnote(std::string href_str)
{
if (startswith(href_str, "#")) {
return;
}
auto is_internal = startswith(href_str, "#");
auto& last_block = this->ml_blocks.back();
last_block.appendf(FMT_STRING("[{}]"), this->ml_footnotes.size() + 1);
last_block.with_attr(string_attr{
line_range{
(int) this->ml_span_starts.back(),
@ -1067,6 +1064,15 @@ md2attr_line::append_url_footnote(std::string href_str)
},
VC_STYLE.value(text_attrs{A_UNDERLINE}),
});
if (is_internal) {
return;
}
if (this->ml_last_superscript_index == last_block.length()) {
last_block.append("\u02d2");
}
last_block.append(to_superscript(this->ml_footnotes.size() + 1));
this->ml_last_superscript_index = last_block.length();
if (this->ml_source_path && href_str.find(':') == std::string::npos) {
auto link_path = ghc::filesystem::absolute(
this->ml_source_path.value().parent_path() / href_str);

@ -91,6 +91,7 @@ private:
std::vector<std::pair<std::string, size_t>> ml_html_starts;
std::vector<attr_line_t> ml_footnotes;
int32_t ml_code_depth{0};
ssize_t ml_last_superscript_index{-1};
};
#endif

@ -49,7 +49,8 @@ to_text_line(const std::vector<attr_line_t>& lines)
});
}
plain_text_source::plain_text_source(const std::string& text)
plain_text_source::
plain_text_source(const std::string& text)
{
size_t start = 0, end;
@ -64,12 +65,14 @@ plain_text_source::plain_text_source(const std::string& text)
this->tds_longest_line = this->compute_longest_line();
}
plain_text_source::plain_text_source(const std::vector<std::string>& text_lines)
plain_text_source::
plain_text_source(const std::vector<std::string>& text_lines)
{
this->replace_with(text_lines);
}
plain_text_source::plain_text_source(const std::vector<attr_line_t>& text_lines)
plain_text_source::
plain_text_source(const std::vector<attr_line_t>& text_lines)
: tds_lines(to_text_line(text_lines))
{
this->tds_longest_line = this->compute_longest_line();
@ -432,8 +435,7 @@ plain_text_source::row_for_anchor(const std::string& id)
meta.m_sections_root.get(),
[this, &id, &retval](const lnav::document::hier_node* node) {
for (const auto& child_pair : node->hn_named_children) {
const auto& child_anchor
= text_anchors::to_anchor_string(child_pair.first);
const auto& child_anchor = to_anchor_string(child_pair.first);
if (child_anchor != id) {
continue;
@ -456,8 +458,7 @@ plain_text_source::get_anchors()
this->tds_doc_sections.m_sections_root.get(),
[&retval](const lnav::document::hier_node* node) {
for (const auto& child_pair : node->hn_named_children) {
retval.emplace(
text_anchors::to_anchor_string(child_pair.first));
retval.emplace(to_anchor_string(child_pair.first));
}
});
@ -488,8 +489,7 @@ plain_text_source::anchor_for_row(vis_line_t vl)
|| this->tds_text_format == text_format_t::TF_MARKDOWN)
&& path_for_line.back().is<std::string>())
{
return text_anchors::to_anchor_string(
path_for_line.back().get<std::string>());
return to_anchor_string(path_for_line.back().get<std::string>());
}
auto comps = path_for_line | lnav::itertools::map([](const auto& elem) {
@ -505,7 +505,7 @@ plain_text_source::anchor_for_row(vis_line_t vl)
}
std::optional<vis_line_t>
plain_text_source::adjacent_anchor(vis_line_t vl, text_anchors::direction dir)
plain_text_source::adjacent_anchor(vis_line_t vl, direction dir)
{
if (vl > this->tds_lines.size()
|| this->tds_doc_sections.m_sections_root == nullptr)
@ -525,14 +525,14 @@ plain_text_source::adjacent_anchor(vis_line_t vl, text_anchors::direction dir)
}
switch (dir) {
case text_anchors::direction::prev: {
case direction::prev: {
if (neighbors_res->cnr_previous) {
return this->line_for_offset(
neighbors_res->cnr_previous.value()->hn_start);
}
break;
}
case text_anchors::direction::next: {
case direction::next: {
if (neighbors_res->cnr_next) {
return this->line_for_offset(
neighbors_res->cnr_next.value()->hn_start);
@ -585,14 +585,14 @@ plain_text_source::adjacent_anchor(vis_line_t vl, text_anchors::direction dir)
}
switch (dir) {
case text_anchors::direction::prev: {
case direction::prev: {
if (neighbors_res->cnr_previous) {
return this->line_for_offset(
neighbors_res->cnr_previous.value()->hn_start);
}
break;
}
case text_anchors::direction::next: {
case direction::next: {
if (neighbors_res->cnr_next) {
return this->line_for_offset(
neighbors_res->cnr_next.value()->hn_start);

@ -38,6 +38,7 @@
#include "base/time_util.hh"
#include "config.h"
#include "data_scanner.hh"
#include "date/solar_hijri.h"
#include "fmt/format.h"
#include "lnav_config.hh"
#include "log_format_fwd.hh"
@ -693,6 +694,29 @@ textview_curses::handle_mouse(mouse_event& me)
}
this->tc_selection_start = std::nullopt;
}
if (me.me_button == mouse_button_t::BUTTON_LEFT
&& mouse_line.is<main_content>())
{
const auto& [mc_line] = mouse_line.get<main_content>();
attr_line_t al;
this->textview_value_for_row(mc_line, al);
auto get_res = get_string_attr(al.get_attrs(),
&VC_HYPERLINK,
this->lv_left + me.me_press_x);
if (get_res) {
auto href = get_res.value()->sa_value.get<std::string>();
if (startswith(href, "#")) {
auto* ta
= dynamic_cast<text_anchors*>(this->tc_sub_source);
if (ta != nullptr) {
ta->row_for_anchor(href) |
[this](auto row) { this->set_selection(row); };
}
}
}
}
if (this->tc_delegate != nullptr) {
this->tc_delegate->text_handle_mouse(*this, mouse_line, me);
}

@ -848,11 +848,12 @@ void
view_colors::init_roles(const lnav_theme& lt,
lnav_config_listener::error_reporter& reporter)
{
const auto& default_theme = lnav_config.lc_ui_theme_defs["default"];
rgb_color fg, bg;
std::string err;
/* Setup the mappings from roles to actual colors. */
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_TEXT)]
this->get_role_attrs(role_t::VCR_TEXT)
= this->to_attrs(lt, lt.lt_style_text, reporter);
for (int ansi_fg = 0; ansi_fg < 8; ansi_fg++) {
@ -908,122 +909,119 @@ view_colors::init_roles(const lnav_theme& lt,
}
if (lnav_config.lc_ui_dim_text) {
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_TEXT)]
.ra_normal.ta_attrs
|= A_DIM;
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_TEXT)]
.ra_reverse.ta_attrs
|= A_DIM;
this->get_role_attrs(role_t::VCR_TEXT).ra_normal.ta_attrs |= A_DIM;
this->get_role_attrs(role_t::VCR_TEXT).ra_reverse.ta_attrs |= A_DIM;
}
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_SEARCH)]
this->get_role_attrs(role_t::VCR_SEARCH)
= role_attrs{text_attrs{A_REVERSE}, text_attrs{A_REVERSE}};
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_SEARCH)]
.ra_class_name
this->get_role_attrs(role_t::VCR_SEARCH).ra_class_name
= intern_string::lookup("-lnav_styles_search");
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_IDENTIFIER)]
this->get_role_attrs(role_t::VCR_IDENTIFIER)
= this->to_attrs(lt, lt.lt_style_identifier, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_OK)]
this->get_role_attrs(role_t::VCR_OK)
= this->to_attrs(lt, lt.lt_style_ok, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_INFO)]
this->get_role_attrs(role_t::VCR_INFO)
= this->to_attrs(lt, lt.lt_style_info, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_ERROR)]
this->get_role_attrs(role_t::VCR_ERROR)
= this->to_attrs(lt, lt.lt_style_error, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_WARNING)]
this->get_role_attrs(role_t::VCR_WARNING)
= this->to_attrs(lt, lt.lt_style_warning, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_ALT_ROW)]
this->get_role_attrs(role_t::VCR_ALT_ROW)
= this->to_attrs(lt, lt.lt_style_alt_text, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_HIDDEN)]
this->get_role_attrs(role_t::VCR_HIDDEN)
= this->to_attrs(lt, lt.lt_style_hidden, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_CURSOR_LINE)]
this->get_role_attrs(role_t::VCR_CURSOR_LINE)
= this->to_attrs(lt, lt.lt_style_cursor_line, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_DISABLED_CURSOR_LINE)]
if (this->get_role_attrs(role_t::VCR_CURSOR_LINE).ra_normal.empty()) {
this->get_role_attrs(role_t::VCR_CURSOR_LINE) = this->to_attrs(
default_theme, default_theme.lt_style_cursor_line, reporter);
}
this->get_role_attrs(role_t::VCR_DISABLED_CURSOR_LINE)
= this->to_attrs(lt, lt.lt_style_disabled_cursor_line, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_ADJUSTED_TIME)]
if (this->get_role_attrs(role_t::VCR_DISABLED_CURSOR_LINE)
.ra_normal.empty())
{
this->get_role_attrs(role_t::VCR_DISABLED_CURSOR_LINE)
= this->to_attrs(default_theme,
default_theme.lt_style_disabled_cursor_line,
reporter);
}
this->get_role_attrs(role_t::VCR_ADJUSTED_TIME)
= this->to_attrs(lt, lt.lt_style_adjusted_time, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_SKEWED_TIME)]
this->get_role_attrs(role_t::VCR_SKEWED_TIME)
= this->to_attrs(lt, lt.lt_style_skewed_time, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_OFFSET_TIME)]
this->get_role_attrs(role_t::VCR_OFFSET_TIME)
= this->to_attrs(lt, lt.lt_style_offset_time, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_FILE_OFFSET)]
this->get_role_attrs(role_t::VCR_FILE_OFFSET)
= this->to_attrs(lt, lt.lt_style_file_offset, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_INVALID_MSG)]
this->get_role_attrs(role_t::VCR_INVALID_MSG)
= this->to_attrs(lt, lt.lt_style_invalid_msg, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_STATUS)]
this->get_role_attrs(role_t::VCR_STATUS)
= this->to_attrs(lt, lt.lt_style_status, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_WARN_STATUS)]
this->get_role_attrs(role_t::VCR_WARN_STATUS)
= this->to_attrs(lt, lt.lt_style_warn_status, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_ALERT_STATUS)]
this->get_role_attrs(role_t::VCR_ALERT_STATUS)
= this->to_attrs(lt, lt.lt_style_alert_status, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_ACTIVE_STATUS)]
this->get_role_attrs(role_t::VCR_ACTIVE_STATUS)
= this->to_attrs(lt, lt.lt_style_active_status, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_ACTIVE_STATUS2)]
= role_attrs{
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_ACTIVE_STATUS)]
.ra_normal,
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_ACTIVE_STATUS)]
.ra_reverse,
};
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_ACTIVE_STATUS2)]
.ra_normal.ta_attrs
this->get_role_attrs(role_t::VCR_ACTIVE_STATUS2) = role_attrs{
this->get_role_attrs(role_t::VCR_ACTIVE_STATUS).ra_normal,
this->get_role_attrs(role_t::VCR_ACTIVE_STATUS).ra_reverse,
};
this->get_role_attrs(role_t::VCR_ACTIVE_STATUS2).ra_normal.ta_attrs
|= A_BOLD;
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_ACTIVE_STATUS2)]
.ra_reverse.ta_attrs
this->get_role_attrs(role_t::VCR_ACTIVE_STATUS2).ra_reverse.ta_attrs
|= A_BOLD;
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_STATUS_TITLE)]
this->get_role_attrs(role_t::VCR_STATUS_TITLE)
= this->to_attrs(lt, lt.lt_style_status_title, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_STATUS_SUBTITLE)]
this->get_role_attrs(role_t::VCR_STATUS_SUBTITLE)
= this->to_attrs(lt, lt.lt_style_status_subtitle, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_STATUS_INFO)]
this->get_role_attrs(role_t::VCR_STATUS_INFO)
= this->to_attrs(lt, lt.lt_style_status_info, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_STATUS_HOTKEY)]
this->get_role_attrs(role_t::VCR_STATUS_HOTKEY)
= this->to_attrs(lt, lt.lt_style_status_hotkey, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_STATUS_TITLE_HOTKEY)]
this->get_role_attrs(role_t::VCR_STATUS_TITLE_HOTKEY)
= this->to_attrs(lt, lt.lt_style_status_title_hotkey, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_STATUS_DISABLED_TITLE)]
this->get_role_attrs(role_t::VCR_STATUS_DISABLED_TITLE)
= this->to_attrs(lt, lt.lt_style_status_disabled_title, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_H1)]
this->get_role_attrs(role_t::VCR_H1)
= this->to_attrs(lt, lt.lt_style_header[0], reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_H2)]
this->get_role_attrs(role_t::VCR_H2)
= this->to_attrs(lt, lt.lt_style_header[1], reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_H3)]
this->get_role_attrs(role_t::VCR_H3)
= this->to_attrs(lt, lt.lt_style_header[2], reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_H4)]
this->get_role_attrs(role_t::VCR_H4)
= this->to_attrs(lt, lt.lt_style_header[3], reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_H5)]
this->get_role_attrs(role_t::VCR_H5)
= this->to_attrs(lt, lt.lt_style_header[4], reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_H6)]
this->get_role_attrs(role_t::VCR_H6)
= this->to_attrs(lt, lt.lt_style_header[5], reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_HR)]
this->get_role_attrs(role_t::VCR_HR)
= this->to_attrs(lt, lt.lt_style_hr, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_HYPERLINK)]
this->get_role_attrs(role_t::VCR_HYPERLINK)
= this->to_attrs(lt, lt.lt_style_hyperlink, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_LIST_GLYPH)]
this->get_role_attrs(role_t::VCR_LIST_GLYPH)
= this->to_attrs(lt, lt.lt_style_list_glyph, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_BREADCRUMB)]
this->get_role_attrs(role_t::VCR_BREADCRUMB)
= this->to_attrs(lt, lt.lt_style_breadcrumb, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_TABLE_BORDER)]
this->get_role_attrs(role_t::VCR_TABLE_BORDER)
= this->to_attrs(lt, lt.lt_style_table_border, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_TABLE_HEADER)]
this->get_role_attrs(role_t::VCR_TABLE_HEADER)
= this->to_attrs(lt, lt.lt_style_table_header, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_QUOTE_BORDER)]
this->get_role_attrs(role_t::VCR_QUOTE_BORDER)
= this->to_attrs(lt, lt.lt_style_quote_border, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_QUOTED_TEXT)]
this->get_role_attrs(role_t::VCR_QUOTED_TEXT)
= this->to_attrs(lt, lt.lt_style_quoted_text, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_FOOTNOTE_BORDER)]
this->get_role_attrs(role_t::VCR_FOOTNOTE_BORDER)
= this->to_attrs(lt, lt.lt_style_footnote_border, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_FOOTNOTE_TEXT)]
this->get_role_attrs(role_t::VCR_FOOTNOTE_TEXT)
= this->to_attrs(lt, lt.lt_style_footnote_text, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_SNIPPET_BORDER)]
this->get_role_attrs(role_t::VCR_SNIPPET_BORDER)
= this->to_attrs(lt, lt.lt_style_snippet_border, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_INDENT_GUIDE)]
this->get_role_attrs(role_t::VCR_INDENT_GUIDE)
= this->to_attrs(lt, lt.lt_style_indent_guide, reporter);
{
@ -1033,8 +1031,7 @@ view_colors::init_roles(const lnav_theme& lt,
= lt.lt_style_status_subtitle.pp_value.sc_background_color;
stitch_sc.pp_value.sc_background_color
= lt.lt_style_status_title.pp_value.sc_background_color;
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_STATUS_STITCH_TITLE_TO_SUB)]
this->get_role_attrs(role_t::VCR_STATUS_STITCH_TITLE_TO_SUB)
= this->to_attrs(lt, stitch_sc, reporter);
}
{
@ -1044,8 +1041,7 @@ view_colors::init_roles(const lnav_theme& lt,
= lt.lt_style_status_title.pp_value.sc_background_color;
stitch_sc.pp_value.sc_background_color
= lt.lt_style_status_subtitle.pp_value.sc_background_color;
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_STATUS_STITCH_SUB_TO_TITLE)]
this->get_role_attrs(role_t::VCR_STATUS_STITCH_SUB_TO_TITLE)
= this->to_attrs(lt, stitch_sc, reporter);
}
@ -1056,8 +1052,7 @@ view_colors::init_roles(const lnav_theme& lt,
= lt.lt_style_status.pp_value.sc_background_color;
stitch_sc.pp_value.sc_background_color
= lt.lt_style_status_subtitle.pp_value.sc_background_color;
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_STATUS_STITCH_SUB_TO_NORMAL)]
this->get_role_attrs(role_t::VCR_STATUS_STITCH_SUB_TO_NORMAL)
= this->to_attrs(lt, stitch_sc, reporter);
}
{
@ -1067,8 +1062,7 @@ view_colors::init_roles(const lnav_theme& lt,
= lt.lt_style_status_subtitle.pp_value.sc_background_color;
stitch_sc.pp_value.sc_background_color
= lt.lt_style_status.pp_value.sc_background_color;
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_STATUS_STITCH_NORMAL_TO_SUB)]
this->get_role_attrs(role_t::VCR_STATUS_STITCH_NORMAL_TO_SUB)
= this->to_attrs(lt, stitch_sc, reporter);
}
@ -1079,8 +1073,7 @@ view_colors::init_roles(const lnav_theme& lt,
= lt.lt_style_status.pp_value.sc_background_color;
stitch_sc.pp_value.sc_background_color
= lt.lt_style_status_title.pp_value.sc_background_color;
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_STATUS_STITCH_TITLE_TO_NORMAL)]
this->get_role_attrs(role_t::VCR_STATUS_STITCH_TITLE_TO_NORMAL)
= this->to_attrs(lt, stitch_sc, reporter);
}
{
@ -1090,25 +1083,22 @@ view_colors::init_roles(const lnav_theme& lt,
= lt.lt_style_status_title.pp_value.sc_background_color;
stitch_sc.pp_value.sc_background_color
= lt.lt_style_status.pp_value.sc_background_color;
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_STATUS_STITCH_NORMAL_TO_TITLE)]
this->get_role_attrs(role_t::VCR_STATUS_STITCH_NORMAL_TO_TITLE)
= this->to_attrs(lt, stitch_sc, reporter);
}
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_INACTIVE_STATUS)]
this->get_role_attrs(role_t::VCR_INACTIVE_STATUS)
= this->to_attrs(lt, lt.lt_style_inactive_status, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_INACTIVE_ALERT_STATUS)]
this->get_role_attrs(role_t::VCR_INACTIVE_ALERT_STATUS)
= this->to_attrs(lt, lt.lt_style_inactive_alert_status, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_POPUP)]
this->get_role_attrs(role_t::VCR_POPUP)
= this->to_attrs(lt, lt.lt_style_popup, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_FOCUSED)]
this->get_role_attrs(role_t::VCR_FOCUSED)
= this->to_attrs(lt, lt.lt_style_focused, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_DISABLED_FOCUSED)]
this->get_role_attrs(role_t::VCR_DISABLED_FOCUSED)
= this->to_attrs(lt, lt.lt_style_disabled_focused, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_SCROLLBAR)]
this->get_role_attrs(role_t::VCR_SCROLLBAR)
= this->to_attrs(lt, lt.lt_style_scrollbar, reporter);
{
positioned_property<style_config> bar_sc;
@ -1116,8 +1106,7 @@ view_colors::init_roles(const lnav_theme& lt,
bar_sc.pp_value.sc_color = lt.lt_style_error.pp_value.sc_color;
bar_sc.pp_value.sc_background_color
= lt.lt_style_scrollbar.pp_value.sc_background_color;
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_SCROLLBAR_ERROR)]
this->get_role_attrs(role_t::VCR_SCROLLBAR_ERROR)
= this->to_attrs(lt, bar_sc, reporter);
}
{
@ -1126,67 +1115,70 @@ view_colors::init_roles(const lnav_theme& lt,
bar_sc.pp_value.sc_color = lt.lt_style_warning.pp_value.sc_color;
bar_sc.pp_value.sc_background_color
= lt.lt_style_scrollbar.pp_value.sc_background_color;
this->vc_role_attrs[lnav::enums::to_underlying(
role_t::VCR_SCROLLBAR_WARNING)]
this->get_role_attrs(role_t::VCR_SCROLLBAR_WARNING)
= this->to_attrs(lt, bar_sc, reporter);
}
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_INLINE_CODE)]
this->get_role_attrs(role_t::VCR_INLINE_CODE)
= this->to_attrs(lt, lt.lt_style_inline_code, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_QUOTED_CODE)]
this->get_role_attrs(role_t::VCR_QUOTED_CODE)
= this->to_attrs(lt, lt.lt_style_quoted_code, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_CODE_BORDER)]
this->get_role_attrs(role_t::VCR_CODE_BORDER)
= this->to_attrs(lt, lt.lt_style_code_border, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_KEYWORD)]
this->get_role_attrs(role_t::VCR_KEYWORD)
= this->to_attrs(lt, lt.lt_style_keyword, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_STRING)]
this->get_role_attrs(role_t::VCR_STRING)
= this->to_attrs(lt, lt.lt_style_string, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_COMMENT)]
this->get_role_attrs(role_t::VCR_COMMENT)
= this->to_attrs(lt, lt.lt_style_comment, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_DOC_DIRECTIVE)]
this->get_role_attrs(role_t::VCR_DOC_DIRECTIVE)
= this->to_attrs(lt, lt.lt_style_doc_directive, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_VARIABLE)]
this->get_role_attrs(role_t::VCR_VARIABLE)
= this->to_attrs(lt, lt.lt_style_variable, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_SYMBOL)]
this->get_role_attrs(role_t::VCR_SYMBOL)
= this->to_attrs(lt, lt.lt_style_symbol, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_NULL)]
this->get_role_attrs(role_t::VCR_NULL)
= this->to_attrs(lt, lt.lt_style_null, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_ASCII_CTRL)]
this->get_role_attrs(role_t::VCR_ASCII_CTRL)
= this->to_attrs(lt, lt.lt_style_ascii_ctrl, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_NON_ASCII)]
this->get_role_attrs(role_t::VCR_NON_ASCII)
= this->to_attrs(lt, lt.lt_style_non_ascii, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_NUMBER)]
this->get_role_attrs(role_t::VCR_NUMBER)
= this->to_attrs(lt, lt.lt_style_number, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_FUNCTION)]
this->get_role_attrs(role_t::VCR_FUNCTION)
= this->to_attrs(lt, lt.lt_style_function, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_TYPE)]
this->get_role_attrs(role_t::VCR_TYPE)
= this->to_attrs(lt, lt.lt_style_type, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_SEP_REF_ACC)]
this->get_role_attrs(role_t::VCR_SEP_REF_ACC)
= this->to_attrs(lt, lt.lt_style_sep_ref_acc, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_SUGGESTION)]
this->get_role_attrs(role_t::VCR_SUGGESTION)
= this->to_attrs(lt, lt.lt_style_suggestion, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_SELECTED_TEXT)]
this->get_role_attrs(role_t::VCR_SELECTED_TEXT)
= this->to_attrs(lt, lt.lt_style_selected_text, reporter);
if (this->get_role_attrs(role_t::VCR_SELECTED_TEXT).ra_normal.empty()) {
this->get_role_attrs(role_t::VCR_SELECTED_TEXT) = this->to_attrs(
default_theme, default_theme.lt_style_selected_text, reporter);
}
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_RE_SPECIAL)]
this->get_role_attrs(role_t::VCR_RE_SPECIAL)
= this->to_attrs(lt, lt.lt_style_re_special, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_RE_REPEAT)]
this->get_role_attrs(role_t::VCR_RE_REPEAT)
= this->to_attrs(lt, lt.lt_style_re_repeat, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_FILE)]
this->get_role_attrs(role_t::VCR_FILE)
= this->to_attrs(lt, lt.lt_style_file, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_DIFF_DELETE)]
this->get_role_attrs(role_t::VCR_DIFF_DELETE)
= this->to_attrs(lt, lt.lt_style_diff_delete, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_DIFF_ADD)]
this->get_role_attrs(role_t::VCR_DIFF_ADD)
= this->to_attrs(lt, lt.lt_style_diff_add, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_DIFF_SECTION)]
this->get_role_attrs(role_t::VCR_DIFF_SECTION)
= this->to_attrs(lt, lt.lt_style_diff_section, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_LOW_THRESHOLD)]
this->get_role_attrs(role_t::VCR_LOW_THRESHOLD)
= this->to_attrs(lt, lt.lt_style_low_threshold, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_MED_THRESHOLD)]
this->get_role_attrs(role_t::VCR_MED_THRESHOLD)
= this->to_attrs(lt, lt.lt_style_med_threshold, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_HIGH_THRESHOLD)]
this->get_role_attrs(role_t::VCR_HIGH_THRESHOLD)
= this->to_attrs(lt, lt.lt_style_high_threshold, reporter);
for (auto level = static_cast<log_level_t>(LEVEL_UNKNOWN + 1);

@ -292,6 +292,11 @@ private:
const positioned_property<style_config>& sc,
lnav_config_listener::error_reporter& reporter);
role_attrs& get_role_attrs(const role_t role)
{
return this->vc_role_attrs[lnav::enums::to_underlying(role)];
}
role_attrs vc_level_attrs[LEVEL__MAX];
/** Map of role IDs to attribute values. */

@ -426,7 +426,7 @@ can always use  q  to pop the top view off of the stack.
CTRL+], ESCAPE Abort command-line entry started with  / ,  : ,
 ; , or  | .
Note: The regular expression format used by lnav is ]8;;http://perldoc.perl.org/perlre.html\PCRE]8;;\[1]
Note: The regular expression format used by lnav is ]8;;http://perldoc.perl.org/perlre.html\PCRE]8;;\¹
▌(Perl-Compatible Regular Expressions).
▌[1] - http://perldoc.perl.org/perlre.html
@ -577,7 +577,7 @@ example of a top ten query into the "/tmp/topten.db" file, you can do:
PRQL Support
The Pipelined Relational Query Language ]8;;https://prql-lang.org\(PRQL)]8;;\[1] is an alternative
The Pipelined Relational Query Language ]8;;https://prql-lang.org\(PRQL)]8;;\¹ is an alternative
database query language that compiles to SQL. The main advantage of
PRQL, in the context of lnav, is that it is easier to work with
interactively compared to SQL. For example, lnav can provide previews
@ -589,8 +589,8 @@ tab-completions for the columns in the result set.
You can execute a PRQL query in the SQL prompt. A PRQL query starts
with the  from  keyword that specifies the table to use as a data
source. The next stage of a pipeline is started by entering a pipe
symbol ( | ) followed by a ]8;;https://prql-lang.org/book/reference/stdlib/transforms/index.html\PRQL transform]8;;\[1]. As you build the query
in the prompt, lnav will display any relevant help and preview for the
symbol ( | ) followed by a ]8;;https://prql-lang.org/book/reference/stdlib/transforms/index.html\PRQL transform]8;;\¹. As you build the query in
the prompt, lnav will display any relevant help and preview for the
current and previous stages of the pipeline.
▌[1] - https://prql-lang.org/book/reference/stdlib/transforms/index.html

@ -11,7 +11,7 @@ Run  ./autogen.sh  if compiling from a cloned repository.
See Also
]8;;https://github.com/rcoh/angle-grinder\Angle-grinder]8;;\[1] is a tool to slice and dice log files on the
]8;;https://github.com/rcoh/angle-grinder\Angle-grinder]8;;\¹ is a tool to slice and dice log files on the
command-line. If you're familiar with the SumoLogic query language,
you might find this tool more comfortable to work with.

@ -1,4 +1,4 @@
]8;;https://github.com/tstack/lnav/actions?query=workflow%3Aci-build\🖼 Build[1]]8;;\[2] ]8;;https://docs.lnav.org\🖼 Docs[3]]8;;\[4] ]8;;https://coveralls.io/github/tstack/lnav?branch=master\🖼 Coverage Status[5]]8;;\[6] ]8;;https://snapcraft.io/lnav\🖼 lnav[7]]8;;\[8]
]8;;https://github.com/tstack/lnav/actions?query=workflow%3Aci-build\🖼 Build]8;;\]8;;https://github.com/tstack/lnav/actions?query=workflow%3Aci-build\¹]8;;\˒² ]8;;https://docs.lnav.org\🖼 Docs]8;;\]8;;https://docs.lnav.org\³]8;;\˒⁴ ]8;;https://coveralls.io/github/tstack/lnav?branch=master\🖼 Coverage Status]8;;\]8;;https://coveralls.io/github/tstack/lnav?branch=master\⁵]8;;\˒⁶ ]8;;https://snapcraft.io/lnav\🖼 lnav]8;;\]8;;https://snapcraft.io/lnav\⁷]8;;\˒⁸
▌[1] - https://github.com/tstack/lnav/workflows/ci-build/badge.svg
▌[2] - https://github.com/tstack/lnav/actions?query=workflow%3Aci-build
@ -9,13 +9,13 @@
▌[7] - https://snapcraft.io/lnav/badge.svg
▌[8] - https://snapcraft.io/lnav
]8;;https://discord.gg/erBPnKwz7R\🖼 ]8;;\]8;;https://discord.gg/erBPnKwz7R\Discord Logo]8;;\]8;;https://discord.gg/erBPnKwz7R\[1]]8;;\[2]
]8;;https://discord.gg/erBPnKwz7R\🖼 ]8;;\]8;;https://discord.gg/erBPnKwz7R\Discord Logo]8;;\]8;;https://discord.gg/erBPnKwz7R\¹]8;;
▌[1] - https://assets-global.website-files.com/6257adef93867e50d84d30e2/62594fddd654fc29fcc07359_cb48d2a8d4991281d7a6a95d2f58195e.svg
▌[2] - https://discord.gg/erBPnKwz7R
This is the source repository for lnav, visit ]8;;https://lnav.org\https://lnav.org]8;;\[1] for
a high level overview.
This is the source repository for lnav, visit ]8;;https://lnav.org\https://lnav.org]8;;\¹ for a
high level overview.
▌[1] - https://lnav.org
@ -30,21 +30,21 @@ set of files/directories, lnav will:
• tail the files, follow renames, find new files in
directories;
• build an index of errors and warnings;
• ]8;;https://docs.lnav.org/en/latest/formats.html#json-lines\pretty-print JSON-lines]8;;\[1].
• ]8;;https://docs.lnav.org/en/latest/formats.html#json-lines\pretty-print JSON-lines]8;;\¹.
▌[1] - https://docs.lnav.org/en/latest/formats.html#json-lines
Then, in the lnav TUI, you can:
• jump quickly to the previous/next error (]8;;https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation\press ]8;;\]8;;https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation\ e ]8;;\]8;;https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation\/]8;;\]8;;https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation\ E ]8;;\[1]);
• search using regular expressions (]8;;https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation\press ]8;;\]8;;https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation\ / ]8;;\[2]);
• highlight text with a regular expression (]8;;https://docs.lnav.org/en/latest/commands.html#highlight-pattern\ :highlight ]8;;\[3]
• jump quickly to the previous/next error (]8;;https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation\press ]8;;\]8;;https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation\ e ]8;;\]8;;https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation\/]8;;\]8;;https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation\ E ]8;;\¹);
• search using regular expressions (]8;;https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation\press ]8;;\]8;;https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation\ / ]8;;\²);
• highlight text with a regular expression (]8;;https://docs.lnav.org/en/latest/commands.html#highlight-pattern\ :highlight ]8;;\³
command);
• filter messages using ]8;;https://docs.lnav.org/en/latest/usage.html#regular-expression-match\regular expressions]8;;\[4] or ]8;;https://docs.lnav.org/en/latest/usage.html#sqlite-expression\SQLite]8;;\
]8;;https://docs.lnav.org/en/latest/usage.html#sqlite-expression\expressions]8;;\[5];
• pretty-print structured text (]8;;https://docs.lnav.org/en/latest/ui.html#pretty\press ]8;;\]8;;https://docs.lnav.org/en/latest/ui.html#pretty\ P ]8;;\[6]);
• view a histogram of messages over time (]8;;https://docs.lnav.org/en/latest/ui.html#hist\press ]8;;\]8;;https://docs.lnav.org/en/latest/ui.html#hist\ i ]8;;\[7]);
• query messages using SQLite (]8;;https://docs.lnav.org/en/latest/sqlext.html\press ]8;;\]8;;https://docs.lnav.org/en/latest/sqlext.html\ ; ]8;;\[8])
• filter messages using ]8;;https://docs.lnav.org/en/latest/usage.html#regular-expression-match\regular expressions]8;;\ or ]8;;https://docs.lnav.org/en/latest/usage.html#sqlite-expression\SQLite]8;;\
]8;;https://docs.lnav.org/en/latest/usage.html#sqlite-expression\expressions]8;;\;
• pretty-print structured text (]8;;https://docs.lnav.org/en/latest/ui.html#pretty\press ]8;;\]8;;https://docs.lnav.org/en/latest/ui.html#pretty\ P ]8;;\);
• view a histogram of messages over time (]8;;https://docs.lnav.org/en/latest/ui.html#hist\press ]8;;\]8;;https://docs.lnav.org/en/latest/ui.html#hist\ i ]8;;\);
• query messages using SQLite (]8;;https://docs.lnav.org/en/latest/sqlext.html\press ]8;;\]8;;https://docs.lnav.org/en/latest/sqlext.html\ ; ]8;;\)
▌[1] - https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation
▌[2] - https://docs.lnav.org/en/latest/hotkeys.html#spatial-navigation
@ -61,7 +61,7 @@ The following screenshot shows a mix of syslog and web access log
files. Failed requests are shown in red. Identifiers, like IP
address and PIDs are semantically highlighted.
]8;;docs/assets/images/lnav-front-page.png\🖼 Screenshot[1]]8;;\[2]
]8;;docs/assets/images/lnav-front-page.png\🖼 Screenshot]8;;\]8;;docs/assets/images/lnav-front-page.png\¹]8;;\˒²
▌[1] - file://{top_srcdir}/docs/assets/images/lnav-front-page.png
▌[2] - file://{top_srcdir}/docs/assets/images/lnav-front-page.png
@ -83,21 +83,21 @@ You can SSH into a demo node to play with lnav before installing.
The "playground" account starts lnav with a couple of log files as an
example:
]8;;ssh://playground@demo.lnav.org\ $ ssh playground@demo.lnav.org ]8;;\[1]
]8;;ssh://playground@demo.lnav.org\ $ ssh playground@demo.lnav.org ]8;;\¹
▌[1] - ssh://playground@demo.lnav.org
The "tutorial 1" account is an interactive tutorial that can teach you
the basics of operation:
]8;;ssh://tutorial1@demo.lnav.org\ $ ssh tutorial1@demo.lnav.org ]8;;\[1]
]8;;ssh://tutorial1@demo.lnav.org\ $ ssh tutorial1@demo.lnav.org ]8;;\¹
▌[1] - ssh://tutorial1@demo.lnav.org
Installation
]8;;https://github.com/tstack/lnav/releases/latest#release-artifacts\Download a statically-linked binary for Linux/MacOS from the release]8;;\
]8;;https://github.com/tstack/lnav/releases/latest#release-artifacts\page]8;;\[1]
]8;;https://github.com/tstack/lnav/releases/latest#release-artifacts\page]8;;\¹
▌[1] - https://github.com/tstack/lnav/releases/latest#release-artifacts
@ -118,7 +118,7 @@ indexing has finished, the LOG view will display the log messages that
were recognized[^1]. You can then use the usual hotkeys to move around
the view (arrow keys or  j / k / h / l  to move down/up/left/right).
See the ]8;;https://docs.lnav.org/en/latest/usage.html\Usage section]8;;\[1] of the online documentation for more
See the ]8;;https://docs.lnav.org/en/latest/usage.html\Usage section]8;;\¹ of the online documentation for more
information.
▌[1] - https://docs.lnav.org/en/latest/usage.html
@ -173,9 +173,9 @@ log lines fed into  lnav  via  journalctl 's [
Please file issues on this repository or use the discussions section.
The following alternatives are also available:
• ]8;;mailto:support@lnav.org\support@lnav.org]8;;\[1]
• ]8;;https://discord.gg/erBPnKwz7R\Discord]8;;\[2]
• ]8;;https://groups.google.com/g/lnav\Google Groups]8;;\[3]
• ]8;;mailto:support@lnav.org\support@lnav.org]8;;\¹
• ]8;;https://discord.gg/erBPnKwz7R\Discord]8;;\²
• ]8;;https://groups.google.com/g/lnav\Google Groups]8;;\³
▌[1] - mailto:support@lnav.org
▌[2] - https://discord.gg/erBPnKwz7R
@ -183,9 +183,9 @@ The following alternatives are also available:
Links
• ]8;;https://lnav.org\Main Site]8;;\[1]
• ]8;;https://docs.lnav.org\Documentation]8;;\[2] on Read the Docs
• ]8;;ARCHITECTURE.md\Internal Architecture]8;;\[3]
• ]8;;https://lnav.org\Main Site]8;;\¹
• ]8;;https://docs.lnav.org\Documentation]8;;\² on Read the Docs
• ]8;;ARCHITECTURE.md\Internal Architecture]8;;\³
▌[1] - https://lnav.org
▌[2] - https://docs.lnav.org
@ -193,7 +193,7 @@ The following alternatives are also available:
Contributing
• ]8;;https://github.com/sponsors/tstack\Become a Sponsor on GitHub]8;;\[1]
• ]8;;https://github.com/sponsors/tstack\Become a Sponsor on GitHub]8;;\¹
▌[1] - https://github.com/sponsors/tstack
@ -234,7 +234,7 @@ Run  ./autogen.sh  if compiling from a cloned repository.
See Also
]8;;https://github.com/rcoh/angle-grinder\Angle-grinder]8;;\[1] is a tool to slice and dice log files on the
]8;;https://github.com/rcoh/angle-grinder\Angle-grinder]8;;\¹ is a tool to slice and dice log files on the
command-line. If you're familiar with the SumoLogic query language,
you might find this tool more comfortable to work with.

@ -4,7 +4,7 @@ The following screenshot shows a mix of syslog and web access log
files. Failed requests are shown in red. Identifiers, like IP
address and PIDs are semantically highlighted.
]8;;docs/assets/images/lnav-front-page.png\🖼 Screenshot[1]]8;;\[2]
]8;;docs/assets/images/lnav-front-page.png\🖼 Screenshot]8;;\]8;;docs/assets/images/lnav-front-page.png\¹]8;;\˒²
▌[1] - file://{top_srcdir}/docs/assets/images/lnav-front-page.png
▌[2] - file://{top_srcdir}/docs/assets/images/lnav-front-page.png
@ -26,21 +26,21 @@ You can SSH into a demo node to play with lnav before installing.
The "playground" account starts lnav with a couple of log files as an
example:
]8;;ssh://playground@demo.lnav.org\ $ ssh playground@demo.lnav.org ]8;;\[1]
]8;;ssh://playground@demo.lnav.org\ $ ssh playground@demo.lnav.org ]8;;\¹
▌[1] - ssh://playground@demo.lnav.org
The "tutorial 1" account is an interactive tutorial that can teach you
the basics of operation:
]8;;ssh://tutorial1@demo.lnav.org\ $ ssh tutorial1@demo.lnav.org ]8;;\[1]
]8;;ssh://tutorial1@demo.lnav.org\ $ ssh tutorial1@demo.lnav.org ]8;;\¹
▌[1] - ssh://tutorial1@demo.lnav.org
Installation
]8;;https://github.com/tstack/lnav/releases/latest#release-artifacts\Download a statically-linked binary for Linux/MacOS from the release]8;;\
]8;;https://github.com/tstack/lnav/releases/latest#release-artifacts\page]8;;\[1]
]8;;https://github.com/tstack/lnav/releases/latest#release-artifacts\page]8;;\¹
▌[1] - https://github.com/tstack/lnav/releases/latest#release-artifacts
@ -61,7 +61,7 @@ indexing has finished, the LOG view will display the log messages that
were recognized[^1]. You can then use the usual hotkeys to move around
the view (arrow keys or  j / k / h / l  to move down/up/left/right).
See the ]8;;https://docs.lnav.org/en/latest/usage.html\Usage section]8;;\[1] of the online documentation for more
See the ]8;;https://docs.lnav.org/en/latest/usage.html\Usage section]8;;\¹ of the online documentation for more
information.
▌[1] - https://docs.lnav.org/en/latest/usage.html
@ -116,9 +116,9 @@ log lines fed into  lnav  via  journalctl 's [
Please file issues on this repository or use the discussions section.
The following alternatives are also available:
• ]8;;mailto:support@lnav.org\support@lnav.org]8;;\[1]
• ]8;;https://discord.gg/erBPnKwz7R\Discord]8;;\[2]
• ]8;;https://groups.google.com/g/lnav\Google Groups]8;;\[3]
• ]8;;mailto:support@lnav.org\support@lnav.org]8;;\¹
• ]8;;https://discord.gg/erBPnKwz7R\Discord]8;;\²
• ]8;;https://groups.google.com/g/lnav\Google Groups]8;;\³
▌[1] - mailto:support@lnav.org
▌[2] - https://discord.gg/erBPnKwz7R
@ -126,9 +126,9 @@ The following alternatives are also available:
Links
• ]8;;https://lnav.org\Main Site]8;;\[1]
• ]8;;https://docs.lnav.org\Documentation]8;;\[2] on Read the Docs
• ]8;;ARCHITECTURE.md\Internal Architecture]8;;\[3]
• ]8;;https://lnav.org\Main Site]8;;\¹
• ]8;;https://docs.lnav.org\Documentation]8;;\² on Read the Docs
• ]8;;ARCHITECTURE.md\Internal Architecture]8;;\³
▌[1] - https://lnav.org
▌[2] - https://docs.lnav.org
@ -136,7 +136,7 @@ The following alternatives are also available:
Contributing
• ]8;;https://github.com/sponsors/tstack\Become a Sponsor on GitHub]8;;\[1]
• ]8;;https://github.com/sponsors/tstack\Become a Sponsor on GitHub]8;;\¹
▌[1] - https://github.com/sponsors/tstack
@ -177,7 +177,7 @@ Run  ./autogen.sh  if compiling from a cloned repository.
See Also
]8;;https://github.com/rcoh/angle-grinder\Angle-grinder]8;;\[1] is a tool to slice and dice log files on the
]8;;https://github.com/rcoh/angle-grinder\Angle-grinder]8;;\¹ is a tool to slice and dice log files on the
command-line. If you're familiar with the SumoLogic query language,
you might find this tool more comfortable to work with.

@ -1,13 +1,18 @@
Table of Contents
• ]8;;#test\Test]8;;\
• ]8;;#github-alerts\Github Alerts]8;;\
Test
• One
• Two
• Three
🖼 ]8;;file://{top_srcdir}/docs/lnav-tui.png\lnav-tui.png]8;;\[1]
🖼 ]8;;file://{top_srcdir}/docs/lnav-tui.png\lnav-tui.png]8;;\¹
🖼 ]8;;file://{top_srcdir}/docs/lnav-architecture.png\The internal architecture of lnav]8;;\[2]
🖼 ]8;;file://{top_srcdir}/docs/lnav-architecture.png\The internal architecture of lnav]8;;\²
▌[1] - file://{top_srcdir}/docs/lnav-tui.png
▌[2] - file://{top_srcdir}/docs/lnav-architecture.png
@ -50,7 +55,9 @@ Goodbye, ▌World╏!
 </book> 
</books> 
▌ⓘ Note
Github Alerts
▌ⓘ Note
▌Useful information that users should know, even when
▌skimming content.
@ -60,7 +67,7 @@ Goodbye, ▌World╏!
▌🌟 Important
▌Key information users need to know to achieve their goal.
▌⚠ Warning
▌⚠ Warning
▌Urgent info that needs immediate user attention to avoid
▌problems.

@ -4,7 +4,7 @@ The following screenshot shows a mix of syslog and web access log
files. Failed requests are shown in red. Identifiers, like IP
address and PIDs are semantically highlighted.
]8;;docs/assets/images/lnav-front-page.png\🖼 Screenshot[1]]8;;\[2]
]8;;docs/assets/images/lnav-front-page.png\🖼 Screenshot]8;;\]8;;docs/assets/images/lnav-front-page.png\¹]8;;\˒²
▌[1] - file://{top_srcdir}/docs/assets/images/lnav-front-page.png
▌[2] - file://{top_srcdir}/docs/assets/images/lnav-front-page.png
@ -26,21 +26,21 @@ You can SSH into a demo node to play with lnav before installing.
The "playground" account starts lnav with a couple of log files as an
example:
]8;;ssh://playground@demo.lnav.org\ $ ssh playground@demo.lnav.org ]8;;\[1]
]8;;ssh://playground@demo.lnav.org\ $ ssh playground@demo.lnav.org ]8;;\¹
▌[1] - ssh://playground@demo.lnav.org
The "tutorial 1" account is an interactive tutorial that can teach you
the basics of operation:
]8;;ssh://tutorial1@demo.lnav.org\ $ ssh tutorial1@demo.lnav.org ]8;;\[1]
]8;;ssh://tutorial1@demo.lnav.org\ $ ssh tutorial1@demo.lnav.org ]8;;\¹
▌[1] - ssh://tutorial1@demo.lnav.org
Installation
]8;;https://github.com/tstack/lnav/releases/latest#release-artifacts\Download a statically-linked binary for Linux/MacOS from the release]8;;\
]8;;https://github.com/tstack/lnav/releases/latest#release-artifacts\page]8;;\[1]
]8;;https://github.com/tstack/lnav/releases/latest#release-artifacts\page]8;;\¹
▌[1] - https://github.com/tstack/lnav/releases/latest#release-artifacts
@ -61,7 +61,7 @@ indexing has finished, the LOG view will display the log messages that
were recognized[^1]. You can then use the usual hotkeys to move around
the view (arrow keys or  j / k / h / l  to move down/up/left/right).
See the ]8;;https://docs.lnav.org/en/latest/usage.html\Usage section]8;;\[1] of the online documentation for more
See the ]8;;https://docs.lnav.org/en/latest/usage.html\Usage section]8;;\¹ of the online documentation for more
information.
▌[1] - https://docs.lnav.org/en/latest/usage.html
@ -116,9 +116,9 @@ log lines fed into  lnav  via  journalctl 's [
Please file issues on this repository or use the discussions section.
The following alternatives are also available:
• ]8;;mailto:support@lnav.org\support@lnav.org]8;;\[1]
• ]8;;https://discord.gg/erBPnKwz7R\Discord]8;;\[2]
• ]8;;https://groups.google.com/g/lnav\Google Groups]8;;\[3]
• ]8;;mailto:support@lnav.org\support@lnav.org]8;;\¹
• ]8;;https://discord.gg/erBPnKwz7R\Discord]8;;\²
• ]8;;https://groups.google.com/g/lnav\Google Groups]8;;\³
▌[1] - mailto:support@lnav.org
▌[2] - https://discord.gg/erBPnKwz7R
@ -126,9 +126,9 @@ The following alternatives are also available:
Links
• ]8;;https://lnav.org\Main Site]8;;\[1]
• ]8;;https://docs.lnav.org\Documentation]8;;\[2] on Read the Docs
• ]8;;ARCHITECTURE.md\Internal Architecture]8;;\[3]
• ]8;;https://lnav.org\Main Site]8;;\¹
• ]8;;https://docs.lnav.org\Documentation]8;;\² on Read the Docs
• ]8;;ARCHITECTURE.md\Internal Architecture]8;;\³
▌[1] - https://lnav.org
▌[2] - https://docs.lnav.org
@ -136,7 +136,7 @@ The following alternatives are also available:
Contributing
• ]8;;https://github.com/sponsors/tstack\Become a Sponsor on GitHub]8;;\[1]
• ]8;;https://github.com/sponsors/tstack\Become a Sponsor on GitHub]8;;\¹
▌[1] - https://github.com/sponsors/tstack
@ -177,7 +177,7 @@ Run  ./autogen.sh  if compiling from a cloned repository.
See Also
]8;;https://github.com/rcoh/angle-grinder\Angle-grinder]8;;\[1] is a tool to slice and dice log files on the
]8;;https://github.com/rcoh/angle-grinder\Angle-grinder]8;;\¹ is a tool to slice and dice log files on the
command-line. If you're familiar with the SumoLogic query language,
you might find this tool more comfortable to work with.

@ -2,6 +2,11 @@
"comment": "This is JSON front-matter"
}
# Table of Contents
- [Test](#test)
- [Github Alerts](#github-alerts)
## Test
* One
@ -59,6 +64,8 @@ def hw(name):
</books>
```
## Github Alerts
> [!NOTE]
> Useful information that users should know, even when skimming content.

Loading…
Cancel
Save