[line_buffer] add some performance counters for tracking SQL perf

Also, check for keyboard input during SQL execution
so we can cancel.

Fixes #894
pull/824/merge
Timothy Stack 2 years ago
parent 0f2d38df50
commit 8ef581177c

@ -30,6 +30,8 @@ lnav v0.11.0:
that range. You can then press TAB to focus on the detail view
and scroll around.
* Add initial support for pcap(3) files using tshark(1).
* SQL statement execution can now be canceled by pressing CTRL+]
(same as canceling out of a prompt).
* To make it possible to automate some operations, there is now an
"lnav_events" table that is updated when internal events occur
within lnav (e.g. opening a file, format is detected). You
@ -105,6 +107,8 @@ lnav v0.11.0:
* Fix a crash related to long lines that are word wrapped.
* Multiple SQL statements in a SQL block of a script are now
executed instead of just the first one.
* In cases where there were many different colors on screen, some
text would be colored incorrectly.
lnav v0.10.1:
Features:

@ -269,6 +269,11 @@
"title": "/ui/theme-defs/<theme_name>/styles/ok",
"$ref": "#/definitions/style"
},
"info": {
"description": "Styling for informational messages",
"title": "/ui/theme-defs/<theme_name>/styles/info",
"$ref": "#/definitions/style"
},
"warning": {
"description": "Styling for warning messages",
"title": "/ui/theme-defs/<theme_name>/styles/warning",

@ -50,7 +50,7 @@ void
scrub_ansi_string(std::string& str, string_attrs_t& sa)
{
pcre_context_static<60> context;
pcrepp& regex = ansi_regex();
auto& regex = ansi_regex();
pcre_input pi(str);
replace(str.begin(), str.end(), '\0', ' ');
@ -58,9 +58,7 @@ scrub_ansi_string(std::string& str, string_attrs_t& sa)
pcre_context::capture_t* caps = context.all();
struct line_range lr;
bool has_attrs = false;
attr_t attrs = 0;
auto bg = nonstd::optional<int>();
auto fg = nonstd::optional<int>();
text_attrs attrs;
auto role = nonstd::optional<role_t>();
size_t lpc;
@ -74,29 +72,29 @@ scrub_ansi_string(std::string& str, string_attrs_t& sa)
if (sscanf(&(str[lpc]), "%d", &ansi_code) == 1) {
if (90 <= ansi_code && ansi_code <= 97) {
ansi_code -= 60;
attrs |= A_STANDOUT;
attrs.ta_attrs |= A_STANDOUT;
}
if (30 <= ansi_code && ansi_code <= 37) {
fg = ansi_code - 30;
attrs.ta_fg_color = ansi_code - 30;
}
if (40 <= ansi_code && ansi_code <= 47) {
bg = ansi_code - 40;
attrs.ta_bg_color = ansi_code - 40;
}
switch (ansi_code) {
case 1:
attrs |= A_BOLD;
attrs.ta_attrs |= A_BOLD;
break;
case 2:
attrs |= A_DIM;
attrs.ta_attrs |= A_DIM;
break;
case 4:
attrs |= A_UNDERLINE;
attrs.ta_attrs |= A_UNDERLINE;
break;
case 7:
attrs |= A_REVERSE;
attrs.ta_attrs |= A_REVERSE;
break;
}
}
@ -160,17 +158,11 @@ scrub_ansi_string(std::string& str, string_attrs_t& sa)
}
lr.lr_start = caps[0].c_begin;
lr.lr_end = -1;
if (attrs) {
if (attrs.ta_attrs || attrs.ta_fg_color || attrs.ta_bg_color) {
sa.emplace_back(lr, VC_STYLE.value(attrs));
}
role |
[&lr, &sa](role_t r) { sa.emplace_back(lr, VC_ROLE.value(r)); };
fg | [&lr, &sa](int color) {
sa.emplace_back(lr, VC_FOREGROUND.value(color));
};
bg | [&lr, &sa](int color) {
sa.emplace_back(lr, VC_BACKGROUND.value(color));
};
}
pi.reset(str);

@ -101,7 +101,7 @@ consume(const string_fragment text)
pcre_input pi(text);
pcre_context_static<30> pc;
if (WORD_RE.match(pc, pi)) {
if (WORD_RE.match(pc, pi, PCRE_NO_UTF8_CHECK)) {
auto split_res = text.split_n(pc.all()->length()).value();
return word{split_res.first, split_res.second};
@ -113,7 +113,7 @@ consume(const string_fragment text)
return space{split_res.first, split_res.second};
}
if (SPACE_RE.match(pc, pi)) {
if (SPACE_RE.match(pc, pi, PCRE_NO_UTF8_CHECK)) {
auto split_res = text.split_n(pc.all()->length()).value();
return space{split_res.first, split_res.second};
@ -195,8 +195,8 @@ attr_line_t::insert(size_t index,
const ssize_t usable_width = tws->tws_width - tws->tws_indent;
auto text_to_wrap
= string_fragment{this->al_string.data(), (int) starting_line_index};
auto text_to_wrap = string_fragment::from_str_range(
this->al_string, starting_line_index, this->al_string.length());
string_fragment last_word;
ssize_t line_ch_count = 0;
auto needs_indent = false;
@ -225,7 +225,8 @@ attr_line_t::insert(size_t index,
text_to_wrap = chunk.match(
[&](text_stream::word word) {
auto ch_count = word.w_word.utf8_length().unwrap();
auto ch_count
= word.w_word.utf8_length().unwrapOr(word.w_word.length());
if ((line_ch_count + ch_count) > usable_width
&& find_string_attr_containing(this->al_attrs,
@ -272,7 +273,8 @@ attr_line_t::insert(size_t index,
}
if (line_ch_count > 0) {
auto ch_count = space.s_value.utf8_length().unwrap();
auto ch_count = space.s_value.utf8_length().unwrapOr(
space.s_value.length());
if ((line_ch_count + ch_count) > usable_width
&& find_string_attr_containing(this->al_attrs,

@ -47,15 +47,71 @@
struct string_fragment {
using iterator = const char*;
static string_fragment from_c_str(const char* str)
{
return string_fragment{str, 0, (int) strlen(str)};
}
template<typename T, std::size_t N>
static string_fragment from_const(const T (&str)[N])
{
return string_fragment{str, 0, (int) N - 1};
}
static string_fragment from_str(const std::string& str)
{
return string_fragment{str.c_str(), 0, (int) str.size()};
}
static string_fragment from_substr(const std::string& str,
size_t offset,
size_t length)
{
return string_fragment{
str.c_str(), (int) offset, (int) (offset + length)};
}
static string_fragment from_str_range(const std::string& str,
size_t begin,
size_t end)
{
return string_fragment{str.c_str(), (int) begin, (int) end};
}
static string_fragment from_bytes(const char* bytes, size_t len)
{
return string_fragment{bytes, 0, (int) len};
}
static string_fragment from_bytes(const unsigned char* bytes, size_t len)
{
return string_fragment{(const char*) bytes, 0, (int) len};
}
static string_fragment from_memory_buffer(const fmt::memory_buffer& buf)
{
return string_fragment{buf.data(), 0, (int) buf.size()};
}
static string_fragment from_byte_range(const char* bytes,
size_t begin,
size_t end)
{
return string_fragment{bytes, (int) begin, (int) end};
}
explicit string_fragment(const char* str = "", int begin = 0, int end = -1)
: sf_string(str), sf_begin(begin),
sf_end(end == -1 ? strlen(str) : end){};
: sf_string(str), sf_begin(begin), sf_end(end == -1 ? strlen(str) : end)
{
}
explicit string_fragment(const unsigned char* str,
int begin = 0,
int end = -1)
: sf_string((const char*) str), sf_begin(begin),
sf_end(end == -1 ? strlen((const char*) str) : end){};
sf_end(end == -1 ? strlen((const char*) str) : end)
{
}
string_fragment(const std::string& str)
: sf_string(str.c_str()), sf_begin(0), sf_end(str.length())

@ -60,14 +60,18 @@
error.
*/
ssize_t
is_utf8(unsigned char* str, size_t len, const char** message, int* faulty_bytes)
is_utf8(const unsigned char* str,
size_t len,
const char** message,
int* faulty_bytes,
nonstd::optional<unsigned char> terminator)
{
size_t i = 0;
*message = nullptr;
*faulty_bytes = 0;
while (i < len) {
if (str[i] == '\n') {
if (terminator && str[i] == terminator.value()) {
*message = nullptr;
return i;
}

@ -31,9 +31,12 @@
#include <stdlib.h>
#include <sys/types.h>
ssize_t is_utf8(unsigned char* str,
#include "optional.hpp"
ssize_t is_utf8(const unsigned char* str,
size_t len,
const char** message,
int* faulty_bytes);
int* faulty_bytes,
nonstd::optional<unsigned char> terminator = nonstd::nullopt);
#endif /* _IS_UTF8_H */

@ -588,6 +588,18 @@ operator|(nonstd::optional<T> in,
lnav::func::invoke(eacher.fe_func, in.value());
}
template<typename T,
typename F,
std::enable_if_t<lnav::func::is_invocable<F, T>::value, int> = 0>
void
operator|(std::vector<std::shared_ptr<T>>& in,
const lnav::itertools::details::for_eacher<F>& eacher)
{
for (auto& elem : in) {
lnav::func::invoke(eacher.fe_func, *elem);
}
}
template<typename T,
typename F,
std::enable_if_t<lnav::func::is_invocable<F, T>::value, int> = 0>

@ -110,7 +110,7 @@ user_message::to_attr_line(std::set<render_flags> flags) const
retval.append(lnav::roles::ok("\u2714 "));
break;
case level::info:
retval.append(lnav::roles::status("\u24d8 info")).append(": ");
retval.append("\u24d8 info"_info).append(": ");
break;
case level::warning:
retval.append(lnav::roles::warning("\u26a0 warning"))
@ -293,15 +293,31 @@ println(FILE* file, const attr_line_t& al)
fg_style = fmt::fg(color_opt.value());
}
} else if (attr.sa_type == &VC_STYLE) {
auto saw = string_attr_wrapper<int64_t>(&attr);
auto saw = string_attr_wrapper<text_attrs>(&attr);
auto style = saw.get();
if (style & A_REVERSE) {
if (style.ta_attrs & A_REVERSE) {
line_style |= fmt::emphasis::reverse;
}
if (style & A_BOLD) {
if (style.ta_attrs & A_BOLD) {
line_style |= fmt::emphasis::bold;
}
if (style.ta_fg_color) {
auto color_opt = curses_color_to_terminal_color(
style.ta_fg_color.value());
if (color_opt) {
fg_style = fmt::fg(color_opt.value());
}
}
if (style.ta_bg_color) {
auto color_opt = curses_color_to_terminal_color(
style.ta_bg_color.value());
if (color_opt) {
line_style |= fmt::bg(color_opt.value());
}
}
} else if (attr.sa_type == &SA_LEVEL) {
auto level = static_cast<log_level_t>(
attr.sa_value.get<int64_t>());
@ -341,6 +357,7 @@ println(FILE* file, const attr_line_t& al)
line_style |= fmt::emphasis::bold
| fmt::fg(fmt::terminal_color::green);
break;
case role_t::VCR_INFO:
case role_t::VCR_STATUS:
line_style |= fmt::emphasis::bold
| fmt::fg(fmt::terminal_color::magenta);

@ -68,7 +68,7 @@ find_matching_bracket(
} else if (line[lpc] == left && is_bracket(line, lpc, is_lit)) {
if (depth == 0) {
alb.overlay_attr_for_char(
lpc, VC_STYLE.value(A_BOLD | A_REVERSE));
lpc, VC_STYLE.value(text_attrs{A_BOLD | A_REVERSE}));
alb.overlay_attr_for_char(lpc,
VC_ROLE.value(role_t::VCR_OK));
break;
@ -85,7 +85,7 @@ find_matching_bracket(
} else if (line[lpc] == right && is_bracket(line, lpc, is_lit)) {
if (depth == 0) {
alb.overlay_attr_for_char(
lpc, VC_STYLE.value(A_BOLD | A_REVERSE));
lpc, VC_STYLE.value(text_attrs{A_BOLD | A_REVERSE}));
alb.overlay_attr_for_char(lpc,
VC_ROLE.value(role_t::VCR_OK));
break;
@ -110,7 +110,8 @@ find_matching_bracket(
depth -= 1;
} else {
auto lr = line_range(is_lit ? lpc - 1 : lpc, lpc + 1);
alb.overlay_attr(lr, VC_STYLE.value(A_BOLD | A_REVERSE));
alb.overlay_attr(
lr, VC_STYLE.value(text_attrs{A_BOLD | A_REVERSE}));
alb.overlay_attr(lr, VC_ROLE.value(role_t::VCR_ERROR));
}
}
@ -120,7 +121,7 @@ find_matching_bracket(
auto lr
= line_range(is_lit ? first_left.value() - 1 : first_left.value(),
first_left.value() + 1);
alb.overlay_attr(lr, VC_STYLE.value(A_BOLD | A_REVERSE));
alb.overlay_attr(lr, VC_STYLE.value(text_attrs{A_BOLD | A_REVERSE}));
alb.overlay_attr(lr, VC_ROLE.value(role_t::VCR_ERROR));
}
}
@ -189,7 +190,8 @@ regex_highlighter(attr_line_t& al, int x, line_range sub)
if (lpc == sub.lr_start || (lpc - sub.lr_start) == 0) {
alb.overlay_attr_for_char(
lpc, VC_STYLE.value(A_BOLD | A_REVERSE));
lpc,
VC_STYLE.value(text_attrs{A_BOLD | A_REVERSE}));
alb.overlay_attr_for_char(
lpc, VC_ROLE.value(role_t::VCR_ERROR));
} else if (line[lpc - 1] == '(') {
@ -220,10 +222,11 @@ regex_highlighter(attr_line_t& al, int x, line_range sub)
case '>': {
static const pcrepp CAP_RE(R"(\(\?\<\w+$)");
auto sf = string_fragment{
line.c_str(), sub.lr_start, (int) lpc};
auto capture_start = sf.find_left_boundary(
lpc - sub.lr_start - 1, string_fragment::tag1{'('});
auto capture_start
= string_fragment::from_str_range(
line, sub.lr_start, lpc)
.find_left_boundary(lpc - sub.lr_start - 1,
string_fragment::tag1{'('});
pcre_context_static<30> pc;
pcre_input pi(capture_start);
@ -280,8 +283,9 @@ regex_highlighter(attr_line_t& al, int x, line_range sub)
VC_ROLE.value(role_t::VCR_SYMBOL));
break;
case ' ':
alb.overlay_attr(line_range(lpc - 1, lpc + 1),
VC_STYLE.value(A_BOLD | A_REVERSE));
alb.overlay_attr(
line_range(lpc - 1, lpc + 1),
VC_STYLE.value(text_attrs{A_BOLD | A_REVERSE}));
alb.overlay_attr(line_range(lpc - 1, lpc + 1),
VC_ROLE.value(role_t::VCR_ERROR));
break;
@ -296,8 +300,9 @@ regex_highlighter(attr_line_t& al, int x, line_range sub)
alb.overlay_attr(line_range(lpc - 1, lpc + 3),
VC_ROLE.value(role_t::VCR_RE_SPECIAL));
} else {
alb.overlay_attr(line_range(lpc - 1, lpc + 1),
VC_STYLE.value(A_BOLD | A_REVERSE));
alb.overlay_attr(
line_range(lpc - 1, lpc + 1),
VC_STYLE.value(text_attrs{A_BOLD | A_REVERSE}));
alb.overlay_attr(line_range(lpc - 1, lpc + 1),
VC_ROLE.value(role_t::VCR_ERROR));
}

@ -43,7 +43,7 @@ string_attr_type<int64_t> SA_LEVEL("level");
string_attr_type<role_t> VC_ROLE("role");
string_attr_type<role_t> VC_ROLE_FG("role-fg");
string_attr_type<int64_t> VC_STYLE("style");
string_attr_type<text_attrs> VC_STYLE("style");
string_attr_type<int64_t> VC_GRAPHIC("graphic");
string_attr_type<int64_t> VC_FOREGROUND("foreground");
string_attr_type<int64_t> VC_BACKGROUND("background");

@ -49,6 +49,7 @@ enum class role_t : int32_t {
VCR_IDENTIFIER,
VCR_SEARCH, /*< A search hit. */
VCR_OK,
VCR_INFO,
VCR_ERROR, /*< An error message. */
VCR_WARNING, /*< A warning message. */
VCR_ALT_ROW, /*< Highlight for alternating rows in a list */
@ -127,8 +128,29 @@ enum class role_t : int32_t {
VCR__MAX
};
struct text_attrs {
bool empty() const
{
return this->ta_attrs == 0 && !this->ta_fg_color && !this->ta_bg_color;
}
text_attrs operator|(const text_attrs& other) const
{
return text_attrs{
this->ta_attrs | other.ta_attrs,
this->ta_fg_color ? this->ta_fg_color : other.ta_fg_color,
this->ta_bg_color ? this->ta_bg_color : other.ta_bg_color,
};
}
int32_t ta_attrs{0};
nonstd::optional<short> ta_fg_color;
nonstd::optional<short> ta_bg_color;
};
using string_attr_value = mapbox::util::variant<int64_t,
role_t,
text_attrs,
const intern_string_t,
std::string,
std::shared_ptr<logfile>,
@ -183,7 +205,7 @@ extern string_attr_type<int64_t> SA_LEVEL;
extern string_attr_type<role_t> VC_ROLE;
extern string_attr_type<role_t> VC_ROLE_FG;
extern string_attr_type<int64_t> VC_STYLE;
extern string_attr_type<text_attrs> VC_STYLE;
extern string_attr_type<int64_t> VC_GRAPHIC;
extern string_attr_type<int64_t> VC_FOREGROUND;
extern string_attr_type<int64_t> VC_BACKGROUND;
@ -455,6 +477,13 @@ h6(S str)
namespace literals {
inline std::pair<std::string, string_attr_pair> operator"" _info(
const char* str, std::size_t len)
{
return std::make_pair(std::string(str, len),
VC_ROLE.template value(role_t::VCR_INFO));
}
inline std::pair<std::string, string_attr_pair> operator"" _symbol(
const char* str, std::size_t len)
{
@ -483,6 +512,13 @@ inline std::pair<std::string, string_attr_pair> operator"" _comment(
VC_ROLE.template value(role_t::VCR_COMMENT));
}
inline std::pair<std::string, string_attr_pair> operator"" _hotkey(
const char* str, std::size_t len)
{
return std::make_pair(std::string(str, len),
VC_ROLE.template value(role_t::VCR_STATUS_HOTKEY));
}
inline std::pair<std::string, string_attr_pair> operator"" _h1(const char* str,
std::size_t len)
{

@ -90,7 +90,7 @@ breadcrumb_curses::do_update()
- crumb.c_display_value.length()),
(int) crumbs_line.length(),
},
VC_STYLE.template value(A_REVERSE));
VC_STYLE.template value(text_attrs{A_REVERSE}));
}
crumb_index += 1;
crumbs_line.append("\u276d"_breadcrumb);
@ -385,7 +385,7 @@ breadcrumb_curses::search_overlay_source::list_value_for_overlay(
| lnav::itertools::unwrap_or(
breadcrumb::crumb::expected_input_t::exact);
value_out.with_attr_for_all(VC_STYLE.value(A_UNDERLINE));
value_out.with_attr_for_all(VC_STYLE.value(text_attrs{A_UNDERLINE}));
if (!parent->bc_current_search.empty()) {
value_out = parent->bc_current_search;

@ -38,7 +38,7 @@
#include "config.h"
#include "sql_util.hh"
const char* column_namer::BUILTIN_COL = "col";
const char column_namer::BUILTIN_COL[] = "col";
column_namer::column_namer(language lang) : cn_language(lang) {}
@ -79,7 +79,7 @@ column_namer::add_column(const string_fragment& in_name)
int num = 0;
if (in_name.empty()) {
base_name = string_fragment{BUILTIN_COL};
base_name = string_fragment::from_const(BUILTIN_COL);
} else {
base_name = in_name;
}
@ -90,7 +90,7 @@ column_namer::add_column(const string_fragment& in_name)
num = ++counter_iter->second;
fmt::format_to(
std::back_inserter(buf), FMT_STRING("{}_{}"), base_name, num);
retval = string_fragment{buf.data(), 0, (int) buf.size()};
retval = string_fragment::from_memory_buffer(buf);
}
while (this->existing_name(retval)) {
@ -103,7 +103,7 @@ column_namer::add_column(const string_fragment& in_name)
"column name already exists: %.*s", retval.length(), retval.data());
fmt::format_to(
std::back_inserter(buf), FMT_STRING("{}_{}"), base_name, num);
retval = string_fragment{buf.data(), 0, (int) buf.size()};
retval = string_fragment::from_memory_buffer(buf);
num += 1;
}

@ -52,7 +52,7 @@ public:
string_fragment add_column(const string_fragment& in_name);
static const char* BUILTIN_COL;
static const char BUILTIN_COL[];
ArenaAlloc::Alloc<char> cn_alloc;
language cn_language;

@ -34,6 +34,7 @@
#include "base/ansi_scrubber.hh"
#include "base/fs_util.hh"
#include "base/injector.hh"
#include "base/itertools.hh"
#include "base/string_util.hh"
#include "bound_tags.hh"
#include "config.h"
@ -51,6 +52,8 @@
#include "vtab_module.hh"
#include "yajlpp/json_ptr.hh"
using namespace lnav::roles::literals;
exec_context INIT_EXEC_CONTEXT;
static const std::string MSG_FORMAT_STMT = R"(
@ -123,10 +126,36 @@ sql_progress(const struct log_cursor& lc)
}
if (ui_periodic_timer::singleton().time_to_update(sql_counter)) {
struct timeval current_time = {0, 0};
int ch;
while ((ch = getch()) != ERR) {
if (current_time.tv_sec == 0) {
gettimeofday(&current_time, nullptr);
}
lnav_data.ld_user_message_source.clear();
alerter::singleton().new_input(ch);
lnav_data.ld_input_dispatcher.new_input(current_time, ch);
lnav_data.ld_view_stack.top() | [ch](auto tc) {
lnav_data.ld_key_repeat_history.update(ch, tc->get_top());
};
if (!lnav_data.ld_looping) {
// No reason to keep processing input after the
// user has quit. The view stack will also be
// empty, which will cause issues.
break;
}
}
lnav_data.ld_bottom_source.update_loading(off, total);
lnav_data.ld_top_source.update_time();
lnav_data.ld_status[LNS_TOP].do_update();
lnav_data.ld_status[LNS_BOTTOM].do_update();
lnav_data.ld_rl_view->do_update();
refresh();
}
@ -316,6 +345,9 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg)
log_info("Executing SQL: %s", sql.c_str());
auto old_mode = lnav_data.ld_mode;
lnav_data.ld_mode = ln_mode_t::BUSY;
auto mode_fin = finally([old_mode]() { lnav_data.ld_mode = old_mode; });
lnav_data.ld_bottom_source.grep_error("");
if (startswith(stmt_str, ".")) {
@ -400,7 +432,15 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg)
auto bound_values = TRY(bind_sql_parameters(ec, stmt.in()));
if (lnav_data.ld_rl_view != nullptr) {
lnav_data.ld_rl_view->set_value("Executing query: " + sql + " ...");
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());
@ -473,6 +513,8 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg)
lnav_data.ld_views[LNV_DB].reload_data();
lnav_data.ld_views[LNV_DB].set_left(0);
lnav_data.ld_active_files.fc_files
| lnav::itertools::for_each(&logfile::dump_stats);
if (!ec.ec_accumulator->empty()) {
retval = ec.ec_accumulator->get_string();
} else if (!dls.dls_rows.empty()) {
@ -853,8 +895,8 @@ sql_callback(exec_context& ec, sqlite3_stmt* stmt)
return 0;
}
stacked_bar_chart<std::string>& chart = dls.dls_chart;
view_colors& vc = view_colors::singleton();
auto& chart = dls.dls_chart;
auto& vc = view_colors::singleton();
int ncols = sqlite3_column_count(stmt);
int row_number;
int lpc, retval = 0;
@ -875,7 +917,7 @@ sql_callback(exec_context& ec, sqlite3_stmt* stmt)
dls.push_header(colname, type, graphable);
if (graphable) {
int attrs = vc.attrs_for_ident(colname);
auto attrs = vc.attrs_for_ident(colname);
chart.with_attrs_for_ident(colname, attrs);
}
}
@ -898,11 +940,9 @@ sql_callback(exec_context& ec, sqlite3_stmt* stmt)
value = null_value_t{};
break;
default:
value = string_fragment{
value = string_fragment::from_bytes(
sqlite3_value_text(raw_value),
0,
sqlite3_value_bytes(raw_value),
};
sqlite3_value_bytes(raw_value));
break;
}
dls.push_column(value);

@ -37,7 +37,7 @@
#include "config.h"
#include "yajlpp/json_ptr.hh"
const char* db_label_source::NULL_STR = "<NULL>";
const char db_label_source::NULL_STR[] = "<NULL>";
constexpr size_t MAX_COLUMN_WIDTH = 120;
constexpr size_t MAX_JSON_WIDTH = 16 * 1024;
@ -93,7 +93,7 @@ db_label_source::text_attrs_for_line(textview_curses& tc,
}
for (size_t lpc = 0; lpc < this->dls_headers.size() - 1; lpc++) {
if (row % 2 == 0) {
sa.emplace_back(lr2, VC_STYLE.value(A_BOLD));
sa.emplace_back(lr2, VC_STYLE.value(text_attrs{A_BOLD}));
}
lr.lr_start += this->dls_cell_width[lpc];
lr.lr_end = lr.lr_start + 1;
@ -166,7 +166,7 @@ db_label_source::push_column(const scoped_value_t& sv)
double num_value = 0.0;
auto col_sf = sv.match(
[](const std::string& str) { return string_fragment{str}; },
[](const std::string& str) { return string_fragment::from_str(str); },
[this](const string_fragment& sf) {
return sf.to_owned(*this->dls_allocator);
},
@ -174,17 +174,17 @@ db_label_source::push_column(const scoped_value_t& sv)
fmt::memory_buffer buf;
fmt::format_to(std::back_inserter(buf), FMT_STRING("{}"), i);
return string_fragment{buf.data(), 0, (int) buf.size()}.to_owned(
return string_fragment::from_memory_buffer(buf).to_owned(
*this->dls_allocator);
},
[this](double d) {
fmt::memory_buffer buf;
fmt::format_to(std::back_inserter(buf), FMT_STRING("{}"), d);
return string_fragment{buf.data(), 0, (int) buf.size()}.to_owned(
return string_fragment::from_memory_buffer(buf).to_owned(
*this->dls_allocator);
},
[](null_value_t) { return string_fragment{NULL_STR}; });
[](null_value_t) { return string_fragment::from_const(NULL_STR); });
if (index == this->dls_time_column_index) {
date_time_scanner dts;
@ -332,7 +332,7 @@ db_overlay_source::list_overlay_count(const listview_curses& lv)
sa.emplace_back(lr, VC_GRAPHIC.value(ACS_LTEE));
lr.lr_start = 3 + jpw_value.wt_ptr.size() + 3;
lr.lr_end = -1;
sa.emplace_back(lr, VC_STYLE.value(A_BOLD));
sa.emplace_back(lr, VC_STYLE.value(text_attrs{A_BOLD}));
double num_value = 0.0;
@ -340,7 +340,7 @@ db_overlay_source::list_overlay_count(const listview_curses& lv)
&& sscanf(jpw_value.wt_value.c_str(), "%lf", &num_value)
== 1)
{
int attrs = vc.attrs_for_ident(jpw_value.wt_ptr);
auto attrs = vc.attrs_for_ident(jpw_value.wt_ptr);
chart.add_value(jpw_value.wt_ptr, num_value);
chart.with_attrs_for_ident(jpw_value.wt_ptr, attrs);
@ -423,17 +423,19 @@ db_overlay_source::list_value_for_overlay(const listview_curses& lv,
struct line_range header_range(line_len_before, line.length());
int attrs
= vc.attrs_for_ident(dls->dls_headers[lpc].hm_name) | A_REVERSE;
if (!this->dos_labels->dls_headers[lpc].hm_graphable) {
attrs = A_UNDERLINE;
text_attrs attrs;
if (this->dos_labels->dls_headers[lpc].hm_graphable) {
attrs = vc.attrs_for_ident(dls->dls_headers[lpc].hm_name)
| text_attrs{A_REVERSE};
} else {
attrs.ta_attrs = A_UNDERLINE;
}
sa.emplace_back(header_range, VC_STYLE.value(attrs));
sa.emplace_back(header_range, VC_STYLE.value(text_attrs{attrs}));
}
struct line_range lr(0);
sa.emplace_back(lr, VC_STYLE.value(A_BOLD | A_UNDERLINE));
sa.emplace_back(lr, VC_STYLE.value(text_attrs{A_BOLD | A_UNDERLINE}));
return true;
} else if (this->dos_active && y >= 2
&& ((size_t) y) < (this->dos_lines.size() + 2))

@ -123,7 +123,7 @@ public:
std::unique_ptr<ArenaAlloc::Alloc<char>> dls_allocator{
std::make_unique<ArenaAlloc::Alloc<char>>(64 * 1024)};
static const char* NULL_STR;
static const char NULL_STR[];
};
class db_overlay_source : public list_overlay_source {

@ -131,7 +131,7 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
time_str.append(curr_timestamp);
time_lr.lr_end = time_str.length();
time_line.with_attr(
string_attr(time_lr, VC_STYLE.value(A_BOLD)));
string_attr(time_lr, VC_STYLE.value(text_attrs{A_BOLD})));
time_str.append(" -- ");
time_lr.lr_start = time_str.length();
time_str.append(humanize::time::point::from_tv(ll->get_timeval())
@ -139,7 +139,7 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
.as_precise_time_ago());
time_lr.lr_end = time_str.length();
time_line.with_attr(
string_attr(time_lr, VC_STYLE.value(A_BOLD)));
string_attr(time_lr, VC_STYLE.value(text_attrs{A_BOLD})));
struct line_range time_range = find_string_attr_range(
this->fos_log_helper.ldh_line_attrs, &logline::L_TIMESTAMP);
@ -181,7 +181,7 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
humanize::time::duration::from_tv(diff_tv).to_string());
time_lr.lr_end = time_str.length();
time_line.with_attr(
string_attr(time_lr, VC_STYLE.value(A_BOLD)));
string_attr(time_lr, VC_STYLE.value(text_attrs{A_BOLD})));
}
}
@ -282,10 +282,10 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
if (curr_format != last_format) {
this->fos_lines.emplace_back(" Known message fields for table "
+ format_name + ":");
this->fos_lines.back().with_attr(string_attr(
line_range(32, 32 + format_name.length()),
VC_STYLE.value(vc.attrs_for_ident(format_name)
| A_BOLD)));
this->fos_lines.back().with_attr(
string_attr(line_range(32, 32 + format_name.length()),
VC_STYLE.value(vc.attrs_for_ident(format_name)
| text_attrs{A_BOLD})));
last_format = curr_format;
}
@ -344,8 +344,8 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
- 9 + 3,
' ')
.append(" = ")
.append(string_fragment{
(const char*) js.js_content.in(), 0, (int) js.js_len});
.append(
string_fragment::from_bytes(js.js_content.in(), js.js_len));
this->fos_lines.emplace_back(al);
this->add_key_line_attrs(this->fos_known_key_size);
}
@ -406,7 +406,7 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
auto& disc_str = al.get_string();
al.with_attr(string_attr(line_range(disc_str.length(), -1),
VC_STYLE.value(A_BOLD)));
VC_STYLE.value(text_attrs{A_BOLD})));
disc_str.append(this->fos_log_helper.ldh_msg_format);
}
@ -488,7 +488,7 @@ field_overlay_source::add_key_line_attrs(int key_size, bool last_line)
lr.lr_start = 3 + key_size + 3;
lr.lr_end = -1;
sa.emplace_back(lr, VC_STYLE.value(A_BOLD));
sa.emplace_back(lr, VC_STYLE.value(text_attrs{A_BOLD}));
}
bool

@ -334,7 +334,7 @@ files_sub_source::text_attrs_for_line(textview_curses& tc,
}
if (line == fc.fc_other_files.size() - 1) {
value_out.emplace_back(line_range{0, -1},
VC_STYLE.value(A_UNDERLINE));
VC_STYLE.value(text_attrs{A_UNDERLINE}));
}
return;
}
@ -366,7 +366,7 @@ files_sub_source::text_attrs_for_line(textview_curses& tc,
(int) filename_width + 3 + 4,
(int) filename_width + 3 + 10,
};
value_out.emplace_back(lr, VC_STYLE.value(A_BOLD));
value_out.emplace_back(lr, VC_STYLE.value(text_attrs{A_BOLD}));
lr.lr_start = this->fss_last_line_len;
lr.lr_end = -1;

@ -210,10 +210,9 @@ filter_status_source::update_filtered(text_sub_source* tss)
if (tss->get_filtered_count() == this->bss_last_filtered_count) {
if (timer.fade_diff(this->bss_filter_counter) == 0) {
this->tss_fields[TSF_FILTERED].set_role(
role_t::VCR_STATUS);
this->tss_fields[TSF_FILTERED].set_role(role_t::VCR_STATUS);
al.with_attr(string_attr(line_range{0, -1},
VC_STYLE.value(A_BOLD)));
VC_STYLE.value(text_attrs{A_BOLD})));
}
} else {
this->tss_fields[TSF_FILTERED].set_role(

@ -298,9 +298,9 @@ filter_sub_source::text_value_for_line(textview_curses& tc,
std::string& value_out,
text_sub_source::line_flags_t flags)
{
textview_curses* top_view = *lnav_data.ld_view_stack.top();
text_sub_source* tss = top_view->get_sub_source();
filter_stack& fs = tss->get_filters();
auto* top_view = *lnav_data.ld_view_stack.top();
auto* tss = top_view->get_sub_source();
auto& fs = tss->get_filters();
auto tf = *(fs.begin() + line);
value_out = " ";
@ -357,19 +357,21 @@ filter_sub_source::text_attrs_for_line(textview_curses& tc,
value_out.emplace_back(lr, VC_FOREGROUND.value(COLOR_GREEN));
}
if (selected) {
value_out.emplace_back(line_range{0, -1},
VC_ROLE.value(role_t::VCR_FOCUSED));
}
role_t fg_role = tf->get_type() == text_filter::INCLUDE ? role_t::VCR_OK
: role_t::VCR_ERROR;
value_out.emplace_back(line_range{4, 7}, VC_ROLE.value(fg_role));
value_out.emplace_back(line_range{4, 7}, VC_STYLE.value(A_BOLD));
value_out.emplace_back(line_range{4, 7},
VC_STYLE.value(text_attrs{A_BOLD}));
value_out.emplace_back(line_range{8, 17}, VC_STYLE.value(A_BOLD));
value_out.emplace_back(line_range{8, 17},
VC_STYLE.value(text_attrs{A_BOLD}));
value_out.emplace_back(line_range{23, 24}, VC_GRAPHIC.value(ACS_VLINE));
if (selected) {
value_out.emplace_back(line_range{0, -1},
VC_ROLE.value(role_t::VCR_FOCUSED));
}
attr_line_t content{tf->get_id()};
auto& content_attrs = content.get_attrs();
@ -436,15 +438,11 @@ filter_sub_source::rl_change(readline_curses* rc)
} else {
auto& hm = top_view->get_highlights();
highlighter hl(code.release());
int color;
if (tf->get_type() == text_filter::EXCLUDE) {
color = COLOR_RED;
} else {
color = COLOR_GREEN;
}
hl.with_attrs(view_colors::ansi_color_pair(COLOR_BLACK, color)
| A_BLINK);
auto role = tf->get_type() == text_filter::EXCLUDE
? role_t::VCR_DIFF_DELETE
: role_t::VCR_DIFF_ADD;
hl.with_role(role);
hl.with_attrs(text_attrs{A_BLINK | A_REVERSE});
hm[{highlight_source_t::PREVIEW, "preview"}] = hl;
top_view->set_needs_update();
@ -616,7 +614,7 @@ filter_sub_source::rl_display_matches(readline_curses* rc)
for (const auto& match : matches) {
if (match == current_match) {
al.append(match, VC_STYLE.value(A_REVERSE));
al.append(match, VC_STYLE.value(text_attrs{A_REVERSE}));
selected_line = line;
} else {
al.append(match);

@ -21,26 +21,23 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file logfmt.parser.cc
*/
#include "config.h"
#include "logfmt.parser.hh"
#include "base/string_util.hh"
#include "logfmt.parser.hh"
#include "config.h"
logfmt::parser::parser(string_fragment sf)
: p_next_input(sf)
{
logfmt::parser::parser(string_fragment sf) : p_next_input(sf) {}
}
static bool is_not_eq(char ch)
static bool
is_not_eq(char ch)
{
return ch != '=';
}
@ -68,11 +65,13 @@ struct bare_value_predicate {
float_state_t bvp_float_state{float_state_t::INIT};
size_t bvp_index{0};
bool is_integer() const {
bool is_integer() const
{
return this->bvp_int_state == int_state_t::DIGITS;
}
bool is_float() const {
bool is_float() const
{
switch (this->bvp_float_state) {
case float_state_t::DIGITS:
case float_state_t::FRACTION_DIGIT:
@ -83,7 +82,8 @@ struct bare_value_predicate {
}
}
bool operator()(char ch) {
bool operator()(char ch)
{
if (ch == ' ') {
return false;
}
@ -169,7 +169,8 @@ struct bare_value_predicate {
}
};
logfmt::parser::step_result logfmt::parser::step()
logfmt::parser::step_result
logfmt::parser::step()
{
const static auto IS_DQ = string_fragment::tag1{'"'};
@ -209,48 +210,52 @@ logfmt::parser::step_result logfmt::parser::step()
}
this->p_next_input = after_quote.value();
return std::make_pair(key_frag, quoted_value{string_fragment{
quoted_pair->first.sf_string,
quoted_pair->first.sf_begin - 1,
quoted_pair->first.sf_end + 1
}});
} else {
bare_value_predicate bvp;
auto value_pair = value_start.split_while(bvp);
if (value_pair) {
static const auto TRUE_FRAG = string_fragment{"true"};
static const auto FALSE_FRAG = string_fragment{"false"};
this->p_next_input = value_pair->second;
if (bvp.is_integer()) {
int_value retval;
strtonum(retval.iv_value,
value_pair->first.data(),
value_pair->first.length());
retval.iv_str_value = value_pair->first;
return std::make_pair(key_frag, retval);
} else if (bvp.is_float()) {
char float_copy[value_pair->first.length() + 1];
float_value retval;
strncpy(float_copy, value_pair->first.data(), value_pair->first.length());
float_copy[value_pair->first.length()] = '\0';
retval.fv_value = strtod(float_copy, nullptr);
retval.fv_str_value = value_pair->first;
return std::make_pair(key_frag, retval);
} else if (value_pair->first.iequal(TRUE_FRAG)) {
return std::make_pair(key_frag, bool_value{true, value_pair->first});
} else if (value_pair->first.iequal(FALSE_FRAG)) {
return std::make_pair(key_frag, bool_value{false, value_pair->first});
}
return std::make_pair(key_frag, unquoted_value{value_pair->first});
} else {
this->p_next_input = value_start;
return std::make_pair(key_frag, unquoted_value{string_fragment{""}});
return std::make_pair(
key_frag,
quoted_value{string_fragment{quoted_pair->first.sf_string,
quoted_pair->first.sf_begin - 1,
quoted_pair->first.sf_end + 1}});
}
bare_value_predicate bvp;
auto value_pair = value_start.split_while(bvp);
if (value_pair) {
static const auto TRUE_FRAG = string_fragment::from_const("true");
static const auto FALSE_FRAG = string_fragment::from_const("false");
this->p_next_input = value_pair->second;
if (bvp.is_integer()) {
int_value retval;
strtonum(retval.iv_value,
value_pair->first.data(),
value_pair->first.length());
retval.iv_str_value = value_pair->first;
return std::make_pair(key_frag, retval);
} else if (bvp.is_float()) {
char float_copy[value_pair->first.length() + 1];
float_value retval;
strncpy(float_copy,
value_pair->first.data(),
value_pair->first.length());
float_copy[value_pair->first.length()] = '\0';
retval.fv_value = strtod(float_copy, nullptr);
retval.fv_str_value = value_pair->first;
return std::make_pair(key_frag, retval);
} else if (value_pair->first.iequal(TRUE_FRAG)) {
return std::make_pair(key_frag,
bool_value{true, value_pair->first});
} else if (value_pair->first.iequal(FALSE_FRAG)) {
return std::make_pair(key_frag,
bool_value{false, value_pair->first});
}
return std::make_pair(key_frag, unquoted_value{value_pair->first});
} else {
this->p_next_input = value_start;
return std::make_pair(key_frag, unquoted_value{string_fragment{}});
}
}

@ -135,27 +135,25 @@ highlighter::annotate(attr_line_t& al, int start) const
sa, &VC_STYLE, lr)
== sa.end()))
{
int attrs = 0;
if (this->h_attrs != -1) {
attrs = this->h_attrs;
}
if (!this->h_fg.empty()) {
sa.emplace_back(lr,
VC_FOREGROUND.value(
vc.match_color(this->h_fg)));
sa.emplace_back(
lr,
VC_FOREGROUND.value(
vc.match_color(this->h_fg)
.value_or(view_colors::MATCH_COLOR_DEFAULT)));
}
if (!this->h_bg.empty()) {
sa.emplace_back(lr,
VC_BACKGROUND.value(
vc.match_color(this->h_bg)));
sa.emplace_back(
lr,
VC_BACKGROUND.value(
vc.match_color(this->h_bg)
.value_or(view_colors::MATCH_COLOR_DEFAULT)));
}
if (this->h_role != role_t::VCR_NONE) {
sa.emplace_back(lr,
VC_ROLE.value(this->h_role));
sa.emplace_back(lr, VC_ROLE.value(this->h_role));
}
if (attrs) {
sa.emplace_back(lr, VC_STYLE.value(attrs));
if (!this->h_attrs.empty()) {
sa.emplace_back(lr, VC_STYLE.value(this->h_attrs));
}
off = matches[1];

@ -40,7 +40,7 @@
#include "view_curses.hh"
struct highlighter {
highlighter() : h_code(nullptr), h_code_extra(nullptr){};
highlighter() : h_code(nullptr), h_code_extra(nullptr) {}
explicit highlighter(pcre* code) : h_code(code)
{
@ -77,7 +77,7 @@ struct highlighter {
return *this;
}
highlighter& with_attrs(int attrs)
highlighter& with_attrs(text_attrs attrs)
{
this->h_attrs = attrs;
@ -113,12 +113,7 @@ struct highlighter {
return *this;
}
int get_attrs() const
{
ensure(this->h_attrs != -1);
return this->h_attrs;
}
text_attrs get_attrs() const { return this->h_attrs; }
void annotate(attr_line_t& al, int start) const;
@ -128,7 +123,7 @@ struct highlighter {
styling::color_unit h_bg{styling::color_unit::make_empty()};
pcre* h_code;
pcre_extra* h_code_extra;
int h_attrs{-1};
text_attrs h_attrs;
std::set<text_format_t> h_text_formats;
intern_string_t h_format_name;
bool h_nestable{true};

@ -80,9 +80,9 @@ public:
return *this;
}
stacked_bar_chart& with_attrs_for_ident(const T& ident, int attrs)
stacked_bar_chart& with_attrs_for_ident(const T& ident, text_attrs attrs)
{
struct chart_ident& ci = this->find_ident(ident);
auto& ci = this->find_ident(ident);
ci.ci_attrs = attrs;
return *this;
}
@ -221,8 +221,10 @@ public:
}
lr.lr_end = left = lr.lr_start + amount;
if (ci.ci_attrs != 0 && !lr.empty()) {
value_out.emplace_back(lr, VC_STYLE.value(ci.ci_attrs | A_REVERSE));
if (!ci.ci_attrs.empty() && !lr.empty()) {
auto rev_attrs = ci.ci_attrs;
rev_attrs.ta_attrs |= A_REVERSE;
value_out.emplace_back(lr, VC_STYLE.value(rev_attrs));
}
}
@ -283,7 +285,7 @@ protected:
explicit chart_ident(const T& ident) : ci_ident(ident) {}
T ci_ident;
int ci_attrs{0};
text_attrs ci_attrs;
bucket_stats_t ci_stats;
};

@ -122,12 +122,27 @@ key_sql_callback(exec_context& ec, sqlite3_stmt* stmt)
if (sql_ident_needs_quote(column_name)) {
continue;
}
if (sqlite3_column_type(stmt, lpc) == SQLITE_NULL) {
continue;
}
vars[column_name]
= std::string((const char*) sqlite3_column_text(stmt, lpc));
auto* raw_value = sqlite3_column_value(stmt, lpc);
auto value_type = sqlite3_column_type(stmt, lpc);
scoped_value_t value;
switch (value_type) {
case SQLITE_INTEGER:
value = (int64_t) sqlite3_value_int64(raw_value);
break;
case SQLITE_FLOAT:
value = sqlite3_value_double(raw_value);
break;
case SQLITE_NULL:
value = null_value_t{};
break;
default:
value = string_fragment::from_bytes(
sqlite3_value_text(raw_value),
sqlite3_value_bytes(raw_value));
break;
}
vars[column_name] = value;
}
return 0;

@ -75,7 +75,7 @@ struct contains_userdata {
static int
contains_string(void* ctx, const unsigned char* str, size_t len)
{
auto sf = string_fragment{(const char*) str, 0, (int) len};
auto sf = string_fragment::from_bytes(str, len);
auto& cu = *((contains_userdata*) ctx);
if (cu.cu_depth <= 1 && cu.cu_match_value.get<string_fragment>() == sf) {
@ -156,11 +156,8 @@ json_contains(vtab_types::nullable<const char> nullable_json_in,
switch (sqlite3_value_type(value)) {
case SQLITE3_TEXT:
cb.yajl_string = contains_string;
cu.cu_match_value = string_fragment{
(const char*) sqlite3_value_text(value),
0,
sqlite3_value_bytes(value),
};
cu.cu_match_value = string_fragment::from_bytes(
sqlite3_value_text(value), sqlite3_value_bytes(value));
break;
case SQLITE_INTEGER:
cb.yajl_integer = contains_integer;

@ -88,15 +88,9 @@ class lock_hack {
public:
class guard {
public:
guard() : g_lock(lock_hack::singleton())
{
this->g_lock.lock();
};
guard() : g_lock(lock_hack::singleton()) { this->g_lock.lock(); }
~guard()
{
this->g_lock.unlock();
};
~guard() { this->g_lock.unlock(); }
private:
lock_hack& g_lock;
@ -107,17 +101,11 @@ public:
static lock_hack retval;
return retval;
};
}
void lock()
{
lockf(this->lh_fd, F_LOCK, 0);
};
void lock() { lockf(this->lh_fd, F_LOCK, 0); }
void unlock()
{
lockf(this->lh_fd, F_ULOCK, 0);
};
void unlock() { lockf(this->lh_fd, F_ULOCK, 0); }
private:
lock_hack()
@ -128,7 +116,7 @@ private:
this->lh_fd = open(lockname, O_CREAT | O_RDWR, 0600);
log_perror(fcntl(this->lh_fd, F_SETFD, FD_CLOEXEC));
unlink(lockname);
};
}
auto_fd lh_fd;
};
@ -649,8 +637,11 @@ line_buffer::load_next_buffer()
auto before = line_start - this->lb_alt_buffer->begin();
auto remaining = this->lb_alt_buffer.value().size() - before;
auto utf8_end = is_utf8(
(unsigned char*) line_start, remaining, &msg, &faulty_bytes);
auto utf8_end = is_utf8((unsigned char*) line_start,
remaining,
&msg,
&faulty_bytes,
'\n');
if (msg != nullptr) {
lf = (char*) memchr(line_start, '\n', remaining);
utf8_end = lf - line_start;
@ -722,6 +713,7 @@ line_buffer::fill_range(file_off_t start, ssize_t max_length)
this->lb_alt_line_starts.clear();
this->lb_line_is_utf = std::move(this->lb_alt_line_is_utf);
this->lb_alt_line_is_utf.clear();
this->lb_stats.s_used_preloads += 1;
}
if (this->in_range(start) && this->in_range(start + max_length - 1)) {
/* Cache already has the data, nothing to do. */
@ -755,6 +747,7 @@ line_buffer::fill_range(file_off_t start, ssize_t max_length)
#endif
auto prom = std::make_shared<std::promise<bool>>();
this->lb_loader_future = prom->get_future();
this->lb_stats.s_requested_preloads += 1;
isc::to<io_looper&, io_looper_tag>().send(
[this, prom](auto& ioloop) mutable {
prom->set_value(this->load_next_buffer());
@ -777,6 +770,12 @@ line_buffer::fill_range(file_off_t start, ssize_t max_length)
{
rc = 0;
} else {
this->lb_stats.s_decompressions += 1;
if (this->lb_last_line_offset > 0) {
this->lb_stats.s_hist[(this->lb_file_offset * 10)
/ this->lb_last_line_offset]
+= 1;
}
rc = gi->read(this->lb_buffer.end(),
this->lb_file_offset + this->lb_buffer.size(),
this->lb_buffer.available());
@ -852,6 +851,17 @@ line_buffer::fill_range(file_off_t start, ssize_t max_length)
#endif
else if (this->lb_seekable)
{
this->lb_stats.s_preads += 1;
if (this->lb_last_line_offset > 0) {
this->lb_stats.s_hist[(this->lb_file_offset * 10)
/ this->lb_last_line_offset]
+= 1;
}
#if 0
log_debug("%d: pread %lld",
this->lb_fd.get(),
this->lb_file_offset + this->lb_buffer.size());
#endif
rc = pread(this->lb_fd,
this->lb_buffer.end(),
this->lb_buffer.available(),
@ -943,6 +953,7 @@ line_buffer::fill_range(file_off_t start, ssize_t max_length)
#endif
auto prom = std::make_shared<std::promise<bool>>();
this->lb_loader_future = prom->get_future();
this->lb_stats.s_requested_preloads += 1;
isc::to<io_looper&, io_looper_tag>().send(
[this, prom](auto& ioloop) mutable {
prom->set_value(this->load_next_buffer());
@ -1018,7 +1029,8 @@ line_buffer::load_next_line(file_range prev_line)
utf8_end = is_utf8((unsigned char*) line_start,
retval.li_file_range.fr_size,
&msg,
&faulty_bytes);
&faulty_bytes,
'\n');
if (msg != nullptr) {
lf = (char*) memchr(
line_start, '\n', retval.li_file_range.fr_size);

@ -32,6 +32,7 @@
#ifndef line_buffer_hh
#define line_buffer_hh
#include <array>
#include <exception>
#include <future>
#include <vector>
@ -243,6 +244,31 @@ public:
void quiesce();
struct stats {
bool empty() const
{
return this->s_decompressions == 0 && this->s_preads == 0
&& this->s_requested_preloads == 0
&& this->s_used_preloads == 0;
}
uint32_t s_decompressions{0};
uint32_t s_preads{0};
uint32_t s_requested_preloads{0};
uint32_t s_used_preloads{0};
std::array<uint32_t, 10> s_hist{};
};
struct stats consume_stats()
{
return std::exchange(this->lb_stats, {});
}
size_t get_buffer_size() const
{
return this->lb_buffer.size();
}
private:
/**
* @param off The file offset to check for in the buffer.
@ -340,6 +366,7 @@ private:
std::vector<uint32_t> lb_line_starts;
std::vector<bool> lb_line_is_utf;
stats lb_stats;
};
#endif

@ -197,7 +197,7 @@ listview_curses::do_update()
struct line_range lr;
unsigned long width, wrap_width;
int y = this->lv_y, bottom;
attr_t role_attrs = vc.attrs_for_role(this->vc_default_role);
auto role_attrs = vc.attrs_for_role(this->vc_default_role);
this->get_dimensions(height, width);
@ -254,9 +254,12 @@ listview_curses::do_update()
&& lr.lr_start < (int) al.length());
++row;
} else {
wattron(this->lv_window, role_attrs);
wattr_set(this->lv_window,
role_attrs.ta_attrs,
vc.ensure_color_pair(role_attrs.ta_fg_color,
role_attrs.ta_bg_color),
nullptr);
mvwhline(this->lv_window, y, this->lv_x, ' ', width);
wattroff(this->lv_window, role_attrs);
++y;
}
}
@ -283,7 +286,7 @@ listview_curses::do_update()
int range_start = 0, range_end;
role_t role = this->vc_default_role;
role_t bar_role = role_t::VCR_SCROLLBAR;
int attrs;
text_attrs attrs;
chtype ch = ACS_VLINE;
if (row_count > 0) {
@ -299,9 +302,12 @@ listview_curses::do_update()
role = bar_role;
}
attrs = vc.attrs_for_role(role);
wattron(this->lv_window, attrs);
wattr_set(
this->lv_window,
attrs.ta_attrs,
vc.ensure_color_pair(attrs.ta_fg_color, attrs.ta_bg_color),
nullptr);
mvwaddch(this->lv_window, gutter_y, this->lv_x + width - 1, ch);
wattroff(this->lv_window, attrs);
}
wmove(this->lv_window, this->lv_y + height - 1, this->lv_x);
}

@ -82,6 +82,7 @@
#include "base/humanize.time.hh"
#include "base/injector.bind.hh"
#include "base/isc.hh"
#include "base/itertools.hh"
#include "base/lnav.console.hh"
#include "base/lnav_log.hh"
#include "base/paths.hh"
@ -906,6 +907,14 @@ handle_key(int ch)
handle_rl_key(ch);
break;
case ln_mode_t::BUSY:
switch (ch) {
case KEY_CTRL_RBRACKET:
log_vtab_data.lvd_looping = false;
break;
}
break;
default:
require(0);
break;
@ -1133,10 +1142,8 @@ looper()
for (const auto& format : log_format::get_root_formats()) {
for (auto& hl : format->lf_highlighters) {
if (hl.h_fg.empty()) {
hl.with_attrs(hl.h_attrs
| vc.attrs_for_ident(hl.h_pattern));
}
hl.with_attrs(hl.h_attrs
| vc.attrs_for_ident(hl.h_pattern));
lnav_data.ld_views[LNV_LOG].get_highlights()[{
highlight_source_t::CONFIGURATION,
@ -1174,7 +1181,7 @@ looper()
&lnav_data.ld_bottom_source));
sb.push_back(bind_mem(&bottom_status_source::update_marks,
&lnav_data.ld_bottom_source));
sb.push_back(
vsb.push_back(
bind_mem(&term_extra::update_title, injector::get<term_extra*>()));
vsb.push_back([](listview_curses* lv) {
auto* tc = dynamic_cast<textview_curses*>(lv);
@ -1413,7 +1420,7 @@ UPDATE lnav_views_echo
attr_line_t("restored session from ")
.append(lnav::roles::number(ago))
.append("; press ")
.append("CTRL-R"_symbol)
.append("CTRL-R"_hotkey)
.append(" to reset session"));
lnav_data.ld_rl_view->set_attr_value(um.to_attr_line());
}
@ -1621,6 +1628,7 @@ UPDATE lnav_views_echo
case ln_mode_t::FILTER:
case ln_mode_t::FILES:
case ln_mode_t::SPECTRO_DETAILS:
case ln_mode_t::BUSY:
if (old_gen
== lnav_data.ld_active_files
.fc_files_generation) {
@ -1772,7 +1780,8 @@ UPDATE lnav_views_echo
}
if (session_stage == 1
&& (lnav_data.ld_log_source.text_line_count() > 0
&& (lnav_data.ld_active_files.fc_file_names.empty()
|| lnav_data.ld_log_source.text_line_count() > 0
|| lnav_data.ld_text_source.text_line_count() > 0
|| !lnav_data.ld_active_files.fc_other_files.empty()))
{
@ -1791,6 +1800,9 @@ UPDATE lnav_views_echo
{
log_debug("switching to paging!");
lnav_data.ld_mode = ln_mode_t::PAGING;
lnav_data.ld_active_files.fc_files
| lnav::itertools::for_each(
&logfile::dump_stats);
} else {
lnav_data.ld_files_view.set_selection(0_vl);
}
@ -2071,9 +2083,6 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
static const std::string DEFAULT_DEBUG_LOG = "/dev/null";
lnav_data.ld_debug_log_name = DEFAULT_DEBUG_LOG;
lnav_data.ld_config_paths.emplace_back("/etc/lnav");
lnav_data.ld_config_paths.emplace_back(SYSCONFDIR "/lnav");
lnav_data.ld_config_paths.emplace_back(lnav::paths::dotlnav());
std::vector<std::string> file_args;
std::vector<lnav::console::user_message> arg_errors;
@ -2228,6 +2237,13 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
return e.get_exit_code();
}
lnav_data.ld_config_paths.insert(lnav_data.ld_config_paths.begin(),
lnav::paths::dotlnav());
lnav_data.ld_config_paths.insert(lnav_data.ld_config_paths.begin(),
SYSCONFDIR "/lnav");
lnav_data.ld_config_paths.insert(lnav_data.ld_config_paths.begin(),
"/etc/lnav");
if (lnav_data.ld_debug_log_name != DEFAULT_DEBUG_LOG) {
lnav_log_level = lnav_log_level_t::TRACE;
}

@ -127,7 +127,7 @@ remaining_args_frag(const std::string& cmdline,
require(index_in_cmdline != std::string::npos);
return string_fragment{cmdline.c_str(), static_cast<int>(index_in_cmdline)};
return string_fragment::from_str_range(cmdline, index_in_cmdline, cmdline.size());
}
static nonstd::optional<std::string>
@ -1606,10 +1606,10 @@ com_highlight(exec_context& ec,
return Err(um);
} else {
highlighter hl(code.release());
attr_t hl_attrs = view_colors::singleton().attrs_for_ident(args[1]);
auto hl_attrs = view_colors::singleton().attrs_for_ident(args[1]);
if (ec.ec_dry_run) {
hl_attrs |= A_BLINK;
hl_attrs.ta_attrs |= A_BLINK;
}
hl.with_attrs(hl_attrs);
@ -1752,22 +1752,17 @@ com_filter(exec_context& ec,
} else {
auto& hm = tc->get_highlights();
highlighter hl(code.release());
int color;
if (args[0] == "filter-out") {
color = COLOR_RED;
} else {
color = COLOR_GREEN;
}
hl.with_attrs(view_colors::ansi_color_pair(COLOR_BLACK, color)
| A_BLINK);
auto role = (args[0] == "filter-out") ?
role_t::VCR_DIFF_DELETE :
role_t::VCR_DIFF_ADD;
hl.with_attrs(text_attrs{A_BLINK});
hm[{highlight_source_t::PREVIEW, "preview"}] = hl;
tc->reload_data();
lnav_data.ld_preview_status_source.get_description().set_value(
"Matches are highlighted in %s in the text view",
color == COLOR_RED ? "red" : "green");
role == role_t::VCR_DIFF_DELETE ? "red" : "green");
retval = "";
}
@ -2179,12 +2174,12 @@ com_create_search_table(exec_context& ec,
auto tab_name = intern_string::lookup(args[1]);
auto lst = std::make_shared<log_search_table>(re, tab_name);
if (ec.ec_dry_run) {
textview_curses* tc = &lnav_data.ld_views[LNV_LOG];
auto* tc = &lnav_data.ld_views[LNV_LOG];
auto& hm = tc->get_highlights();
highlighter hl(re.p_code);
hl.with_attrs(view_colors::ansi_color_pair(COLOR_BLACK, COLOR_CYAN)
| A_BLINK);
hl.with_role(role_t::VCR_INFO);
hl.with_attrs(text_attrs{A_BLINK});
hm[{highlight_source_t::PREVIEW, "preview"}] = hl;
tc->reload_data();
@ -2210,7 +2205,7 @@ com_create_search_table(exec_context& ec,
errmsg = lnav_data.ld_vtab_manager->register_vtab(lst);
if (errmsg.empty()) {
custom_search_tables.insert(args[1]);
if (lnav_data.ld_rl_view != NULL) {
if (lnav_data.ld_rl_view != nullptr) {
lnav_data.ld_rl_view->add_possibility(
ln_mode_t::COMMAND, "search-table", args[1]);
}
@ -2556,8 +2551,7 @@ com_open(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
}
if (gl->gl_pathc > 10) {
al.append(" ... ")
.append(std::to_string(gl->gl_pathc - 10),
VC_STYLE.value(A_BOLD))
.append(lnav::roles::number(std::to_string(gl->gl_pathc - 10)))
.append(" files not shown ...");
}
lnav_data.ld_preview_status_source.get_description()

@ -515,6 +515,10 @@ static const struct json_path_container theme_styles_handlers = {
.with_description("Styling for success messages")
.for_child(&lnav_theme::lt_style_ok)
.with_children(style_config_handlers),
yajlpp::property_handler("info")
.with_description("Styling for informational messages")
.for_child(&lnav_theme::lt_style_info)
.with_children(style_config_handlers),
yajlpp::property_handler("warning")
.with_description("Styling for warning messages")
.for_child(&lnav_theme::lt_style_warning)

@ -144,6 +144,7 @@ to_json(yajlpp_gen& gen, const attr_line_t& al)
},
[&](const intern_string_t& str) { elem_map.gen(str); },
[&](const std::string& str) { elem_map.gen(str); },
[&](const text_attrs& ta) { elem_map.gen(""); },
[&](const std::shared_ptr<logfile>& lf) {
elem_map.gen("");
},

@ -123,8 +123,8 @@ logline_value::logline_value(logline_value_meta lvm,
case value_kind_t::VALUE_W3C_QUOTED:
case value_kind_t::VALUE_TIMESTAMP:
require(origin.lr_end != -1);
this->lv_frag = string_fragment{
sbr.get_data(), origin.lr_start, origin.lr_end};
this->lv_frag = string_fragment::from_byte_range(
sbr.get_data(), origin.lr_start, origin.lr_end);
break;
case value_kind_t::VALUE_NULL:
@ -555,11 +555,9 @@ json_array_end(void* ctx)
jlu->jlu_format->jlf_line_values.lvv_values.emplace_back(
jlu->jlu_format->get_value_meta(field_name,
value_kind_t::VALUE_JSON),
string_fragment{
jlu->jlu_shared_buffer.get_data(),
(int) jlu->jlu_sub_start,
(int) sub_end,
});
string_fragment::from_byte_range(jlu->jlu_shared_buffer.get_data(),
jlu->jlu_sub_start,
sub_end));
}
return 1;
@ -1324,11 +1322,10 @@ rewrite_json_field(yajlpp_parse_context* ypc,
jlu->jlu_format->jlf_line_values.lvv_values.emplace_back(
jlu->jlu_format->get_value_meta(body_name,
value_kind_t::VALUE_TEXT),
string_fragment{
string_fragment::from_byte_range(
jlu->jlu_shared_buffer.get_data(),
str_offset,
str_offset + (int) len,
});
str_offset + len));
}
if (!ypc->is_level(1) && !jlu->jlu_format->has_value_def(field_name)) {
return 1;
@ -1337,11 +1334,9 @@ rewrite_json_field(yajlpp_parse_context* ypc,
jlu->jlu_format->jlf_line_values.lvv_values.emplace_back(
jlu->jlu_format->get_value_meta(field_name,
value_kind_t::VALUE_TEXT),
string_fragment{
jlu->jlu_shared_buffer.get_data(),
str_offset,
str_offset + (int) len,
});
string_fragment::from_byte_range(jlu->jlu_shared_buffer.get_data(),
str_offset,
str_offset + len));
} else {
if (field_name == jlu->jlu_format->elf_body_field) {
jlu->jlu_format->jlf_line_values.lvv_values.emplace_back(
@ -2265,7 +2260,8 @@ external_log_format::build(std::vector<lnav::console::user_message>& errors)
const char* errptr;
auto fg = styling::color_unit::make_empty();
auto bg = styling::color_unit::make_empty();
int eoff, attrs = 0;
text_attrs attrs;
int eoff;
if (!hd.hd_color.pp_value.empty()) {
fg = styling::color_unit::from_str(hd.hd_color.pp_value)
@ -2305,14 +2301,14 @@ external_log_format::build(std::vector<lnav::console::user_message>& errors)
}
if (hd.hd_underline) {
attrs |= A_UNDERLINE;
attrs.ta_attrs |= A_UNDERLINE;
}
if (hd.hd_blink) {
attrs |= A_BLINK;
attrs.ta_attrs |= A_BLINK;
}
if (hd.hd_pattern != nullptr) {
pcre* code = pcre_compile(hd.hd_pattern->get_pattern().c_str(),
auto* code = pcre_compile(hd.hd_pattern->get_pattern().c_str(),
PCRE_CASELESS | PCRE_UTF8,
&errptr,
&eoff,

@ -351,7 +351,7 @@ struct separated_string {
string_fragment operator*()
{
const separated_string& ss = this->i_parent;
const auto& ss = this->i_parent;
int end;
if (this->i_next_pos < (ss.ss_str + ss.ss_len)) {
@ -359,7 +359,8 @@ struct separated_string {
} else {
end = this->i_next_pos - ss.ss_str;
}
return string_fragment(ss.ss_str, this->i_pos - ss.ss_str, end);
return string_fragment::from_byte_range(
ss.ss_str, this->i_pos - ss.ss_str, end);
}
bool operator==(const iterator& other) const
@ -1643,8 +1644,7 @@ public:
shared_buffer_ref& sbr,
scan_batch_context& sbc) override
{
auto p = logfmt::parser(
string_fragment{sbr.get_data(), 0, (int) sbr.length()});
auto p = logfmt::parser(sbr.to_string_fragment());
scan_result_t retval = scan_result_t::SCAN_NO_MATCH;
bool done = false;
logfmt_pair_handler lph(this->lf_date_time);
@ -1729,8 +1729,7 @@ public:
static const auto FIELDS_NAME = intern_string::lookup("fields");
auto& sbr = values.lvv_sbr;
auto p = logfmt::parser(
string_fragment{sbr.get_data(), 0, (int) sbr.length()});
auto p = logfmt::parser(sbr.to_string_fragment());
bool done = false;
while (!done) {

@ -70,8 +70,8 @@ log_search_table::get_columns_int(std::vector<vtab_column>& cols) const
std::string colname;
int sqlite_type = SQLITE3_TEXT;
colname = cn.add_column(
string_fragment{this->lst_regex.name_for_capture(lpc)})
colname = cn.add_column(string_fragment::from_c_str(
this->lst_regex.name_for_capture(lpc)))
.to_string();
if (this->lst_regex.captures().size()
== (size_t) this->lst_regex.get_capture_count())

@ -37,6 +37,7 @@
#include "logfile_sub_source.hh"
#include "sql_util.hh"
#include "vtab_module.hh"
#include "vtab_module_json.hh"
#include "yajlpp/json_op.hh"
#include "yajlpp/yajlpp_def.hh"
@ -752,11 +753,7 @@ vt_column(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int col)
}
}
string_fragment sf = gen.to_string_fragment();
sqlite3_result_text(
ctx, sf.data(), sf.length(), SQLITE_TRANSIENT);
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
to_sqlite(ctx, json_string(gen));
}
break;
}
@ -930,8 +927,7 @@ vt_column(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int col)
line_hasher.update(sbr.get_data(), sbr.length())
.update(cl)
.to_string(outbuf);
auto tab = text_auto_buffer{std::move(outbuf)};
to_sqlite(ctx, tab);
to_sqlite(ctx, text_auto_buffer{std::move(outbuf)});
}
break;
}
@ -2046,6 +2042,9 @@ progress_callback(void* ptr)
if (log_vtab_data.lvd_progress != nullptr) {
retval = log_vtab_data.lvd_progress(log_cursor_latest);
}
if (!log_vtab_data.lvd_looping) {
retval = 1;
}
return retval;
}

@ -268,6 +268,7 @@ using sql_progress_callback_t = int (*)(const log_cursor&);
using sql_progress_finished_callback_t = void (*)();
struct _log_vtab_data {
bool lvd_looping{true};
sql_progress_callback_t lvd_progress;
sql_progress_finished_callback_t lvd_finished;
source_location lvd_location;
@ -283,6 +284,7 @@ public:
source_location loc,
const attr_line_t& content)
{
log_vtab_data.lvd_looping = true;
log_vtab_data.lvd_progress = cb;
log_vtab_data.lvd_finished = fcb;
log_vtab_data.lvd_location = loc;
@ -294,6 +296,7 @@ public:
if (log_vtab_data.lvd_finished) {
log_vtab_data.lvd_finished();
}
log_vtab_data.lvd_looping = true;
log_vtab_data.lvd_progress = nullptr;
log_vtab_data.lvd_finished = nullptr;
log_vtab_data.lvd_location = source_location{};

@ -962,3 +962,31 @@ logfile::line_for_offset(file_off_t off) const
return nonstd::make_optional(iter);
}
void
logfile::dump_stats()
{
const auto buf_stats = this->lf_line_buffer.consume_stats();
if (buf_stats.empty()) {
return;
}
log_info("line buffer stats for file: %s", this->lf_filename.c_str());
log_info(" file_size=%lld", this->lf_line_buffer.get_file_size());
log_info(" buffer_size=%ld", this->lf_line_buffer.get_buffer_size());
log_info(" read_hist=[%4lu %4lu %4lu %4lu %4lu %4lu %4lu %4lu %4lu %4lu]",
buf_stats.s_hist[0],
buf_stats.s_hist[1],
buf_stats.s_hist[2],
buf_stats.s_hist[3],
buf_stats.s_hist[4],
buf_stats.s_hist[5],
buf_stats.s_hist[6],
buf_stats.s_hist[7],
buf_stats.s_hist[8],
buf_stats.s_hist[9]);
log_info(" decompressions=%lu", buf_stats.s_decompressions);
log_info(" preads=%lu", buf_stats.s_preads);
log_info(" requested_preloads=%lu", buf_stats.s_requested_preloads);
log_info(" used_preloads=%lu", buf_stats.s_used_preloads);
}

@ -373,6 +373,8 @@ public:
void quiesce() { this->lf_line_buffer.quiesce(); }
void dump_stats();
protected:
/**
* Process a line from the file.

@ -353,7 +353,7 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
logline* next_line = nullptr;
struct line_range lr;
int time_offset_end = 0;
int attrs = 0;
text_attrs attrs;
value_out = this->lss_token_attrs;
@ -365,7 +365,7 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
&& (day_num(next_line->get_time())
> day_num(this->lss_token_line->get_time())))
{
attrs |= A_UNDERLINE;
attrs.ta_attrs |= A_UNDERLINE;
}
const auto& line_values = this->lss_token_values;
@ -458,7 +458,8 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
vis_line_t(row))) {
lr.lr_start = 0;
lr.lr_end = 1;
value_out.emplace_back(lr, VC_STYLE.value(A_REVERSE));
value_out.emplace_back(lr,
VC_STYLE.value(text_attrs{A_REVERSE}));
}
}
}
@ -586,7 +587,7 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
} else {
color = COLOR_RED;
value_out.emplace_back(line_range{0, 1},
VC_STYLE.value(A_BLINK));
VC_STYLE.value(text_attrs{A_BLINK}));
}
}
value_out.emplace_back(line_range{0, 1},

@ -187,11 +187,8 @@ md2attr_line::leave_block(const md4cpp::event_handler::block& bl)
this->ml_code_depth -= 1;
auto lang_sf = string_fragment{
code_detail->lang.text,
0,
(int) code_detail->lang.size,
};
auto lang_sf = string_fragment::from_bytes(code_detail->lang.text,
code_detail->lang.size);
if (lang_sf == "lnav") {
readline_lnav_highlighter(block_text, block_text.length());
}
@ -398,7 +395,7 @@ md2attr_line::leave_span(const md4cpp::event_handler::span& sp)
#if defined(A_ITALIC)
last_block.with_attr({
lr,
VC_STYLE.value(A_ITALIC),
VC_STYLE.value(text_attrs{(int32_t) A_ITALIC}),
});
#endif
} else if (sp.is<span_strong>()) {
@ -408,7 +405,7 @@ md2attr_line::leave_span(const md4cpp::event_handler::span& sp)
};
last_block.with_attr({
lr,
VC_STYLE.value(A_BOLD),
VC_STYLE.value(text_attrs{A_BOLD}),
});
} else if (sp.is<MD_SPAN_A_DETAIL*>()) {
auto* a_detail = sp.get<MD_SPAN_A_DETAIL*>();
@ -464,12 +461,7 @@ md2attr_line::text(MD_TEXTTYPE tt, const string_fragment& sf)
pcre_context_static<30> pc;
while (REPL_RE.match(pc, pi)) {
auto prev = string_fragment{
sf.sf_string,
(int) pi.pi_offset,
pc.all()->c_begin,
};
auto prev = pi.get_up_to(pc.all());
last_block.append(prev);
auto matched = pi.get_string_fragment(pc.all());
@ -489,11 +481,7 @@ md2attr_line::text(MD_TEXTTYPE tt, const string_fragment& sf)
}
}
this->ml_blocks.back().append(string_fragment{
sf.sf_string,
(int) pi.pi_offset,
sf.sf_end,
});
this->ml_blocks.back().append(sf.substr(pi.pi_offset));
break;
}
}
@ -514,9 +502,9 @@ md2attr_line::append_url_footnote(std::string href_str)
(int) this->ml_span_starts.back(),
(int) last_block.length(),
},
VC_STYLE.value(A_UNDERLINE),
VC_STYLE.value(text_attrs{A_UNDERLINE}),
});
if (this->ml_source_path && href_str.find(":") == std::string::npos) {
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);

@ -29,6 +29,7 @@
#include "md4cpp.hh"
#include "base/is_utf8.hh"
#include "base/lnav_log.hh"
#include "emojis-json.h"
#include "xml-entities-json.h"
@ -263,6 +264,20 @@ namespace details {
Result<void, std::string>
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};

@ -237,11 +237,14 @@ public:
string_fragment get_string_fragment(pcre_context::const_iterator iter) const
{
return string_fragment{
this->pi_string,
iter->c_begin,
iter->c_end,
};
return string_fragment::from_byte_range(
this->pi_string, iter->c_begin, iter->c_end);
}
string_fragment get_up_to(pcre_context::const_iterator iter) const
{
return string_fragment::from_byte_range(
this->pi_string, this->pi_offset, iter->c_begin);
}
nonstd::optional<std::string> get_substr_opt(

@ -143,7 +143,8 @@ plain_text_source::text_attrs_for_line(textview_curses& tc,
if (this->tds_reverse_selection && tc.is_selectable()
&& tc.get_selection() == line)
{
value_out.emplace_back(line_range{0, -1}, VC_STYLE.value(A_REVERSE));
value_out.emplace_back(line_range{0, -1},
VC_STYLE.value(text_attrs{A_REVERSE}));
}
}

@ -508,6 +508,7 @@ rl_search_internal(readline_curses* rc, ln_mode_t mode, bool complete = false)
case ln_mode_t::EXEC:
case ln_mode_t::USER:
case ln_mode_t::SPECTRO_DETAILS:
case ln_mode_t::BUSY:
return;
}
@ -603,6 +604,7 @@ rl_callback_int(readline_curses* rc, bool is_alt)
case ln_mode_t::FILTER:
case ln_mode_t::FILES:
case ln_mode_t::SPECTRO_DETAILS:
case ln_mode_t::BUSY:
require(0);
break;
@ -830,7 +832,7 @@ rl_display_matches(readline_curses* rc)
add_nl = false;
}
if (match == current_match) {
al.append(match, VC_STYLE.value(A_REVERSE));
al.append(match, VC_STYLE.value(text_attrs{A_REVERSE}));
} else {
al.append(match);
}

@ -1385,7 +1385,11 @@ readline_curses::do_update()
view_colors& vc = view_colors::singleton();
wmove(this->vc_window, this->get_actual_y(), this->vc_left);
wattron(this->vc_window, vc.attrs_for_role(role_t::VCR_TEXT));
auto attrs = vc.attrs_for_role(role_t::VCR_TEXT);
wattr_set(this->vc_window,
attrs.ta_attrs,
vc.ensure_color_pair(attrs.ta_fg_color, attrs.ta_bg_color),
nullptr);
whline(this->vc_window, ' ', this->vc_width);
if (time(nullptr) > this->rc_value_expiration) {

@ -82,7 +82,7 @@ find_matching_bracket(
} else if (line[lpc] == left && is_bracket(line, lpc, is_lit)) {
if (depth == 0) {
alb.overlay_attr_for_char(
lpc, VC_STYLE.value(A_BOLD | A_REVERSE));
lpc, VC_STYLE.value(text_attrs{A_BOLD | A_REVERSE}));
alb.overlay_attr_for_char(lpc,
VC_ROLE.value(role_t::VCR_OK));
break;
@ -99,7 +99,7 @@ find_matching_bracket(
} else if (line[lpc] == right && is_bracket(line, lpc, is_lit)) {
if (depth == 0) {
alb.overlay_attr_for_char(
lpc, VC_STYLE.value(A_BOLD | A_REVERSE));
lpc, VC_STYLE.value(text_attrs{A_BOLD | A_REVERSE}));
alb.overlay_attr_for_char(lpc,
VC_ROLE.value(role_t::VCR_OK));
break;
@ -124,7 +124,8 @@ find_matching_bracket(
depth -= 1;
} else {
auto lr = line_range(is_lit ? lpc - 1 : lpc, lpc + 1);
alb.overlay_attr(lr, VC_STYLE.value(A_BOLD | A_REVERSE));
alb.overlay_attr(
lr, VC_STYLE.value(text_attrs{A_BOLD | A_REVERSE}));
alb.overlay_attr(lr, VC_ROLE.value(role_t::VCR_ERROR));
}
}
@ -134,7 +135,7 @@ find_matching_bracket(
auto lr
= line_range(is_lit ? first_left.value() - 1 : first_left.value(),
first_left.value() + 1);
alb.overlay_attr(lr, VC_STYLE.value(A_BOLD | A_REVERSE));
alb.overlay_attr(lr, VC_STYLE.value(text_attrs{A_BOLD | A_REVERSE}));
alb.overlay_attr(lr, VC_ROLE.value(role_t::VCR_ERROR));
}
}
@ -189,7 +190,7 @@ readline_command_highlighter_int(attr_line_t& al, int x, line_range sub)
if (COLOR_PREFIXES.match(pc, pi)) {
pi.reset(&line[sub.lr_start], 0, sub.length());
if (COLOR_RE.match(pc, pi)) {
pcre_context::capture_t* cap = pc[0];
auto* cap = pc[0];
auto hash_color = pi.get_substr(cap);
styling::color_unit::from_str(hash_color)
@ -278,8 +279,8 @@ readline_sqlite_highlighter_int(attr_line_t& al, int x, line_range sub)
if (lr.length() > 1 && al.al_string[lr.lr_end - 1] == '\'') {
alb.overlay_attr(lr, VC_ROLE.value(role_t::VCR_STRING));
} else {
alb.overlay_attr_for_char(lr.lr_start,
VC_STYLE.value(A_REVERSE));
alb.overlay_attr_for_char(
lr.lr_start, VC_STYLE.value(text_attrs{A_REVERSE}));
alb.overlay_attr_for_char(lr.lr_start,
VC_ROLE.value(role_t::VCR_ERROR));
}
@ -317,7 +318,7 @@ readline_shlex_highlighter_int(attr_line_t& al, int x, line_range sub)
case shlex_token_t::ST_ERROR:
alb.overlay_attr(line_range(sub.lr_start + cap.c_begin,
sub.lr_start + cap.c_end),
VC_STYLE.value(A_REVERSE));
VC_STYLE.value(text_attrs{A_REVERSE}));
alb.overlay_attr(line_range(sub.lr_start + cap.c_begin,
sub.lr_start + cap.c_end),
VC_ROLE.value(role_t::VCR_ERROR));

@ -123,7 +123,7 @@ public:
string_fragment to_string_fragment() const
{
return string_fragment{this->sb_data, 0, (int) this->length()};
return string_fragment::from_bytes(this->sb_data, this->length());
}
using narrow_result = std::pair<char*, size_t>;

@ -309,8 +309,8 @@ spectrogram_source::list_value_for_overlay(const listview_curses& lv,
}
line.append(buf);
value_out.with_attr(
string_attr(line_range(0, -1), VC_STYLE.value(A_UNDERLINE)));
value_out.with_attr(string_attr(line_range(0, -1),
VC_STYLE.value(text_attrs{A_UNDERLINE})));
return true;
}

@ -693,7 +693,7 @@ annotate_sql_with_error(sqlite3* db, const char* sql, const char* tail)
} else {
tail = tail_lf;
}
retval.append(string_fragment{sql, 0, (int) (tail - sql)});
retval.append(string_fragment::from_bytes(sql, tail - sql));
} else {
retval.append(sql);
}

@ -63,9 +63,9 @@ status_field::do_cylon()
struct line_range lr(std::max(start, 0L), stop);
auto& vc = view_colors::singleton();
sa.emplace_back(lr,
VC_STYLE.value(vc.attrs_for_role(role_t::VCR_ACTIVE_STATUS)
| A_REVERSE));
auto attrs = vc.attrs_for_role(role_t::VCR_ACTIVE_STATUS);
attrs.ta_attrs |= A_REVERSE;
sa.emplace_back(lr, VC_STYLE.value(attrs));
this->sf_cylon_pos += 1;
}
@ -88,7 +88,7 @@ status_field::set_stitch_value(role_t left,
void
statusview_curses::do_update()
{
int top, attrs, field, field_count, left = 0, right;
int top, field, field_count, left = 0, right;
auto& vc = view_colors::singleton();
unsigned long width, height;
@ -101,15 +101,14 @@ statusview_curses::do_update()
top = this->sc_top < 0 ? height + this->sc_top : this->sc_top;
right = width;
attrs = vc.attrs_for_role(this->sc_enabled
? role_t::VCR_STATUS
: role_t::VCR_INACTIVE_STATUS);
auto attrs = vc.attrs_for_role(
this->sc_enabled ? role_t::VCR_STATUS : role_t::VCR_INACTIVE_STATUS);
wattron(this->sc_window, attrs);
auto pair = vc.ensure_color_pair(attrs.ta_fg_color, attrs.ta_bg_color);
wattr_set(this->sc_window, attrs.ta_attrs, pair, nullptr);
wmove(this->sc_window, top, 0);
wclrtoeol(this->sc_window);
whline(this->sc_window, ' ', width);
wattroff(this->sc_window, attrs);
if (this->sc_source != nullptr) {
field_count = this->sc_source->statusview_fields();
@ -125,8 +124,11 @@ statusview_curses::do_update()
if (!this->sc_enabled) {
for (auto& sa : val.get_attrs()) {
if (sa.sa_type == &VC_STYLE) {
sa.sa_value = sa.sa_value.get<int64_t>()
& ~(A_REVERSE | A_COLOR);
auto sa_attrs = sa.sa_value.get<text_attrs>();
sa_attrs.ta_attrs &= ~(A_REVERSE | A_COLOR);
sa_attrs.ta_fg_color = nonstd::nullopt;
sa_attrs.ta_bg_color = nonstd::nullopt;
sa.sa_value = sa_attrs;
} else if (sa.sa_type == &VC_ROLE) {
if (sa.sa_value.get<role_t>()
== role_t::VCR_ALERT_STATUS) {

@ -59,10 +59,11 @@ find_re(string_fragment re)
c.re2 = std::make_shared<pcrepp>(re.to_string());
auto pair = cache.insert(
std::make_pair(string_fragment{c.re2->get_pattern()}, c));
std::make_pair(string_fragment::from_str(c.re2->get_pattern()), c));
for (int lpc = 0; lpc < c.re2->get_capture_count(); lpc++) {
c.cn->add_column(string_fragment{c.re2->name_for_capture(lpc)});
c.cn->add_column(
string_fragment::from_c_str(c.re2->name_for_capture(lpc)));
}
iter = pair.first;

@ -168,6 +168,7 @@ struct lnav_theme {
style_config lt_style_text;
style_config lt_style_alt_text;
style_config lt_style_ok;
style_config lt_style_info;
style_config lt_style_error;
style_config lt_style_warning;
style_config lt_style_popup;

@ -34,6 +34,8 @@
#include "config.h"
#include "md2attr_line.hh"
using namespace lnav::roles::literals;
size_t
textfile_sub_source::text_line_count()
{
@ -514,20 +516,24 @@ textfile_sub_source::rescan_files(
mdal.with_source_path(lf->get_actual_path());
auto parse_res = md4cpp::parse(content_sf, mdal);
auto& rf = this->tss_rendered_files[lf->get_filename()];
rf.rf_mtime = st.st_mtime;
rf.rf_file_size = st.st_size;
rf.rf_text_source = std::make_unique<plain_text_source>();
rf.rf_text_source->register_view(this->tss_view);
if (parse_res.isOk()) {
auto& rf = this->tss_rendered_files[lf->get_filename()];
rf.rf_mtime = st.st_mtime;
rf.rf_file_size = st.st_size;
rf.rf_text_source
= std::make_unique<plain_text_source>();
rf.rf_text_source->register_view(this->tss_view);
rf.rf_text_source->replace_with(parse_res.unwrap());
log_info("successfully rendered markdown file: %s",
lf->get_filename().c_str());
} else {
log_error("unable to parse markdown file: %s -- %s",
lf->get_filename().c_str(),
parse_res.unwrapErr().c_str());
auto view_content
= lnav::console::user_message::error(
"unable to parse markdown file")
.with_reason(parse_res.unwrapErr())
.to_attr_line();
view_content.append("\n").append(
attr_line_t::from_ansi_str(content.c_str()));
rf.rf_text_source->replace_with(view_content);
}
} else {
log_error("unable to read markdown file: %s -- %s",

@ -197,7 +197,7 @@ textview_curses::reload_config(error_reporter& reporter)
const auto& sc = hl_pair.second.hc_style;
std::string fg1, bg1, fg_color, bg_color, errmsg;
bool invalid = false;
int attrs = 0;
text_attrs attrs;
fg1 = sc.sc_color;
bg1 = sc.sc_background_color;
@ -229,15 +229,15 @@ textview_curses::reload_config(error_reporter& reporter)
}
if (sc.sc_bold) {
attrs |= A_BOLD;
attrs.ta_attrs |= A_BOLD;
}
if (sc.sc_underline) {
attrs |= A_UNDERLINE;
attrs.ta_attrs |= A_UNDERLINE;
}
this->tc_highlights[{highlight_source_t::THEME, hl_pair.first}]
= highlighter(code)
.with_pattern(hl_pair.second.hc_regex)
.with_attrs(attrs != 0 ? attrs : -1)
.with_attrs(attrs)
.with_color(fg, bg);
}
}
@ -555,7 +555,7 @@ textview_curses::textview_value_for_row(vis_line_t row, attr_line_t& value_out)
|| binary_search(user_expr_marks.begin(), user_expr_marks.end(), row))
{
sa.emplace_back(line_range{orig_line.lr_start, -1},
VC_STYLE.value(A_REVERSE));
VC_STYLE.value(text_attrs{A_REVERSE}));
}
}
@ -656,8 +656,7 @@ textview_curses::horiz_shift(vis_line_t start,
int off_start,
std::pair<int, int>& range_out)
{
highlighter& hl
= this->tc_highlights[{highlight_source_t::PREVIEW, "search"}];
auto& hl = this->tc_highlights[{highlight_source_t::PREVIEW, "search"}];
int prev_hit = -1, next_hit = INT_MAX;
for (; start < end; ++start) {

@ -185,7 +185,6 @@
},
"hotkey": {
"color": "Purple",
"background-color": "Silver",
"underline": true,
"bold": true
}

@ -115,7 +115,6 @@
},
"hotkey": {
"color": "#fff",
"background-color": "#353535",
"underline": true
},
"text": {

@ -31,6 +31,10 @@
"color": "$green",
"bold": true
},
"info": {
"color": "$magenta",
"bold": true
},
"error": {
"color": "$red",
"bold": true
@ -215,7 +219,6 @@
},
"hotkey": {
"color": "#fff",
"background-color": "#353535",
"underline": true
},
"text": {

@ -183,7 +183,6 @@
},
"hotkey": {
"color": "#2d5a80",
"background-color": "#162d40",
"bold": true,
"underline": true
},

File diff suppressed because it is too large Load Diff

@ -187,6 +187,11 @@ public:
/** @return A reference to the singleton. */
static view_colors& singleton();
view_colors(const view_colors&) = delete;
view_colors(view_colors&&) = delete;
view_colors& operator=(const view_colors&) = delete;
view_colors& operator=(view_colors&&) = delete;
/**
* Performs curses-specific initialization. The other methods can be
* called before this method, but the returned attributes cannot be used
@ -201,21 +206,21 @@ public:
* @param role The role to retrieve character attributes for.
* @return The attributes to use for the given role.
*/
attr_t attrs_for_role(role_t role, bool selected = false) const
text_attrs attrs_for_role(role_t role, bool selected = false) const
{
if (role == role_t::VCR_NONE) {
return 0;
return {};
}
require(role > role_t::VCR_NONE);
require(role < role_t::VCR__MAX);
return selected
? this->vc_role_colors[lnav::enums::to_underlying(role)].second
: this->vc_role_colors[lnav::enums::to_underlying(role)].first;
? this->vc_role_attrs[lnav::enums::to_underlying(role)].second
: this->vc_role_attrs[lnav::enums::to_underlying(role)].first;
}
attr_t reverse_attrs_for_role(role_t role) const
text_attrs reverse_attrs_for_role(role_t role) const
{
require(role > role_t::VCR_NONE);
require(role < role_t::VCR__MAX);
@ -223,56 +228,45 @@ public:
return this->vc_role_reverse_colors[lnav::enums::to_underlying(role)];
}
int color_for_ident(const char* str, size_t len) const;
nonstd::optional<short> color_for_ident(const char* str, size_t len) const;
int color_for_ident(const string_fragment& sf) const
nonstd::optional<short> color_for_ident(const string_fragment& sf) const
{
return this->color_for_ident(sf.data(), sf.length());
}
attr_t attrs_for_ident(const char* str, size_t len);
text_attrs attrs_for_ident(const char* str, size_t len) const;
attr_t attrs_for_ident(intern_string_t str)
text_attrs attrs_for_ident(intern_string_t str) const
{
return this->attrs_for_ident(str.get(), str.size());
}
attr_t attrs_for_ident(const std::string& str)
text_attrs attrs_for_ident(const std::string& str) const
{
return this->attrs_for_ident(str.c_str(), str.length());
}
int ensure_color_pair(short fg, short bg);
int ensure_color_pair(nonstd::optional<short> fg,
nonstd::optional<short> bg);
int ensure_color_pair(const styling::color_unit& fg,
const styling::color_unit& bg);
static constexpr short MATCH_COLOR_DEFAULT = -1;
static constexpr short MATCH_COLOR_SEMANTIC = -10;
short match_color(const styling::color_unit& color) const;
static inline int ansi_color_pair_index(int fg, int bg)
{
return VC_ANSI_START + ((fg * 8) + bg);
}
nonstd::optional<short> match_color(const styling::color_unit& color) const;
static inline attr_t ansi_color_pair(int fg, int bg)
{
return COLOR_PAIR(ansi_color_pair_index(fg, bg));
}
static const int VC_ANSI_START = 0;
static const int VC_ANSI_END = VC_ANSI_START + (8 * 8);
std::pair<attr_t, attr_t> to_attrs(
int& pair_base,
std::pair<text_attrs, text_attrs> to_attrs(
const lnav_theme& lt,
const style_config& sc,
const style_config& fallback_sc,
lnav_config_listener::error_reporter& reporter);
std::pair<attr_t, attr_t> vc_level_attrs[LEVEL__MAX];
std::pair<text_attrs, text_attrs> vc_level_attrs[LEVEL__MAX];
short ansi_to_theme_color(short ansi_fg) const
{
@ -291,17 +285,16 @@ private:
/** Private constructor that initializes the member fields. */
view_colors();
view_colors(const view_colors&) = delete;
struct dyn_pair {
int dp_color_pair;
};
/** Map of role IDs to attribute values. */
std::pair<attr_t, attr_t>
vc_role_colors[lnav::enums::to_underlying(role_t::VCR__MAX)];
std::pair<text_attrs, text_attrs>
vc_role_attrs[lnav::enums::to_underlying(role_t::VCR__MAX)];
/** Map of role IDs to reverse-video attribute values. */
attr_t vc_role_reverse_colors[lnav::enums::to_underlying(role_t::VCR__MAX)];
text_attrs
vc_role_reverse_colors[lnav::enums::to_underlying(role_t::VCR__MAX)];
short vc_ansi_to_theme[8];
short vc_highlight_colors[HI_COLOR_COUNT];
int vc_color_pair_end{0};
@ -331,12 +324,11 @@ struct mouse_event {
int y = -1)
: me_button(button), me_state(state), me_x(x), me_y(y)
{
memset(&this->me_time, 0, sizeof(this->me_time));
}
mouse_button_t me_button;
mouse_button_state_t me_state;
struct timeval me_time;
struct timeval me_time {};
int me_x;
int me_y;
};

@ -71,6 +71,7 @@ enum class ln_mode_t : int {
SQL,
EXEC,
USER,
BUSY,
};
extern const char* lnav_view_strings[LNV__MAX + 1];

@ -327,8 +327,7 @@ CREATE TABLE lnav_views (
crumb.c_search_placeholder,
std::move(poss));
}
auto ret = top_line_meta_handlers.to_json_string(tlm);
to_sqlite(ctx, ret);
to_sqlite(ctx, top_line_meta_handlers.to_json_string(tlm));
} else {
sqlite3_result_null(ctx);
}

@ -159,11 +159,9 @@ template<>
struct from_sqlite<string_fragment> {
inline string_fragment operator()(int argc, sqlite3_value** val, int argi)
{
return string_fragment{
(const unsigned char*) sqlite3_value_blob(val[argi]),
0,
sqlite3_value_bytes(val[argi]),
};
return string_fragment::from_bytes(
(const char*) sqlite3_value_blob(val[argi]),
sqlite3_value_bytes(val[argi]));
}
};
@ -237,14 +235,14 @@ to_sqlite(sqlite3_context* ctx, const char* str)
}
inline void
to_sqlite(sqlite3_context* ctx, text_auto_buffer& buf)
to_sqlite(sqlite3_context* ctx, text_auto_buffer buf)
{
auto pair = buf.inner.release();
sqlite3_result_text(ctx, pair.first, pair.second, free);
}
inline void
to_sqlite(sqlite3_context* ctx, blob_auto_buffer& buf)
to_sqlite(sqlite3_context* ctx, blob_auto_buffer buf)
{
auto pair = buf.inner.release();
sqlite3_result_blob(ctx, pair.first, pair.second, free);
@ -306,10 +304,10 @@ to_sqlite(sqlite3_context* ctx, nonstd::optional<T>& val)
template<typename T>
inline void
to_sqlite(sqlite3_context* ctx, const nonstd::optional<T>& val)
to_sqlite(sqlite3_context* ctx, nonstd::optional<T> val)
{
if (val.has_value()) {
to_sqlite(ctx, val.value());
to_sqlite(ctx, std::move(val.value()));
} else {
sqlite3_result_null(ctx);
}
@ -321,7 +319,7 @@ struct ToSqliteVisitor {
template<typename T>
void operator()(T&& t) const
{
to_sqlite(this->tsv_context, std::forward<T>(t));
to_sqlite(this->tsv_context, std::move(t));
}
sqlite3_context* tsv_context;
@ -329,7 +327,7 @@ struct ToSqliteVisitor {
template<typename... Types>
void
to_sqlite(sqlite3_context* ctx, mapbox::util::variant<Types...>& val)
to_sqlite(sqlite3_context* ctx, mapbox::util::variant<Types...>&& val)
{
ToSqliteVisitor visitor(ctx);
@ -402,7 +400,7 @@ struct sqlite_func_adapter<Return (*)(Args...), f> {
try {
Return retval = f(from_sqlite<Args>()(argc, argv, Idx)...);
to_sqlite(context, retval);
to_sqlite(context, std::move(retval));
} catch (from_sqlite_conversion_error& e) {
char buffer[64];

@ -40,7 +40,7 @@ struct flattened_json_string : json_string {
};
inline void
to_sqlite(sqlite3_context* ctx, flattened_json_string& val)
to_sqlite(sqlite3_context* ctx, flattened_json_string val)
{
sqlite3_result_text(
ctx, (const char*) val.js_content.release(), val.js_len, free);
@ -48,7 +48,7 @@ to_sqlite(sqlite3_context* ctx, flattened_json_string& val)
}
inline void
to_sqlite(sqlite3_context* ctx, json_string& val)
to_sqlite(sqlite3_context* ctx, json_string val)
{
sqlite3_result_text(
ctx, (const char*) val.js_content.release(), val.js_len, free);

@ -1294,8 +1294,8 @@ yajlpp_parse_context::get_snippet() const
if (line_end) {
text_len_remaining = (line_end - line_start);
}
content.append(string_fragment{
(const char*) line_start, 0, (int) text_len_remaining});
content.append(
string_fragment::from_bytes(line_start, text_len_remaining));
}
}

@ -460,6 +460,7 @@ DISTCLEANFILES = \
test_pretty_in.* \
tmp \
unreadable.log \
UTF-8-test.md \
empty \
scripts-empty

@ -69,44 +69,43 @@ main(int argc, char* argv[])
al.clear()
.with_string("\tLeading tab")
.with_attr(string_attr(line_range(0, 1),
VC_STYLE.value(A_REVERSE)));
VC_STYLE.value(text_attrs{A_REVERSE})));
view_curses::mvwattrline(win, y++, 0, al, lr);
al.clear()
.with_string("Tab\twith text")
.with_attr(string_attr(line_range(1, 4),
VC_STYLE.value(A_REVERSE)));
VC_STYLE.value(text_attrs{A_REVERSE})));
view_curses::mvwattrline(win, y++, 0, al, lr);
al.clear()
.with_string("Tab\twith text #2")
.with_attr(string_attr(line_range(3, 4),
VC_STYLE.value(A_REVERSE)));
VC_STYLE.value(text_attrs{A_REVERSE})));
view_curses::mvwattrline(win, y++, 0, al, lr);
al.clear()
.with_string("Two\ttabs\twith text")
.with_attr(string_attr(line_range(4, 6),
VC_STYLE.value(A_REVERSE)))
VC_STYLE.value(text_attrs{A_REVERSE})))
.with_attr(string_attr(line_range(9, 13),
VC_STYLE.value(A_REVERSE)));
VC_STYLE.value(text_attrs{A_REVERSE})));
view_curses::mvwattrline(win, y++, 0, al, lr);
al.clear()
.with_string("Text with mixed attributes.")
.with_attr(string_attr(
line_range(5, 9),
VC_STYLE.value(
view_colors::ansi_color_pair(COLOR_RED, COLOR_BLACK))))
VC_STYLE.value(text_attrs{0, COLOR_RED, COLOR_BLACK})))
.with_attr(string_attr(line_range(7, 12),
VC_STYLE.value(A_REVERSE)));
VC_STYLE.value(text_attrs{A_REVERSE})));
view_curses::mvwattrline(win, y++, 0, al, lr);
const char* text = u8"Text with unicode ▶ characters";
int offset = strstr(text, "char") - text;
al.clear().with_string(text).with_attr(
string_attr(line_range(offset, offset + 4),
VC_STYLE.value(A_REVERSE)));
VC_STYLE.value(text_attrs{A_REVERSE})));
view_curses::mvwattrline(win, y++, 0, al, lr);
wmove(win, y, 0);

@ -40,11 +40,11 @@ public:
void do_update() override
{
view_colors& vc = view_colors::singleton();
auto& vc = view_colors::singleton();
int lpc;
for (lpc = 0; lpc < 16; lpc++) {
int attrs;
text_attrs attrs;
char label[64];
attr_line_t al;
line_range lr;
@ -64,9 +64,9 @@ public:
al = "before <123> after";
al.with_attr({line_range{8, 11},
VC_STYLE.value((int64_t) view_colors::ansi_color_pair(
COLOR_CYAN, COLOR_BLACK))});
al.with_attr({line_range{8, 11}, VC_STYLE.value(A_REVERSE)});
VC_STYLE.value(text_attrs{0, COLOR_CYAN, COLOR_BLACK})});
al.with_attr(
{line_range{8, 11}, VC_STYLE.value(text_attrs{A_REVERSE})});
test_colors::mvwattrline(this->tc_window, lpc, 0, al, lr);
};

@ -926,6 +926,8 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_text_file.sh_5b51b55dff7332c5bee2c9b797c401c5614d574a.out \
$(srcdir)/%reldir%/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.err \
$(srcdir)/%reldir%/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.out \
$(srcdir)/%reldir%/test_text_file.sh_ac872aadda29b9a824361a2c711d62ec1c75d40f.err \
$(srcdir)/%reldir%/test_text_file.sh_ac872aadda29b9a824361a2c711d62ec1c75d40f.out \
$(srcdir)/%reldir%/test_text_file.sh_c2a346ca1da2da4346f1d310212e166767993ce9.err \
$(srcdir)/%reldir%/test_text_file.sh_c2a346ca1da2da4346f1d310212e166767993ce9.out \
$()

@ -1,4 +1,4 @@
 Thu Nov 03 09:20:00  1 normal 2 errors 0 warnings  0 marks
 Thu Nov 03 09:20:00  1 normal 2 errors 0 warnings  0 marks
 Thu Nov 03 09:45:00  1 normal 0 errors 0 warnings 0 marks
 Fri Feb 03 09:20:00  0 normal 1 errors 0 warnings 0 marks
 Fri Feb 03 09:20:00  0 normal 1 errors 0 warnings 0 marks
 Wed Jan 03 09:20:00  1 normal 0 errors 0 warnings 0 marks

@ -1,2 +1,2 @@
 Sat Nov 03 09:20:00 1 normal 2 errors  0 warnings  1 marks
 Sat Nov 03 09:20:00 1 normal 2 errors  0 warnings  1 marks
 Sat Nov 03 09:45:00 1 normal 0 errors 0 warnings 0 marks

@ -1 +1 @@
 Sat Nov 03 00:00:00 2 normal 2 errors 0 warnings 0 marks
 Sat Nov 03 00:00:00 2 normal 2 errors 0 warnings 0 marks

@ -1 +1 @@
 Sat Nov 03 08:00:00 2 normal 2 errors 0 warnings 0 marks
 Sat Nov 03 08:00:00 2 normal 2 errors 0 warnings 0 marks

@ -1 +1 @@
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to readlink(path) failed","attrs":[{"start":8,"end":16,"type":"role","value":45},{"start":17,"end":21,"type":"role","value":44},{"start":8,"end":22,"type":"role","value":58}]},"reason":{"str":"unable to stat path: non-existent-link -- No such file or directory","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to readlink(path) failed","attrs":[{"start":8,"end":16,"type":"role","value":46},{"start":17,"end":21,"type":"role","value":45},{"start":8,"end":22,"type":"role","value":59}]},"reason":{"str":"unable to stat path: non-existent-link -- No such file or directory","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}

@ -1 +1 @@
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to realpath(path) failed","attrs":[{"start":8,"end":16,"type":"role","value":45},{"start":17,"end":21,"type":"role","value":44},{"start":8,"end":22,"type":"role","value":58}]},"reason":{"str":"Could not get real path for non-existent-path -- No such file or directory","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to realpath(path) failed","attrs":[{"start":8,"end":16,"type":"role","value":46},{"start":17,"end":21,"type":"role","value":45},{"start":8,"end":22,"type":"role","value":59}]},"reason":{"str":"Could not get real path for non-existent-path -- No such file or directory","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}

@ -1 +1 @@
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to json_contains(json, value) failed","attrs":[{"start":8,"end":21,"type":"role","value":45},{"start":22,"end":26,"type":"role","value":44},{"start":28,"end":33,"type":"role","value":44},{"start":8,"end":34,"type":"role","value":58}]},"reason":{"str":"parse error: premature EOF\n [\"hi\", \"bye\", \"solong]\n (right here) ------^","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to json_contains(json, value) failed","attrs":[{"start":8,"end":21,"type":"role","value":46},{"start":22,"end":26,"type":"role","value":45},{"start":28,"end":33,"type":"role","value":45},{"start":8,"end":34,"type":"role","value":59}]},"reason":{"str":"parse error: premature EOF\n [\"hi\", \"bye\", \"solong]\n (right here) ------^","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}

@ -1 +1 @@
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to regexp_match(re, str) failed","attrs":[{"start":8,"end":20,"type":"role","value":45},{"start":21,"end":23,"type":"role","value":44},{"start":25,"end":28,"type":"role","value":44},{"start":8,"end":29,"type":"role","value":58}]},"reason":{"str":"regular expression does not have any captures","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to regexp_match(re, str) failed","attrs":[{"start":8,"end":20,"type":"role","value":46},{"start":21,"end":23,"type":"role","value":45},{"start":25,"end":28,"type":"role","value":45},{"start":8,"end":29,"type":"role","value":59}]},"reason":{"str":"regular expression does not have any captures","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}

@ -1 +1 @@
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to timeslice(time, slice) failed","attrs":[{"start":8,"end":17,"type":"role","value":45},{"start":18,"end":22,"type":"role","value":44},{"start":24,"end":29,"type":"role","value":44},{"start":8,"end":30,"type":"role","value":58}]},"reason":{"str":"unable to parse time slice value: blah -- Unrecognized input","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to timeslice(time, slice) failed","attrs":[{"start":8,"end":17,"type":"role","value":46},{"start":18,"end":22,"type":"role","value":45},{"start":24,"end":29,"type":"role","value":45},{"start":8,"end":30,"type":"role","value":59}]},"reason":{"str":"unable to parse time slice value: blah -- Unrecognized input","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}

@ -1 +1 @@
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to timeslice(time, slice) failed","attrs":[{"start":8,"end":17,"type":"role","value":45},{"start":18,"end":22,"type":"role","value":44},{"start":24,"end":29,"type":"role","value":44},{"start":8,"end":30,"type":"role","value":58}]},"reason":{"str":"no time slice value given","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to timeslice(time, slice) failed","attrs":[{"start":8,"end":17,"type":"role","value":46},{"start":18,"end":22,"type":"role","value":45},{"start":24,"end":29,"type":"role","value":45},{"start":8,"end":30,"type":"role","value":59}]},"reason":{"str":"no time slice value given","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}

@ -0,0 +1,74 @@
✘ error: unable to parse markdown file
reason: file has invalid UTF-8 at offset 4461: Expecting bytes in the following ranges: 00..7F C2..F4.
UTF-8 decoder capability and stress test
----------------------------------------
Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/> - 2015-08-28 - CC BY 4.0
This test file can help you examine, how your UTF-8 decoder handles
various types of correct, malformed, or otherwise interesting UTF-8
sequences. This file is not meant to be a conformance test. It does
not prescribe any particular outcome. Therefore, there is no way to
"pass" or "fail" this test file, even though the text does suggest a
preferable decoder behaviour at some places. Its aim is, instead, to
help you think about, and test, the behaviour of your UTF-8 decoder on a
systematic collection of unusual inputs. Experience so far suggests
that most first-time authors of UTF-8 decoders find at least one
serious problem in their decoder using this file.
The test lines below cover boundary conditions, malformed UTF-8
sequences, as well as correctly encoded UTF-8 sequences of Unicode code
points that should never occur in a correct UTF-8 file.
According to ISO 10646-1:2000, sections D.7 and 2.3c, a device
receiving UTF-8 shall interpret a "malformed sequence in the same way
that it interprets a character that is outside the adopted subset" and
"characters that are not within the adopted subset shall be indicated
to the user" by a receiving device. One commonly used approach in
UTF-8 decoders is to replace any malformed UTF-8 sequence by a
replacement character (U+FFFD), which looks a bit like an inverted
question mark, or a similar symbol. It might be a good idea to
visually distinguish a malformed UTF-8 sequence from a correctly
encoded Unicode character that is just not available in the current
font but otherwise fully legal, even though ISO 10646-1 doesn't
mandate this. In any case, just ignoring malformed sequences or
unavailable characters does not conform to ISO 10646, will make
debugging more difficult, and can lead to user confusion.
Please check, whether a malformed UTF-8 sequence is (1) represented at
all, (2) represented by exactly one single replacement character (or
equivalent signal), and (3) the following quotation mark after an
illegal UTF-8 sequence is correctly displayed, i.e. proper
resynchronization takes place immediately after any malformed
sequence. This file says "THE END" in the last line, so if you don't
see that, your decoder crashed somehow before, which should always be
cause for concern.
All lines in this file are exactly 79 characters long (plus the line
feed). In addition, all lines end with "|", except for the two test
lines 2.1.1 and 2.2.1, which contain non-printable ASCII controls
U+0000 and U+007F. If you display this file with a fixed-width font,
these "|" characters should all line up in column 79 (right margin).
This allows you to test quickly, whether your UTF-8 decoder finds the
correct number of characters in every line, that is whether each
malformed sequences is replaced by a single replacement character.
Note that, as an alternative to the notion of malformed sequence used
here, it is also a perfectly acceptable (and in some situations even
preferable) solution to represent each individual byte of a malformed
sequence with a replacement character. If you follow this strategy in
your decoder, then please ignore the "|" column.
Here come the tests: |
|
1 Some correct UTF-8 text |
|
You should see the Greek word 'kosme': "κόσμε" |
|
2 Boundary condition test cases |
|
2.1 First possible sequence of a certain length |
|
2.1.1 1 byte (U-00000000): "

@ -60,11 +60,12 @@ main(int argc, char* argv[])
assert(sa[0].sa_range.lr_start == 5);
assert(sa[0].sa_range.lr_end == 7);
assert(sa[0].sa_type == &VC_BACKGROUND);
assert(sa[0].sa_value.get<int64_t>() == COLOR_BLUE);
assert(sa[0].sa_type == &VC_STYLE);
assert(sa[0].sa_value.get<text_attrs>().ta_bg_color.value() == COLOR_BLUE);
assert(sa[1].sa_range.lr_start == 7);
assert(sa[1].sa_range.lr_end == 12);
assert(sa[1].sa_type == &VC_FOREGROUND);
assert(sa[1].sa_value.get<int64_t>() == COLOR_YELLOW);
assert(sa[1].sa_type == &VC_STYLE);
assert(sa[1].sa_value.get<text_attrs>().ta_fg_color.value()
== COLOR_YELLOW);
}

@ -14,3 +14,7 @@ run_cap_test ${lnav_test} -n \
run_cap_test ${lnav_test} -n \
${top_srcdir}/src/log_level.cc
cp ${test_dir}/UTF-8-test.txt UTF-8-test.md
run_cap_test ${lnav_test} -n \
UTF-8-test.md

@ -14,13 +14,34 @@ OSC Set window title: LOG
S -1 ┋ ┋
A └ normal, normal, normal
CSI Erase all
S 1 ┋ Thu Jun 06 1 :: :: LOG ┋
A └ fg(#c0c0c0), bg(#008080)
S 2 ┋ x┋
A ···············································································├ normal
A └┛ alt
A ················································································└ normal
S 1 ┋ 2013-06-06T12:13:20 PDT ┋
A └ bg(#008080)
S 16 ┋ Files :: Text Filters :: Press q to exit ┋
A └ bg(#000080), bold │ ││
A ·└ fg(#008080), bg(#000080), underline ││
A ··└ normal, bg(#000080), bold ││
A ·······└ normal, fg(#000000), bg(#000080) ││
A ········└ fg(#000080), bg(#c0c0c0) ││
A ·········└ fg(#000000), bg(#c0c0c0), bold ││
A ··········└ fg(#800080), bg(#c0c0c0), underline ││
A ···········└ normal, fg(#000000), bg(#c0c0c0), bold ││
A ·······················└ normal, fg(#000000), bg(#c0c0c0) ││
A ······································································└ bold
A ·······································································└ normal, fg(#000000), bg(#c0c0c0)
S 17 ┋ ┋
S 23 ┋ L0 0% ?:View Help ┋
A └ normal, bg(#008080)
S 18 ┋ ┋
A └ normal, normal
S 1 ┋ Press ENTER to focus on the breadcrumb bar ┋
A ·····································└ bg(#008080) │
A ···············································································└ carriage-return
S 2 ┋ LOG ❭ ┋
A └ fg(#000000), bg(#000080), bold
A ·····└ normal, fg(#008080), bg(#c0c0c0)
A ······└ fg(#000000), bg(#c0c0c0)
S 3 ┋ x┋
A ···············································································├ normal
A └┛ alt
A ················································································└ normal
S 4 ┋ x┋
@ -59,39 +80,13 @@ A ····································
S 15 ┋ x┋
A └┛ alt
A ················································································└ normal
S 16 ┋ x┋
S 18 ┋ x┋
A └┛ alt
A ················································································└ normal
S 17 ┋ lqqqq No log messages; Files: 0; Error rate: 0.00/min; Time span: None qqqqk x┋
A └----┛ alt │ │ │ │ │ │ │ ││ │││
A ·······························└ bold │ │ │ │ ││ │││
A ·································└ normal │ │ │ │ ││ │││
A ···································└ fg(#800000), bold │ ││ │││
A ·············································└ normal │ ││ │││
A ···············································└ bold │ ││ │││
A ···················································└ normal │ ││ │││
A ····································································└ bold │││
A ········································································└ normal│
A ·········································································├ bold││
A └----┛ alt
A ··············································································└ normal
S 19 ┋ x┋
A └┛ alt
A ················································································└ normal
S 18 ┋ Files :: Text Filters :: Press q to exit ┋
A └ fg(#c0c0c0), bg(#000080), bold ││
A ·└ fg(#008080), bg(#000080), underline ││
A ··└ normal, fg(#c0c0c0), bg(#000080), bold ││
A ·······└ normal, fg(#c0c0c0), bg(#000080) ││
A ········└ fg(#000080), bg(#c0c0c0) ││
A ·········└ fg(#000000), bg(#c0c0c0), bold ││
A ··········└ fg(#800080), bg(#c0c0c0), underline ││
A ···········└ normal, fg(#000000), bg(#c0c0c0), bold ││
A ·······················└ normal, fg(#000000), bg(#c0c0c0) ││
A ······································································└ bold
A ·······································································└ normal, fg(#000000), bg(#c0c0c0)
S 19 ┋ ┋
S 20 ┋ x┋
A ···············································································├ normal
A └┛ alt
A ················································································└ normal
S 21 ┋ x┋
@ -100,59 +95,61 @@ A ····································
S 22 ┋ x┋
A └┛ alt
A ················································································└ normal
S 23 ┋ L0 0% ?:View Help ┋
A └ fg(#000000), bg(#c0c0c0)
S 22 ┋ ┋
A └ normal, normal
A └ normal
OSC Set window title: HELP
S 1 ┋ Thu Jun 06 1 :: :: HELP ┋
A └ fg(#000000), bg(#c0c0c0) │││ │││
A ················································└ fg(#008080), bg(#c0c0c0)
A ·················································└ fg(#c0c0c0), bg(#008080)
A ··················································└ fg(#000000), bg(#008080)
A ······································································└ fg(#000080), bg(#008080)
A ·······································································└ fg(#008080), bg(#000080)
A ········································································└ fg(#c0c0c0), bg(#000080), bold
S 2 ┋ x┋
A ···············································································└ normal, fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 3 ┋ lnav - A fancy log file viewer ┋
A ··└ fg(#000000), bg(#c0c0c0), normal
A ································└ carriage-return
S 5 ┋DESCRIPTION ┋
A ···········└ carriage-return
S 6 ┋=========== ┋
A ···········└ carriage-return
S 8 ┋The log file navigator, lnav, is an enhanced log file viewer that ┋
A ·································································└ carriage-return
S 9 ┋takes advantage of any semantic information that can be gleaned from ┋
A ····································································└ carriage-return
S 10 ┋the files being viewed, such as timestamps and log levels. Using this ┋
S 2 ┋ HELP ❭⋯❭ ┋
A ·└ fg(#000000), bg(#000080), bold
A ······└ normal, fg(#008080), bg(#c0c0c0)
A ·······└ fg(#000000), bg(#c0c0c0)
A ········└ fg(#008080), bg(#c0c0c0)
S 3 ┋ x┋
A ···············································································└ normal, fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 4 ┋lnav ┋
A └ fg(#000000), normal, underline
A ····└ carriage-return
S 6 ┋A fancy log file viewer for the terminal. ┋
A └ normal │
A ·········································└ carriage-return
S 8 ┋Overview ┋
A └ underline
A ········└ carriage-return
S 10 ┋The Logfile Navigator, lnav, is an enhanced log file viewer that takes ┋
A └ normal │ │ │
A ·······················└ bold │
A ···························└ normal │
A ······································································└ carriage-return
S 11 ┋extra semantic information, lnav can do things like interleaving ┋
S 11 ┋advantage of any semantic information that can be gleaned from the ┋
A ··································································└ carriage-return
S 12 ┋files being viewed, such as timestamps and log levels. Using this ┋
A ·································································└ carriage-return
S 13 ┋extra semantic information, lnav can do things like interleaving ┋
A ································································└ carriage-return
S 12 ┋messages from different files, generate histograms of messages over ┋
S 14 ┋messages from different files, generate histograms of messages over ┋
A ···································································└ carriage-return
S 13 ┋time, and providing hotkeys for navigating through the file. It is ┋
A ···································································└ carriage-return
S 14 ┋hoped that these features will allow the user to quickly and ┋
A ····························································└ carriage-return
S 15 ┋efficiently zero in on problems. ┋
A ································└ carriage-return
S 17 ┋ ┋
A ··············································································└ carriage-return
S 18 ┋OPENING PATHS/URLs x┋
S 15 ┋time, and providing hotkeys for navigating through the file. It is ┋
A ··································································└ carriage-return
S 16 ┋hoped that these features will allow the user to quickly and x┋
A └┛ alt
A ················································································└ normal
S 19 ┋================== x┋
S 17 ┋efficiently zero in on problems. x┋
A └┛ alt
A ················································································└ normal
S 21 ┋The main arguments to lnav are the files, directories, glob patterns, ┋
A ·····································································└ carriage-return
S 22 ┋or URLs to be viewed. If no arguments are given, the default syslog ┋
S 19 ┋Opening Paths/URLs ┋
A └ underline │
A ··················└ carriage-return
S 21 ┋The main arguments to lnav are the local/remote files, directories, ┋
A └ normal │
A ···································································└ carriage-return
S 22 ┋glob patterns, or URLs to be viewed. If no arguments are given, the ┋
A ···································································└ carriage-return
S 23 ┋ L0 0% ?:View Help ┋
A └ fg(#000000), bg(#c0c0c0)
S 24 ┋ Press e/E to move forward/backward through error messags ┋
A ·······················└ normal││ │
A ·····························└ bold │
A ······························└ normal │
A ·······························└ bold │
@ -167,65 +164,62 @@ A └ normal
K 3a
CSI Erase Below
CSI Erase Below
S 24 ┋
S 24 ┋:
A └ normal
A ·└ normal
S 23 ┋ Enter an lnav command: (Press CTRL+] to abort) ┋
A ·└ fg(#000000), bg(#c0c0c0) │ │
A ·······························└ bold│
A ·····································└ normal, fg(#000000), bg(#c0c0c0)
S 23 ┋ ┋
A ···································································└ carriage-return
S 24 ┋: ┋
A └ normal
A ·└ normal
K 65
S 24 ┋ e ┋
A ·└ normal, normal
A ··└ normal
K 63
K 65
S 24 ┋ c ┋
A ···└ normal
K 68
K 63
S 24 ┋ h ┋
A ····└ normal
K 6f
K 68
S 24 ┋ o ┋
A ·····└ normal
K 20
K 6f
S 24 ┋ echo ┋
A ·····└ backspace
A ····└ backspace
A ···└ backspace
A ··└ backspace
A ·└ fg(#000080), bold
A ·└ fg(#000080)
A ······└ normal, normal
K 68
K 20
S 24 ┋ h ┋
A ·······└ normal
K 69
K 68
S 24 ┋ i ┋
A ········└ normal
K 0d
K 69
S 24 ┋ ┋
A ········└ carriage-return
CSI Erase Below
S 24 ┋
S 24 ┋hi
A └ normal
A ··└ normal
K 0d
S 23 ┋ L0 0% ┋
A ··└ backspace
A ·└ fg(#000000), bg(#c0c0c0)
S 23 ┋ ?:View Help ┋
A ···································································└ carriage-return
S 24 ┋✔ hi ┋
A └ normal, fg(#008000)
A ·└ normal
A ····└ carriage-return
A └ normal
S 24 ┋ ┋
A ··└ normal, normal
K 71
S 24 ┋ⓘ info: executing SQL statement, press CTRL+] to cancel ┋
A ··└ carriage-return │ │ │
A ·······································└ fg(#800080), bold, underline
A ·············································└ normal │
A ·······················································└ carriage-return
A └ normal
OSC Set window title: LOG
S 1 ┋ LOG ┋
A ···········································································└ fg(#c0c0c0), bg(#000080), bold
A ···············································································└ carriage-return
S 24 ┋ ┋
A └ normal, normal
CSI Erase all
CSI Use normal screen buffer
CTRL restore cursor

@ -14,13 +14,34 @@ OSC Set window title: LOG
S -1 ┋ ┋
A └ normal, normal, normal
CSI Erase all
S 1 ┋ Thu Jun 06 1 :: :: LOG ┋
A └ fg(#c0c0c0), bg(#008080)
S 2 ┋ x┋
A ···············································································├ normal
A └┛ alt
A ················································································└ normal
S 1 ┋ 2013-06-06T12:13:20 PDT ┋
A └ bg(#008080)
S 16 ┋ Files :: Text Filters :: Press q to exit ┋
A └ bg(#000080), bold │ ││
A ·└ fg(#008080), bg(#000080), underline ││
A ··└ normal, bg(#000080), bold ││
A ·······└ normal, fg(#000000), bg(#000080) ││
A ········└ fg(#000080), bg(#c0c0c0) ││
A ·········└ fg(#000000), bg(#c0c0c0), bold ││
A ··········└ fg(#800080), bg(#c0c0c0), underline ││
A ···········└ normal, fg(#000000), bg(#c0c0c0), bold ││
A ·······················└ normal, fg(#000000), bg(#c0c0c0) ││
A ······································································└ bold
A ·······································································└ normal, fg(#000000), bg(#c0c0c0)
S 17 ┋ ┋
S 23 ┋ L0 0% ?:View Help ┋
A └ normal, bg(#008080)
S 18 ┋ ┋
A └ normal, normal
S 1 ┋ Press ENTER to focus on the breadcrumb bar ┋
A ·····································└ bg(#008080) │
A ···············································································└ carriage-return
S 2 ┋ LOG ❭ ┋
A └ fg(#000000), bg(#000080), bold
A ·····└ normal, fg(#008080), bg(#c0c0c0)
A ······└ fg(#000000), bg(#c0c0c0)
S 3 ┋ x┋
A ···············································································├ normal
A └┛ alt
A ················································································└ normal
S 4 ┋ x┋
@ -59,39 +80,13 @@ A ····································
S 15 ┋ x┋
A └┛ alt
A ················································································└ normal
S 16 ┋ x┋
S 18 ┋ x┋
A └┛ alt
A ················································································└ normal
S 17 ┋ lqqqq No log messages; Files: 0; Error rate: 0.00/min; Time span: None qqqqk x┋
A └----┛ alt │ │ │ │ │ │ │ ││ │││
A ·······························└ bold │ │ │ │ ││ │││
A ·································└ normal │ │ │ │ ││ │││
A ···································└ fg(#800000), bold │ ││ │││
A ·············································└ normal │ ││ │││
A ···············································└ bold │ ││ │││
A ···················································└ normal │ ││ │││
A ····································································└ bold │││
A ········································································└ normal│
A ·········································································├ bold││
A └----┛ alt
A ··············································································└ normal
S 19 ┋ x┋
A └┛ alt
A ················································································└ normal
S 18 ┋ Files :: Text Filters :: Press q to exit ┋
A └ fg(#c0c0c0), bg(#000080), bold ││
A ·└ fg(#008080), bg(#000080), underline ││
A ··└ normal, fg(#c0c0c0), bg(#000080), bold ││
A ·······└ normal, fg(#c0c0c0), bg(#000080) ││
A ········└ fg(#000080), bg(#c0c0c0) ││
A ·········└ fg(#000000), bg(#c0c0c0), bold ││
A ··········└ fg(#800080), bg(#c0c0c0), underline ││
A ···········└ normal, fg(#000000), bg(#c0c0c0), bold ││
A ·······················└ normal, fg(#000000), bg(#c0c0c0) ││
A ······································································└ bold
A ·······································································└ normal, fg(#000000), bg(#c0c0c0)
S 19 ┋ ┋
S 20 ┋ x┋
A ···············································································├ normal
A └┛ alt
A ················································································└ normal
S 21 ┋ x┋
@ -100,59 +95,61 @@ A ····································
S 22 ┋ x┋
A └┛ alt
A ················································································└ normal
S 23 ┋ L0 0% ?:View Help ┋
A └ fg(#000000), bg(#c0c0c0)
S 22 ┋ ┋
A └ normal, normal
A └ normal
OSC Set window title: HELP
S 1 ┋ Thu Jun 06 1 :: :: HELP ┋
A └ fg(#000000), bg(#c0c0c0) │││ │││
A ················································└ fg(#008080), bg(#c0c0c0)
A ·················································└ fg(#c0c0c0), bg(#008080)
A ··················································└ fg(#000000), bg(#008080)
A ······································································└ fg(#000080), bg(#008080)
A ·······································································└ fg(#008080), bg(#000080)
A ········································································└ fg(#c0c0c0), bg(#000080), bold
S 2 ┋ x┋
A ···············································································└ normal, fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 3 ┋ lnav - A fancy log file viewer ┋
A ··└ fg(#000000), bg(#c0c0c0), normal
A ································└ carriage-return
S 5 ┋DESCRIPTION ┋
A ···········└ carriage-return
S 6 ┋=========== ┋
A ···········└ carriage-return
S 8 ┋The log file navigator, lnav, is an enhanced log file viewer that ┋
A ·································································└ carriage-return
S 9 ┋takes advantage of any semantic information that can be gleaned from ┋
A ····································································└ carriage-return
S 10 ┋the files being viewed, such as timestamps and log levels. Using this ┋
S 2 ┋ HELP ❭⋯❭ ┋
A ·└ fg(#000000), bg(#000080), bold
A ······└ normal, fg(#008080), bg(#c0c0c0)
A ·······└ fg(#000000), bg(#c0c0c0)
A ········└ fg(#008080), bg(#c0c0c0)
S 3 ┋ x┋
A ···············································································└ normal, fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 4 ┋lnav ┋
A └ fg(#000000), normal, underline
A ····└ carriage-return
S 6 ┋A fancy log file viewer for the terminal. ┋
A └ normal │
A ·········································└ carriage-return
S 8 ┋Overview ┋
A └ underline
A ········└ carriage-return
S 10 ┋The Logfile Navigator, lnav, is an enhanced log file viewer that takes ┋
A └ normal │ │ │
A ·······················└ bold │
A ···························└ normal │
A ······································································└ carriage-return
S 11 ┋extra semantic information, lnav can do things like interleaving ┋
S 11 ┋advantage of any semantic information that can be gleaned from the ┋
A ··································································└ carriage-return
S 12 ┋files being viewed, such as timestamps and log levels. Using this ┋
A ·································································└ carriage-return
S 13 ┋extra semantic information, lnav can do things like interleaving ┋
A ································································└ carriage-return
S 12 ┋messages from different files, generate histograms of messages over ┋
A ···································································└ carriage-return
S 13 ┋time, and providing hotkeys for navigating through the file. It is ┋
S 14 ┋messages from different files, generate histograms of messages over ┋
A ···································································└ carriage-return
S 14 ┋hoped that these features will allow the user to quickly and ┋
A ····························································└ carriage-return
S 15 ┋efficiently zero in on problems. ┋
A ································└ carriage-return
S 17 ┋ ┋
A ··············································································└ carriage-return
S 18 ┋OPENING PATHS/URLs x┋
S 15 ┋time, and providing hotkeys for navigating through the file. It is ┋
A ··································································└ carriage-return
S 16 ┋hoped that these features will allow the user to quickly and x┋
A └┛ alt
A ················································································└ normal
S 19 ┋================== x┋
S 17 ┋efficiently zero in on problems. x┋
A └┛ alt
A ················································································└ normal
S 21 ┋The main arguments to lnav are the files, directories, glob patterns, ┋
A ·····································································└ carriage-return
S 22 ┋or URLs to be viewed. If no arguments are given, the default syslog ┋
S 19 ┋Opening Paths/URLs ┋
A └ underline │
A ··················└ carriage-return
S 21 ┋The main arguments to lnav are the local/remote files, directories, ┋
A └ normal │
A ···································································└ carriage-return
S 22 ┋glob patterns, or URLs to be viewed. If no arguments are given, the ┋
A ···································································└ carriage-return
S 23 ┋ L0 0% ?:View Help ┋
A └ fg(#000000), bg(#c0c0c0)
S 24 ┋ Press e/E to move forward/backward through error messags ┋
A ·······················└ normal││ │
A ·····························└ bold │
A ······························└ normal │
A ·······························└ bold │
@ -166,11 +163,13 @@ A ····································
A └ normal
K 71
OSC Set window title: LOG
S 1 ┋ LOG ┋
A ···········································································└ fg(#c0c0c0), bg(#000080), bold
A ···············································································└ carriage-return
S 24 ┋ⓘ info: executing SQL statement, press CTRL+] to cancel ┋
A ·······································└ fg(#800080), bold, underline
A ·············································└ normal
CSI Erase to Right
S 24 ┋ ┋
A └ normal, normal
A ·······················································└ carriage-return
A └ normal
CSI Erase all
CSI Use normal screen buffer
CTRL restore cursor

@ -14,13 +14,14 @@ OSC Set window title: LOG
S -1 ┋ ┋
A └ normal, normal, normal
CSI Erase all
S 1 ┋ Thu Jun 06 1 :: :: LOG
A └ fg(#c0c0c0), bg(#008080)
S 2 ┋ x
A ···············································································├ normal
A └┛ alt
A ················································································└ normal
S 1 ┋ 2013-06-06T12:13:20 PDT Press ENTER to focus on the breadcrumb bar
A └ bg(#008080)
S 2 ┋ LOG ❭
A └ fg(#000000), bg(#000080), bold
A ·····└ normal, fg(#008080), bg(#c0c0c0)
A ······└ fg(#000000), bg(#c0c0c0)
S 3 ┋ x┋
A ···············································································├ normal
A └┛ alt
A ················································································└ normal
S 4 ┋ x┋
@ -59,284 +60,247 @@ A ····································
S 15 ┋ x┋
A └┛ alt
A ················································································└ normal
S 16 ┋ x┋
A └┛ alt
A ················································································└ normal
S 17 ┋ lqqqq No log messages; Log Files: 0; Text Files: 1; Error rate: 0.00/min; Tix┋
A └----┛ alt │ │ │ │ │ │ │ │ ││
A ···································└ bold │ │ │ │ │ │ ││
A ·····································└ normal │ │ │ │ │ │ ││
A ···················································└ bold │ │ │ ││
A ·····················································└ normal │ │ │ ││
A ·······················································└ fg(#800000), bold ││
A ·································································└ normal ││
A ···································································└ bold ││
A ·······································································└ normal││
A └┛ alt
A ················································································└ normal
S 18 ┋ Files :: Text Filters :: Press q to exit ┋
A └ fg(#c0c0c0), bg(#000080), bold ││
S 16 ┋ Files :: Text Filters :: 0 of 1 enabled Press q to exit ┋
A └ bg(#000080), bold │ ││ ││ ││
A ·└ fg(#008080), bg(#000080), underline ││
A ··└ normal, fg(#c0c0c0), bg(#000080), bold ││
A ·······└ normal, fg(#c0c0c0), bg(#000080) ││
A ··└ normal, bg(#000080), bold ││ ││
A ·······└ normal, fg(#000000), bg(#000080) ││
A ········└ fg(#000080), bg(#c0c0c0) ││
A ·········└ fg(#000000), bg(#c0c0c0), bold ││
A ··········└ fg(#800080), bg(#c0c0c0), underline ││
A ···········└ normal, fg(#000000), bg(#c0c0c0), bold ││
A ·······················└ normal, fg(#000000), bg(#c0c0c0) ││
A ··························└ bold│ ││
A ···························└ normal, fg(#000000), bg(#c0c0c0) ││
A ·······························└ bold ││
A ································└ normal, fg(#000000), bg(#c0c0c0) ││
A ······································································└ bold
A ·······································································└ normal, fg(#000000), bg(#c0c0c0)
S 19 ┋ ┋
S 20 ┋→ ` logfile_xml_msg.0 0.0 B — x┋
A ··├ fg(#008000), bg(#c0c0c0) │ │
A └┛ alt │ │ │
A ···└ fg(#000000), bg(#c0c0c0) │ │
A ························└ bold│ │
A ······························└ normal, fg(#000000), bg(#c0c0c0) │
S 17 ┋ ┋
S 18 ┋→ ` logfile_xml_msg.0 0.0 B — x┋
A ··├ fg(#008000), bg(#c0c0c0) │ │ ││
A └┛ alt │ │ │ ││
A ···└ fg(#000000), bg(#c0c0c0) │ │ ││
A ························└ bold│ │ ││
A ······························└ normal, fg(#000000), bg(#c0c0c0) ││
A ······································└ fg(#808000), bg(#c0c0c0) ││
A ···············································································└ normal, fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 19 ┋ x┋
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 20 ┋ x┋
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 21 ┋ x┋
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 22 ┋ x┋
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 23 ┋ L0 0% ?:View Help ┋
A └ fg(#000000), bg(#c0c0c0)
A └ fg(#000000), normal, bg(#008080)
S 22 ┋ ┋
A └ normal, normal
S 19 ┋ SPC: Hide ENTER: Jump To ┋
A ··└ fg(#000000), bg(#c0c0c0), bold
A ·····└ normal, fg(#000000), bg(#c0c0c0)
A ·············└ bold
A ··················└ normal, fg(#000000), bg(#c0c0c0)
S 20 ┋ 64.0 B 2020-12-10 06:56:41.061 — 2020-12-10 06:56:41. ┋
A ···························└ backspace │
A ··························└ bold │
S 18 ┋ 64.0 B 2020-12-10 06:56:41.061 — 2020-12-10 06:56:41. ┋
A ··························└ fg(#000000), bg(#c0c0c0), bold │
A ······························└ normal, fg(#000000), bg(#c0c0c0) │
A ···············································································└ carriage-return
S 22 ┋ ┋
A └ normal, normal
S 20 ┋ 628 ┋
S 18 ┋ 628 ┋
A ·························└ fg(#000000), bg(#c0c0c0), bold
A ····························└ carriage-return
S 22 ┋ ┋
A └ normal, normal
OSC Set window title: logfile_xml_msg.0
S 1 ┋ logfile_xml_msg.0 ┋
A ·······························└ fg(#c0c0c0), bg(#008080)
S 1 ┋ xml_msg_log ┋
A ······································································└ carriage-return
S 2 ┋x x ┋
A └┛ alt│
A ·└ normal
A ······└ carriage-return
S 3 ┋x </head> ┋
A └┛ alt │
A ·└ normal │
A ··········└ carriage-return
S 4 ┋x <reply id="2"> ┋
A └┛ alt │ ││ ││
A ·└ normal │ ││ ││
A ··········└ fg(#008080)
A ············└ normal
A ·············└ fg(#008000), bold
A ················└ normal
A ·················└ carriage-return
S 5 ┋x <status> ┋
A └┛ alt │
A ·└ normal │
S 16 ┋ 1 ┋
A ··························└ fg(#000000), bg(#c0c0c0), bold
S 23 ┋ 25 10 ┋
A ··└ normal, bg(#008080)
A ·············└ carriage-return
S 6 ┋x <result>OK</result> ┋
A ·└ normal │
A └┛ alt │ │
A ·└ normal │
A ·······└ normal │
A ··························└ carriage-return
S 7 ┋x </status> ┋
A └┛ alt │
A ·└ normal │
A ··············└ carriage-return
S 8 ┋x <name> ┋
A └┛ alt │
A ·└ normal │
A ···········└ carriage-return
S 9 ┋x x ┋
A ·└ normal
A └┛ alt ││
A ·└ normal
A ·······└ normal
A ········└ carriage-return
S 10 ┋x </name> ┋
A └┛ alt │
A ·└ normal │
A ············└ carriage-return
S 11 ┋x </reply> x┋
S 22 ┋ ┋
A └ normal, normal
S 2 ┋ 2020-12-10T06:56:41.061❭xml_msg_log❭logfile_xml_msg.0[0]❭ ┋
A ······└ fg(#000000), bg(#c0c0c0) ││ ││
A ·····························└ fg(#008080), bg(#c0c0c0) ││
A ······························└ fg(#000000), bg(#c0c0c0) ││
A ·········································└ fg(#008080), bg(#c0c0c0)
A ··········································└ fg(#000000), bg(#c0c0c0)
A ······························································└ fg(#008080), bg(#c0c0c0)
A ·······························································└ carriage-return
S 3 ┋l[2020-12-10 06:56:41,061] INFO [m:108] Calling 'x' with params: x┋
A ├ normal │ │ ││
A └┛ alt │ │ ││
A ················································└ fg(#008000), bold ││
A ···················································└ normal ││
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 4 ┋x x┋
A ├ fg(#000000), normal ││
A └┛ alt ││
A ·└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 12 ┋x <technical-track> x┋
A ├ fg(#000000), bg(#c0c0c0) ││
S 5 ┋x[2020-12-10 06:56:41,092] DEBUG [connect.client:69] Full request text: x┋
A ├ fg(#000000), normal ││
A └┛ alt ││
A ·└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 13 ┋x x x┋
A ├ fg(#000000), bg(#c0c0c0) ││
A └┛ alt ││
A ·└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
S 6 ┋x<?xml version='1.0' encoding='iso-8859-2'?> x┋
A ├ fg(#000000), normal│ ││ │ ││
A └┛ alt │ ││ ││ ││ │ ││
A ·······└ fg(#008080)││ ││ │ ││
A ··············└ normal ││ │ ││
A ···············└ fg(#008000), bold │ ││
A ····················└ normal ││ │ ││
A ·····················└ fg(#008080) │ ││
A ·····························└ normal │ ││
A ······························└ fg(#008000), bold ││
A ··········································└ normal ││
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 14 ┋x </technical-track> x┋
A ├ fg(#000000), bg(#c0c0c0) ││
S 7 ┋x<a-request> x┋
A ├ fg(#000000), normal ││
A └┛ alt ││
A ·└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 15 ┋x</a-reply> x┋
A ├ fg(#000000), bg(#c0c0c0) ││
A └┛ alt ││
A ·└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
S 8 ┋x <head> ┋
A ├ fg(#000000), normal
A └┛ alt │
A ·········└ carriage-return
S 9 ┋x x ┋
A └┛ alt│
A ······└ carriage-return
S 10 ┋x </head> ┋
A └┛ alt │
A ··········└ carriage-return
S 11 ┋x <source> ┋
A └┛ alt │
A ···········└ carriage-return
S 12 ┋x x ┋
A └┛ alt│
A ······└ carriage-return
S 13 ┋x </source> ┋
A └┛ alt │
A ············└ carriage-return
S 14 ┋x <request id="1"> ┋
A └┛ alt │ ││ ││
A ············└ fg(#008080)
A ··············└ normal
A ···············└ fg(#008000), bold
A ··················└ normal
A ···················└ carriage-return
S 15 ┋x <name> ┋
A └┛ alt │
A ···········└ carriage-return
S 22 ┋ ┋
A └ normal
CSI set scrolling region 3-20
S 3 ┋ ┋
A └ [2M
CSI set scrolling region 1-24
CSI Erase Below
S 2 ┋ 92 ┋
A ···························└ fg(#000000), bg(#c0c0c0)
S 2 ┋ 2]❭⋯❭ ┋
A ······························································└ fg(#008080), bg(#c0c0c0)
A ·······························································└ fg(#000000), bg(#c0c0c0)
A ································································└ fg(#008080), bg(#c0c0c0)
S 3 ┋ x┋
A ···············································································├ normal
A └┛ alt
A ················································································└ normal
S 16 ┋ x┋
A ···············································································└ fg(#000000), bg(#c0c0c0)
S 6 ┋ x┋
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 17 ┋ Last message: in the future; Files: 1; Error rate: 0.00/min; Time span:x┋
A ·······└ fg(#000000), bg(#c0c0c0), normal │ │ │ │ │ │ ││
A ·····················└ bold │ │ │ │ │ │ │ ││
A ··································└ normal │ │ │ │ │ │ ││
A ···········································└ bold │ │ │ ││
A ·············································└ normal │ │ │ ││
A ···············································└ fg(#800000), bold ││
A ·························································└ normal ││
A ···························································└ bold ││
A ·······························································└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
S 7 ┋ x┋
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 23 ┋ 22 10 ┋
A ··└ fg(#000000), bg(#c0c0c0)
A ·············└ carriage-return
S 22 ┋ ┋
A └ normal, normal
CSI Erase Below
S 1 ┋ Thu Jun 06 1 logfile_xml_msg.0:: xml_msg_log:: LOG ┋
A └ fg(#000000), bg(#c0c0c0) │││ │││
A ················································└ fg(#008080), bg(#c0c0c0)
A ·················································└ fg(#c0c0c0), bg(#008080)
A ··················································└ fg(#000000), bg(#008080)
A ······································································└ fg(#000080), bg(#008080)
A ·······································································└ fg(#008080), bg(#000080)
A ········································································└ fg(#c0c0c0), bg(#000080), bold
S 2 ┋ [2020-12-10 06:56:41,092] DEBUG [connect.client:69] Full request text: ┋
A ·└ normal │
A ················································└ normal
S 3 ┋ <?xml version='1.0' encoding='iso-8859-2'?> x┋
A ·······└ fg(#008080)││ ││ │ ││
A ··············└ normal ││ │ ││
A ···············└ fg(#008000), bold │ ││
A ····················└ normal ││ │ ││
A ·····················└ fg(#008080) │ ││
A ·····························└ normal │ ││
A ······························└ fg(#008000), bold ││
A ··········································└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
S 8 ┋ x┋
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 4 ┋ <a-request> x┋
A ·└ fg(#000000), bg(#c0c0c0), normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
S 9 ┋ x┋
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 5 ┋ <head> x┋
A ···└ fg(#000000), bg(#c0c0c0), normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
S 10 ┋ x┋
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 6 ┋ x x┋
A ·····└ fg(#000000), bg(#c0c0c0), normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
S 11 ┋ x┋
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 7 ┋ </head> x┋
A ···└ fg(#000000), bg(#c0c0c0), normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
S 12 ┋ x┋
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 8 ┋ <sourc x┋
A ···└ fg(#000000), bg(#c0c0c0), normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
S 13 ┋ x┋
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 9 ┋ x x┋
A ·····└ fg(#000000), bg(#c0c0c0), normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
S 14 ┋x x x┋
A ├ fg(#000000), normal ││
A └┛ alt ││
A ···············································································└ fg(#000000)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 10 ┋ </sourc x┋
A ···└ fg(#000000), bg(#c0c0c0), normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
S 15 ┋x </name> x┋
A ├ fg(#000000), normal ││
A └┛ alt ││
A └┛ alt
A ················································································└ normal
S 11 ┋ request id="1"> ┋
A ····└ fg(#000000), bg(#c0c0c0), normal
A ············└ fg(#008080)
A ··············└ normal
A ···············└ fg(#008000), bold
A ··················└ normal
S 12 ┋ <name> ┋
S 13 ┋ x ┋
S 14 ┋ </name> ┋
S 15 ┋ </request> x┋
S 16 ┋x </request> x┋
A └┛ alt ││
A └┛ alt
A ················································································└ normal
S 16 ┋x</a-request> x┋
S 17 ┋x</a-request> x┋
A └┛ alt ││
A ·└ normal ││
A └┛ alt
A ················································································└ normal
S 17 ┋x x┋
S 18 ┋x x┋
A └┛ alt ││
A ·└ normal ││
A └┛ alt
A ················································································└ normal
S 18 ┋x[2020-12-10 06:56:41,099] DEBUG [m:85] Full reply text: x┋
A └┛ alt │ ││
A ·└ normal │ ││
A ···································└ normal ││
S 19 ┋x[2020-12-10 06:56:41,099] DEBUG [m:85] Full reply text: x┋
A └┛ alt ││
A └┛ alt
A ················································································└ normal
S 19 ┋x<?xml version='1.0' encoding='iso-8859-2'?> x┋
S 20 ┋x<?xml version='1.0' encoding='iso-8859-2'?> x┋
A └┛ alt │ ││ ││ ││ │ ││
A ·└ normal ││ ││ ││ │ ││
A ·······└ fg(#008080)││ ││ │ ││
A ··············└ normal ││ │ ││
A ···············└ fg(#008000), bold │ ││
@ -347,127 +311,120 @@ A ······························└ fg(#00800
A ··········································└ normal ││
A └┛ alt
A ················································································└ normal
S 20 ┋x<a-reply> x┋
A └┛ alt ││
A ·└ normal ││
A └┛ alt
A ················································································└ normal
S 21 ┋x <head> x┋
S 21 ┋x<a-reply> x┋
A └┛ alt ││
A ·└ normal ││
A └┛ alt
A ················································································└ normal
S 22 ┋ Files :: Text Filters :: Press TAB to edit ┋
A └ fg(#c0c0c0), bg(#008080) │ │
S 24 ┋ ┋
A └ normal
S 22 ┋ Files :: Text Filters :: 0 of 1 enabled Press TAB to edit ┋
A └ bg(#008080) ││ ││ │ │
A ··························└ bold│ │ │
A ···························└ normal, bg(#008080) │ │
A ·······························└ bold │ │
A ································└ normal, bg(#008080) │ │
A ····································································└ bold
A ·······································································└ normal, fg(#c0c0c0), bg(#008080)
S 23 ┋ 61 ┋
A ···└ fg(#000000), bg(#c0c0c0)
A ··············└ carriage-return
A ·······································································└ normal, bg(#008080)
S 23 ┋ L2 58% ?:View Help ┋
A └ fg(#000000), bg(#c0c0c0)
S 24 ┋ ┋
A └ normal, normal
K 70
S 3 ┋ Received Time: 2020-12-10T06:56:41.092 -- in the future ┋
S 4 ┋ Received Time: 2020-12-10T06:56:41.092 -- in the future ┋
A ················└ bold │ │ │
A ·······································└ normal │
A ···········································└ bold │
A ························································└ carriage-return
S 4 ┋ Pattern: xml_msg_log/regex/std = ^\[(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2} ┋
A └ normal ││ │ │ │ │││││ │││││ │││││ │││││ ││││
A ··································└ fg(#008080), bold││││ │││││ │││││ │││││ ││││
A ···································└ normal │ │││││ │││││ │││││ │││││ ││││
A ·····································└ fg(#008000), bold│ │││││ │││││ │││││ ││││
A ········································└ normal │ │││││ │││││ │││││ │││││ ││││
A ··················································└ fg(#000080), bold │││││ ││││
A ····················································└ fg(#008000)││││ │││││ ││││
A ·····················································└ normal││ │││││ │││││ ││││
A ······················································└ fg(#008000), bold││ ││││
A ·······················································└ normal │││││ │││││ ││││
A ························································└ fg(#000080), bold ││││
A ··························································└ fg(#008000)││││ ││││
A ···························································└ normal││ │││││ ││││
A ····························································└ fg(#008000), bold│
A ·····························································└ normal │││││ ││││
A ······························································└ fg(#000080), bold
A ································································└ fg(#008000)│││
A ·································································└ normal││ ││││
A ··································································└ fg(#008000), bold
A ···································································└ normal ││││
A ····································································└ fg(#000080), bold
A ······································································└ fg(#008000)
A ·······································································└ normal│
A ········································································└ fg(#008000), bold
A ·········································································└ normal
A ··········································································└ fg(#000080), bold
A ············································································└ fg(#008000)
A ·············································································└ normal
A ··············································································└ fg(#008000), bold
S 5 ┋ Pattern: /xml_msg_log/regex/std = ^\[(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2 ┋
A └ normal ││ │ ││ ││ │││││ │││││ │││││ │││││ │││
A ···································└ fg(#008080) ││ │││││ │││││ │││││ │││││ │││
A ····································└ normal ││ │││││ │││││ │││││ │││││ │││
A ······································└ fg(#008000), bold│ │││││ │││││ │││││ │││
A ········································└ normal, fg(#008080)│││ │││││ │││││ │││
A ·········································└ normal ││ │││││ │││││ │││││ │││││ │││
A ··················································└ fg(#008080)│ │││││ │││││ │││
A ···················································└ fg(#000080) │││││ │││││ │││
A ·····················································└ fg(#008000), bold││││ │││
A ······················································└ normal││ │││││ │││││ │││
A ·······················································└ fg(#008000), bold││ │││
A ························································└ normal │││││ │││││ │││
A ·························································└ fg(#000080) │││││ │││
A ···························································└ fg(#008000), bold││
A ····························································└ normal││ │││││ │││
A ·····························································└ fg(#008000), bold
A ······························································└ normal │││││ │││
A ·······························································└ fg(#000080) │││
A ·································································└ fg(#008000), bold
A ··································································└ normal││ │││
A ···································································└ fg(#008000), bold
A ····································································└ normal │││
A ·····································································└ fg(#000080)
A ·······································································└ fg(#008000), bold
A ········································································└ normal
A ·········································································└ fg(#008000), bold
A ··········································································└ normal
A ···········································································└ fg(#000080)
A ·············································································└ fg(#008000), bold
A ··············································································└ normal
A ···············································································└ carriage-return
S 5 ┋ Known message fields for table xml_msg_log: ┋
A └ normal │ ││
S 6 ┋ Known message fields for table xml_msg_log: ┋
A ································└ bold ││
A ···········································└ normal
A ············································└ carriage-return
S 6 ┋ t timestamp = 2020-12-10 06:56:41,092 ┋
A └┛ alt │ │ │
A ············└ normal │
S 7 ┋ t log_time = 2020-12-10 06:56:41,092 ┋
A └┛ alt │ │
A ···············└ bold │
A ···············································································└ carriage-return
S 7 ┋ t level = DEBUG ┋
A └ normal│ │ │
A └┛ alt │ │ │
A ········└ normal │
S 8 ┋ t level = DEBUG ┋
A └ normal │ │
A └┛ alt │ │
A ···············└ bold │
A ···············································································└ carriage-return
S 8 ┋ t module = connect.client ┋
A └ normal │ │ │
A └┛ alt │ │ │
A ·········└ normal │
S 9 ┋ t module = connect.client ┋
A └ normal │ │
A └┛ alt │ │
A ···············└ bold │
A ···············································································└ carriage-return
S 9 ┋ t line = 69 ┋
A └ normal │ │ │
A └┛ alt │ │ │
A ·············└ normal │
S 10 ┋ t line = 69 ┋
A └ normal │ │
A └┛ alt │ │
A ···············└ bold │
A ···············································································└ carriage-return
S 10 ┋ t body = Full request text: ┋
S 11 ┋ t log_body = Full request text: ┋
A └ normal │ │
A └┛ alt│ │ │
A ·······└ normal│ │
A └┛ alt │ │
A ···············└ bold │
A ···············································································└ carriage-return
S 11 ┋ t msg_data = <?xml version='1.0' encoding='iso-8859-2'?> <a-request> <head> ┋
A └ normal │ │ │
A └┛ alt │ │ │
A ···········└ normal │
S 12 ┋ t msg_data = <?xml version='1.0' encoding='iso-8859-2'?> <a-request> <head> ┋
A └ normal │ │
A └┛ alt │ │
A ···············└ bold │
A ···············································································└ carriage-return
S 12 ┋ XML fields: ┋
S 13 ┋ XML fields: ┋
A └ normal │
A ············└ carriage-return
S 13 ┋ t xpath('/a-request/head/text()', msg_data) = x ┋
S 14 ┋ t xpath('/a-request/head/text()', msg_data) = x ┋
A └┛ alt │
A ······└ bold │
A ···············································································└ carriage-return
S 14 ┋ t xpath('/a-request/request/@id', msg_data) = 1 ┋
S 15 ┋ t xpath('/a-request/request/@id', msg_data) = 1 ┋
A └ normal │
A └┛ alt │
A ······└ bold │
A ···············································································└ carriage-return
S 15 ┋ t xpath('/a-request/request/name/text()', msg_data) = x ┋
S 16 ┋ t xpath('/a-request/request/name/text()', msg_data) = x ┋
A └ normal │
A └┛ alt │
A ······└ bold │
A ···············································································└ carriage-return
S 16 ┋ t xpath('/a-request/source/text()', msg_data) = x ┋
S 17 ┋ t xpath('/a-request/source/text()', msg_data) = x ┋
A └ normal │
A └┛ alt │
A ······└ bold │
A ···············································································└ carriage-return
S 17 ┋ No discovered message fields ┋
S 18 ┋ No discovered message fields ┋
A └ normal
S 18 ┋ <?xml version='1.0' encoding='iso-8859-2'?> ┋
S 19 ┋ <?xml version='1.0' encoding='iso-8859-2'?> ┋
A ·······└ fg(#008080)││ ││ │
A ··············└ normal ││ │
A ···············└ fg(#008000), bold │
@ -476,13 +433,22 @@ A ·····················└ fg(#008080) │
A ·····························└ normal │
A ······························└ fg(#008000), bold
A ··········································└ normal
S 19 ┋ a-request> ┋
S 20 ┋ <head> ┋
S 21 ┋ x ┋
A ·········└ carriage-return
S 20 ┋ a-request> ┋
S 21 ┋ <head> ┋
A ··········└ carriage-return
S 24 ┋ ┋
A └ normal
K 71
S 23 ┋ 0 ┋
A ··└ fg(#000000), bg(#c0c0c0)
S 23 ┋ 0 ┋
A ··············└ carriage-return
S 24 ┋ⓘ info: executing SQL statement, press CTRL+] to cancel ┋
A └ normal │ │ │
A ·······································└ fg(#800080), bold, underline
A ·············································└ normal │
A ·······················································└ carriage-return
A └ normal
CSI Erase all
CSI Use normal screen buffer
CTRL restore cursor

Loading…
Cancel
Save