mirror of https://github.com/tstack/lnav.git
[console] colorize console output
This commit is contained in:
parent
7652c58248
commit
0785a432fa
|
@ -4,8 +4,11 @@
|
|||
"properties": {
|
||||
"$schema": {
|
||||
"title": "/$schema",
|
||||
"description": "Specifies the type of this file",
|
||||
"type": "string"
|
||||
"description": "The URI that specifies the schema that describes this type of file",
|
||||
"type": "string",
|
||||
"examples": [
|
||||
"https://lnav.org/schemas/config-v1.schema.json"
|
||||
]
|
||||
},
|
||||
"tuning": {
|
||||
"description": "Internal settings",
|
||||
|
@ -314,6 +317,36 @@
|
|||
"description": "Styling for scrollbars",
|
||||
"title": "/ui/theme-defs/<theme_name>/styles/scrollbar",
|
||||
"$ref": "#/definitions/style"
|
||||
},
|
||||
"h1": {
|
||||
"description": "Styling for top-level headers",
|
||||
"title": "/ui/theme-defs/<theme_name>/styles/h1",
|
||||
"$ref": "#/definitions/style"
|
||||
},
|
||||
"h2": {
|
||||
"description": "Styling for 2nd-level headers",
|
||||
"title": "/ui/theme-defs/<theme_name>/styles/h2",
|
||||
"$ref": "#/definitions/style"
|
||||
},
|
||||
"h3": {
|
||||
"description": "Styling for 3rd-level headers",
|
||||
"title": "/ui/theme-defs/<theme_name>/styles/h3",
|
||||
"$ref": "#/definitions/style"
|
||||
},
|
||||
"h4": {
|
||||
"description": "Styling for 4th-level headers",
|
||||
"title": "/ui/theme-defs/<theme_name>/styles/h4",
|
||||
"$ref": "#/definitions/style"
|
||||
},
|
||||
"h5": {
|
||||
"description": "Styling for 5th-level headers",
|
||||
"title": "/ui/theme-defs/<theme_name>/styles/h5",
|
||||
"$ref": "#/definitions/style"
|
||||
},
|
||||
"h6": {
|
||||
"description": "Styling for 6th-level headers",
|
||||
"title": "/ui/theme-defs/<theme_name>/styles/h6",
|
||||
"$ref": "#/definitions/style"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
@ -516,7 +549,7 @@
|
|||
"title": "/ui/keymap-defs/<keymap_name>/<key_seq>/command",
|
||||
"description": "The command to execute for the given key sequence. Use a script to execute more complicated operations.",
|
||||
"type": "string",
|
||||
"pattern": "[:|;].*",
|
||||
"pattern": "^[:|;].*",
|
||||
"examples": [
|
||||
":goto next hour"
|
||||
]
|
||||
|
|
|
@ -419,18 +419,15 @@
|
|||
"search-table": {
|
||||
"description": "Search tables to automatically define for this log format",
|
||||
"title": "/<format_name>/search-table",
|
||||
"type": [
|
||||
"string",
|
||||
"object"
|
||||
],
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"\\w+": {
|
||||
"(\\w+)": {
|
||||
"description": "The set of search tables to be automatically defined",
|
||||
"title": "/<format_name>/search-table/<>",
|
||||
"title": "/<format_name>/search-table/<table_name>",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"title": "/<format_name>/search-table/<>/pattern",
|
||||
"title": "/<format_name>/search-table/<table_name>/pattern",
|
||||
"description": "The regular expression for this search table.",
|
||||
"type": "string"
|
||||
}
|
||||
|
|
|
@ -244,9 +244,7 @@ add_library(
|
|||
${GEN_SRCS}
|
||||
config.h.in
|
||||
all_logs_vtab.cc
|
||||
ansi_scrubber.cc
|
||||
archive_manager.cc
|
||||
attr_line.cc
|
||||
bin2c.hh
|
||||
bookmarks.cc
|
||||
bottom_status_source.cc
|
||||
|
@ -317,7 +315,6 @@ add_library(
|
|||
sql_util.cc
|
||||
state-extension-functions.cc
|
||||
styling.cc
|
||||
string_attr_type.cc
|
||||
text_format.cc
|
||||
textfile_highlighters.cc
|
||||
textfile_sub_source.cc
|
||||
|
@ -342,8 +339,6 @@ add_library(
|
|||
all_logs_vtab.hh
|
||||
archive_manager.hh
|
||||
archive_manager.cfg.hh
|
||||
attr_line.hh
|
||||
auto_mem.hh
|
||||
big_array.hh
|
||||
bottom_status_source.hh
|
||||
bound_tags.hh
|
||||
|
@ -369,6 +364,8 @@ add_library(
|
|||
hotkeys.hh
|
||||
input_dispatcher.hh
|
||||
k_merge_tree.h
|
||||
lnav_config.hh
|
||||
lnav_config_fwd.hh
|
||||
log_actions.hh
|
||||
log_data_helper.hh
|
||||
log_data_table.hh
|
||||
|
@ -410,7 +407,6 @@ add_library(
|
|||
sql_help.hh
|
||||
sql_util.hh
|
||||
strong_int.hh
|
||||
string_attr_type.hh
|
||||
sysclip.hh
|
||||
sysclip.cfg.hh
|
||||
term_extra.hh
|
||||
|
|
|
@ -154,11 +154,8 @@ dist_noinst_DATA = \
|
|||
|
||||
noinst_HEADERS = \
|
||||
all_logs_vtab.hh \
|
||||
ansi_scrubber.hh \
|
||||
archive_manager.hh \
|
||||
archive_manager.cfg.hh \
|
||||
attr_line.hh \
|
||||
auto_mem.hh \
|
||||
big_array.hh \
|
||||
bin2c.hh \
|
||||
bookmarks.hh \
|
||||
|
@ -256,7 +253,6 @@ noinst_HEADERS = \
|
|||
sqlite-extension-func.hh \
|
||||
styling.hh \
|
||||
statusview_curses.hh \
|
||||
string_attr_type.hh \
|
||||
strong_int.hh \
|
||||
sysclip.hh \
|
||||
sysclip.cfg.hh \
|
||||
|
@ -306,9 +302,7 @@ THIRD_PARTY_SRCS = \
|
|||
libdiag_a_SOURCES = \
|
||||
$(THIRD_PARTY_SRCS) \
|
||||
all_logs_vtab.cc \
|
||||
ansi_scrubber.cc \
|
||||
archive_manager.cc \
|
||||
attr_line.cc \
|
||||
bookmarks.cc \
|
||||
bottom_status_source.cc \
|
||||
collation-functions.cc \
|
||||
|
@ -374,7 +368,6 @@ libdiag_a_SOURCES = \
|
|||
sqlite-extension-func.cc \
|
||||
statusview_curses.cc \
|
||||
string-extension-functions.cc \
|
||||
string_attr_type.cc \
|
||||
styling.cc \
|
||||
text_format.cc \
|
||||
textfile_sub_source.cc \
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "all_logs_vtab.hh"
|
||||
|
||||
#include "config.h"
|
||||
#include "string_attr_type.hh"
|
||||
#include "base/attr_line.hh"
|
||||
|
||||
static auto intern_lifetime = intern_string::get_table_lifetime();
|
||||
|
||||
|
|
|
@ -40,8 +40,8 @@
|
|||
|
||||
#include "archive_manager.cfg.hh"
|
||||
#include "archive_manager.hh"
|
||||
#include "auto_mem.hh"
|
||||
#include "base/auto_fd.hh"
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/fs_util.hh"
|
||||
#include "base/humanize.hh"
|
||||
#include "base/injector.hh"
|
||||
|
@ -227,8 +227,10 @@ copy_data(const std::string& filename,
|
|||
FMT_STRING("available space on disk ({}) is below the "
|
||||
"minimum-free threshold ({}). Unable to unpack "
|
||||
"'{}' to '{}'"),
|
||||
humanize::file_size(tmp_space.available),
|
||||
humanize::file_size(cfg.amc_min_free_space),
|
||||
humanize::file_size(tmp_space.available,
|
||||
humanize::alignment::none),
|
||||
humanize::file_size(cfg.amc_min_free_space,
|
||||
humanize::alignment::none),
|
||||
entry_path.filename().string(),
|
||||
entry_path.parent_path().string()));
|
||||
}
|
||||
|
@ -240,11 +242,11 @@ copy_data(const std::string& filename,
|
|||
return Ok();
|
||||
}
|
||||
if (r != ARCHIVE_OK) {
|
||||
return Err(
|
||||
fmt::format(FMT_STRING("failed to read file: {} >> {} -- {}"),
|
||||
filename,
|
||||
archive_entry_pathname_utf8(entry),
|
||||
archive_error_string(ar)));
|
||||
return Err(fmt::format(
|
||||
FMT_STRING("failed to extract '{}' from archive '{}' -- {}"),
|
||||
archive_entry_pathname_utf8(entry),
|
||||
filename,
|
||||
archive_error_string(ar)));
|
||||
}
|
||||
r = archive_write_data_block(aw, buff, size, offset);
|
||||
if (r != ARCHIVE_OK) {
|
||||
|
@ -269,7 +271,7 @@ extract(const std::string& filename, const extract_cb& cb)
|
|||
|
||||
fs::create_directories(tmp_path.parent_path(), ec);
|
||||
if (ec) {
|
||||
return Err(fmt::format("Unable to create directory: {} -- {}",
|
||||
return Err(fmt::format("unable to create directory: {} -- {}",
|
||||
tmp_path.parent_path().string(),
|
||||
ec.message()));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
add_library(
|
||||
base STATIC
|
||||
../config.h.in
|
||||
ansi_scrubber.cc
|
||||
attr_line.cc
|
||||
auto_pid.cc
|
||||
date_time_scanner.cc
|
||||
fs_util.cc
|
||||
|
@ -10,14 +12,20 @@ add_library(
|
|||
intern_string.cc
|
||||
is_utf8.cc
|
||||
isc.cc
|
||||
lnav.console.cc
|
||||
lnav.gzip.cc
|
||||
lnav_log.cc
|
||||
network.tcp.cc
|
||||
paths.cc
|
||||
string_attr_type.cc
|
||||
string_util.cc
|
||||
strnatcmp.c
|
||||
time_util.cc
|
||||
|
||||
ansi_scrubber.hh
|
||||
attr_line.hh
|
||||
auto_fd.hh
|
||||
auto_mem.hh
|
||||
auto_pid.hh
|
||||
date_time_scanner.hh
|
||||
enum_util.hh
|
||||
|
@ -32,11 +40,13 @@ add_library(
|
|||
intern_string.hh
|
||||
is_utf8.hh
|
||||
isc.hh
|
||||
lnav.console.hh
|
||||
lrucache.hpp
|
||||
math_util.hh
|
||||
network.tcp.hh
|
||||
paths.hh
|
||||
result.h
|
||||
string_attr_type.hh
|
||||
strnatcmp.h
|
||||
time_util.hh)
|
||||
|
||||
|
|
|
@ -19,7 +19,10 @@ AM_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
|
|||
noinst_LIBRARIES = libbase.a
|
||||
|
||||
noinst_HEADERS = \
|
||||
ansi_scrubber.hh \
|
||||
attr_line.hh \
|
||||
auto_fd.hh \
|
||||
auto_mem.hh \
|
||||
auto_pid.hh \
|
||||
date_time_scanner.hh \
|
||||
enum_util.hh \
|
||||
|
@ -36,6 +39,7 @@ noinst_HEADERS = \
|
|||
is_utf8.hh \
|
||||
isc.hh \
|
||||
lnav_log.hh \
|
||||
lnav.console.hh \
|
||||
lnav.gzip.hh \
|
||||
lrucache.hpp \
|
||||
math_util.hh \
|
||||
|
@ -43,11 +47,14 @@ noinst_HEADERS = \
|
|||
opt_util.hh \
|
||||
paths.hh \
|
||||
result.h \
|
||||
string_attr_type.hh \
|
||||
string_util.hh \
|
||||
strnatcmp.h \
|
||||
time_util.hh
|
||||
|
||||
libbase_a_SOURCES = \
|
||||
ansi_scrubber.cc \
|
||||
attr_line.cc \
|
||||
auto_pid.cc \
|
||||
date_time_scanner.cc \
|
||||
fs_util.cc \
|
||||
|
@ -57,10 +64,12 @@ libbase_a_SOURCES = \
|
|||
intern_string.cc \
|
||||
is_utf8.cc \
|
||||
isc.cc \
|
||||
lnav.console.cc \
|
||||
lnav.gzip.cc \
|
||||
lnav_log.cc \
|
||||
network.tcp.cc \
|
||||
paths.cc \
|
||||
string_attr_type.cc \
|
||||
string_util.cc \
|
||||
strnatcmp.c \
|
||||
time_util.cc
|
||||
|
|
|
@ -61,7 +61,7 @@ scrub_ansi_string(std::string& str, string_attrs_t& sa)
|
|||
attr_t attrs = 0;
|
||||
auto bg = nonstd::optional<int>();
|
||||
auto fg = nonstd::optional<int>();
|
||||
auto role = nonstd::optional<int>();
|
||||
auto role = nonstd::optional<role_t>();
|
||||
size_t lpc;
|
||||
|
||||
switch (pi.get_substr_start(&caps[2])[0]) {
|
||||
|
@ -138,8 +138,10 @@ scrub_ansi_string(std::string& str, string_attrs_t& sa)
|
|||
int role_int;
|
||||
|
||||
if (sscanf(&(str[caps[1].c_begin]), "%d", &role_int) == 1) {
|
||||
if (role_int >= 0 && role_int < view_colors::VCR__MAX) {
|
||||
role = role_int;
|
||||
role_t role_tmp = (role_t) role_int;
|
||||
if (role_tmp > role_t::VCR_NONE
|
||||
&& role_tmp < role_t::VCR__MAX) {
|
||||
role = role_tmp;
|
||||
has_attrs = true;
|
||||
}
|
||||
}
|
||||
|
@ -158,16 +160,15 @@ scrub_ansi_string(std::string& str, string_attrs_t& sa)
|
|||
lr.lr_start = caps[0].c_begin;
|
||||
lr.lr_end = -1;
|
||||
if (attrs) {
|
||||
sa.emplace_back(lr, view_curses::VC_STYLE.value(attrs));
|
||||
sa.emplace_back(lr, VC_STYLE.value(attrs));
|
||||
}
|
||||
role | [&lr, &sa](int r) {
|
||||
sa.emplace_back(lr, view_curses::VC_ROLE.value(r));
|
||||
};
|
||||
role |
|
||||
[&lr, &sa](role_t r) { sa.emplace_back(lr, VC_ROLE.value(r)); };
|
||||
fg | [&lr, &sa](int color) {
|
||||
sa.emplace_back(lr, view_curses::VC_FOREGROUND.value(color));
|
||||
sa.emplace_back(lr, VC_FOREGROUND.value(color));
|
||||
};
|
||||
bg | [&lr, &sa](int color) {
|
||||
sa.emplace_back(lr, view_curses::VC_BACKGROUND.value(color));
|
||||
sa.emplace_back(lr, VC_BACKGROUND.value(color));
|
||||
};
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
#include "ansi_scrubber.hh"
|
||||
#include "auto_mem.hh"
|
||||
#include "config.h"
|
||||
#include "view_curses.hh"
|
||||
#include "lnav_log.hh"
|
||||
|
||||
attr_line_t&
|
||||
attr_line_t::with_ansi_string(const char* str, ...)
|
||||
|
@ -257,21 +257,49 @@ attr_line_t::apply_hide()
|
|||
struct line_range& lr = sattr.sa_range;
|
||||
|
||||
std::for_each(sa.begin(), sa.end(), [&](string_attr& attr) {
|
||||
if (attr.sa_type == &view_curses::VC_STYLE
|
||||
&& lr.contains(attr.sa_range)) {
|
||||
if (attr.sa_type == &VC_STYLE && lr.contains(attr.sa_range)) {
|
||||
attr.sa_type = &SA_REMOVED;
|
||||
}
|
||||
});
|
||||
|
||||
this->al_string.replace(lr.lr_start, lr.length(), "\xE2\x8B\xAE");
|
||||
shift_string_attrs(sa, lr.lr_start + 1, -(lr.length() - 3));
|
||||
sattr.sa_type = &view_curses::VC_ROLE;
|
||||
sattr.sa_value = view_colors::VCR_HIDDEN;
|
||||
sattr.sa_type = &VC_ROLE;
|
||||
sattr.sa_value = role_t::VCR_HIDDEN;
|
||||
lr.lr_end = lr.lr_start + 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attr_line_t&
|
||||
attr_line_t::rtrim()
|
||||
{
|
||||
auto index = this->al_string.length();
|
||||
|
||||
for (; index > 0; index--) {
|
||||
if (!isspace(this->al_string[index - 1])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index > 0 && index < this->al_string.length()) {
|
||||
this->erase(index);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
attr_line_t&
|
||||
attr_line_t::erase(size_t pos, size_t len)
|
||||
{
|
||||
if (len == std::string::npos) {
|
||||
len = this->al_string.size() - pos;
|
||||
}
|
||||
this->al_string.erase(pos, len);
|
||||
|
||||
shift_string_attrs(this->al_attrs, pos, -((int32_t) len));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
line_range
|
||||
line_range::intersection(const line_range& other) const
|
||||
{
|
||||
|
@ -290,13 +318,14 @@ line_range::intersection(const line_range& other) const
|
|||
line_range&
|
||||
line_range::shift(int32_t start, int32_t amount)
|
||||
{
|
||||
if (this->lr_start >= start) {
|
||||
if (start <= this->lr_start) {
|
||||
this->lr_start = std::max(0, this->lr_start + amount);
|
||||
}
|
||||
if (this->lr_end != -1 && start <= this->lr_end) {
|
||||
this->lr_end += amount;
|
||||
if (this->lr_end < this->lr_start) {
|
||||
this->lr_end = this->lr_start;
|
||||
if (this->lr_end != -1) {
|
||||
this->lr_end = std::max(0, this->lr_end + amount);
|
||||
}
|
||||
} else if (this->lr_end != -1) {
|
||||
if (start < this->lr_end) {
|
||||
this->lr_end = std::max(this->lr_start, this->lr_end + amount);
|
||||
}
|
||||
}
|
||||
|
|
@ -38,10 +38,10 @@
|
|||
|
||||
#include <limits.h>
|
||||
|
||||
#include "base/intern_string.hh"
|
||||
#include "base/lnav_log.hh"
|
||||
#include "base/string_util.hh"
|
||||
#include "fmt/format.h"
|
||||
#include "intern_string.hh"
|
||||
#include "string_attr_type.hh"
|
||||
#include "string_util.hh"
|
||||
|
||||
/**
|
||||
* Encapsulates a range in a string.
|
||||
|
@ -137,18 +137,8 @@ struct line_range {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Container for attribute values for a substring.
|
||||
*/
|
||||
typedef union {
|
||||
const void* sav_ptr;
|
||||
int64_t sav_int;
|
||||
} string_attr_value_t;
|
||||
|
||||
struct string_attr {
|
||||
string_attr(
|
||||
const struct line_range& lr,
|
||||
const std::pair<const string_attr_type_base*, string_attr_value>& value)
|
||||
string_attr(const struct line_range& lr, const string_attr_pair& value)
|
||||
: sa_range(lr), sa_type(value.first), sa_value(value.second)
|
||||
{
|
||||
}
|
||||
|
@ -444,9 +434,7 @@ public:
|
|||
}
|
||||
|
||||
template<typename S>
|
||||
attr_line_t& append(
|
||||
S str,
|
||||
const std::pair<const string_attr_type_base*, string_attr_value>& value)
|
||||
attr_line_t& append(S str, const string_attr_pair& value)
|
||||
{
|
||||
size_t start_len = this->al_string.length();
|
||||
|
||||
|
@ -459,6 +447,63 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
attr_line_t& append(const std::pair<S, string_attr_pair>& value)
|
||||
{
|
||||
size_t start_len = this->al_string.length();
|
||||
|
||||
this->al_string.append(std::move(value.first));
|
||||
|
||||
line_range lr{(int) start_len, (int) this->al_string.length()};
|
||||
|
||||
this->al_attrs.emplace_back(lr, value.second);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
attr_line_t& append_quoted(const std::pair<S, string_attr_pair>& value)
|
||||
{
|
||||
this->al_string.append("\u201c");
|
||||
|
||||
size_t start_len = this->al_string.length();
|
||||
|
||||
this->al_string.append(std::move(value.first));
|
||||
|
||||
line_range lr{(int) start_len, (int) this->al_string.length()};
|
||||
|
||||
this->al_attrs.emplace_back(lr, value.second);
|
||||
|
||||
this->al_string.append("\u201d");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
attr_line_t& append_quoted(const intern_string_t str)
|
||||
{
|
||||
this->al_string.append("\u201c");
|
||||
this->al_string.append(str.get(), str.size());
|
||||
this->al_string.append("\u201d");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
attr_line_t& append_quoted(S s)
|
||||
{
|
||||
this->al_string.append("\u201c");
|
||||
this->al_string.append(std::move(s));
|
||||
this->al_string.append("\u201d");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
attr_line_t& append(const intern_string_t str)
|
||||
{
|
||||
this->al_string.append(str.get(), str.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
attr_line_t& append(S str)
|
||||
{
|
||||
|
@ -466,6 +511,14 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
attr_line_t& append(fmt::string_view format_str, const Args&... args)
|
||||
{
|
||||
this->template append(fmt::vformat(
|
||||
format_str, fmt::make_args_checked<Args...>(format_str, args...)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
attr_line_t& append(const char* str, size_t len)
|
||||
{
|
||||
this->al_string.append(str, len);
|
||||
|
@ -507,14 +560,9 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
attr_line_t& erase(size_t pos, size_t len = std::string::npos)
|
||||
{
|
||||
this->al_string.erase(pos, len);
|
||||
attr_line_t& erase(size_t pos, size_t len = std::string::npos);
|
||||
|
||||
shift_string_attrs(this->al_attrs, pos, -((int32_t) len));
|
||||
|
||||
return *this;
|
||||
}
|
||||
attr_line_t& rtrim();
|
||||
|
||||
attr_line_t& erase_utf8_chars(size_t start)
|
||||
{
|
||||
|
@ -548,7 +596,8 @@ public:
|
|||
return this->al_string.substr(lr.lr_start, lr.sublen(this->al_string));
|
||||
}
|
||||
|
||||
string_fragment to_string_fragment(string_attrs_t::const_iterator iter)
|
||||
string_fragment to_string_fragment(
|
||||
string_attrs_t::const_iterator iter) const
|
||||
{
|
||||
return string_fragment(this->al_string.c_str(),
|
||||
iter->sa_range.lr_start,
|
||||
|
@ -571,6 +620,11 @@ public:
|
|||
return this->length() == 0;
|
||||
}
|
||||
|
||||
bool blank() const
|
||||
{
|
||||
return is_blank(this->al_string);
|
||||
}
|
||||
|
||||
/** Clear the string and the attributes for the string. */
|
||||
attr_line_t& clear()
|
||||
{
|
||||
|
@ -584,11 +638,18 @@ public:
|
|||
|
||||
void split_lines(std::vector<attr_line_t>& lines) const;
|
||||
|
||||
std::vector<attr_line_t> split_lines() const
|
||||
{
|
||||
std::vector<attr_line_t> retval;
|
||||
|
||||
this->split_lines(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
size_t nearest_text(size_t x) const;
|
||||
|
||||
void apply_hide();
|
||||
|
||||
private:
|
||||
const static size_t RESERVE_SIZE = 128;
|
||||
|
||||
std::string al_string;
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
#include "base/result.h"
|
||||
|
||||
typedef void (*free_func_t)(void*);
|
||||
using free_func_t = void (*)(void*);
|
||||
|
||||
/**
|
||||
* Resource management class for memory allocated by a custom allocator.
|
|
@ -108,5 +108,19 @@ build_path(const std::vector<ghc::filesystem::path>& paths)
|
|||
return retval;
|
||||
}
|
||||
|
||||
Result<struct stat, std::string>
|
||||
stat_file(const ghc::filesystem::path& path)
|
||||
{
|
||||
struct stat retval;
|
||||
|
||||
if (statp(path, &retval) == 0) {
|
||||
return Ok(retval);
|
||||
}
|
||||
|
||||
return Err(fmt::format(FMT_STRING("failed to find file: {} -- {}"),
|
||||
path.string(),
|
||||
strerror(errno)));
|
||||
}
|
||||
|
||||
} // namespace filesystem
|
||||
} // namespace lnav
|
||||
|
|
|
@ -62,6 +62,8 @@ Result<auto_fd, std::string> open_file(const ghc::filesystem::path& path,
|
|||
int flags,
|
||||
mode_t mode);
|
||||
|
||||
Result<struct stat, std::string> stat_file(const ghc::filesystem::path& path);
|
||||
|
||||
Result<std::pair<ghc::filesystem::path, auto_fd>, std::string> open_temp_file(
|
||||
const ghc::filesystem::path& pattern);
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
namespace humanize {
|
||||
|
||||
std::string
|
||||
file_size(file_ssize_t value)
|
||||
file_size(file_ssize_t value, alignment align)
|
||||
{
|
||||
static const double LN1024 = log(1024.0);
|
||||
static const std::vector<const char*> UNITS = {
|
||||
|
@ -56,13 +56,21 @@ file_size(file_ssize_t value)
|
|||
}
|
||||
|
||||
if (value == 0) {
|
||||
return "0.0 B";
|
||||
switch (align) {
|
||||
case alignment::none:
|
||||
return "0B";
|
||||
case alignment::columnar:
|
||||
return "0.0 B";
|
||||
}
|
||||
}
|
||||
|
||||
auto exp
|
||||
= floor(std::min(log(value) / LN1024, (double) (UNITS.size() - 1)));
|
||||
auto divisor = pow(1024, exp);
|
||||
|
||||
if (align == alignment::none && divisor <= 1) {
|
||||
return fmt::format(FMT_STRING("{}B"), value, UNITS[exp]);
|
||||
}
|
||||
return fmt::format(FMT_STRING("{:.1f}{}B"),
|
||||
divisor == 0 ? value : value / divisor,
|
||||
UNITS[exp]);
|
||||
|
|
|
@ -36,11 +36,16 @@
|
|||
|
||||
TEST_CASE("humanize::file_size")
|
||||
{
|
||||
CHECK(humanize::file_size(0) == "0.0 B");
|
||||
CHECK(humanize::file_size(1) == "1.0 B");
|
||||
CHECK(humanize::file_size(1024) == "1.0KB");
|
||||
CHECK(humanize::file_size(1500) == "1.5KB");
|
||||
CHECK(humanize::file_size(55LL * 784LL * 1024LL * 1024LL) == "42.1GB");
|
||||
CHECK(humanize::file_size(-1LL) == "Unknown");
|
||||
CHECK(humanize::file_size(std::numeric_limits<int64_t>::max()) == "8.0EB");
|
||||
CHECK(humanize::file_size(0, humanize::alignment::columnar) == "0.0 B");
|
||||
CHECK(humanize::file_size(1, humanize::alignment::columnar) == "1.0 B");
|
||||
CHECK(humanize::file_size(1024, humanize::alignment::columnar) == "1.0KB");
|
||||
CHECK(humanize::file_size(1500, humanize::alignment::columnar) == "1.5KB");
|
||||
CHECK(humanize::file_size(55LL * 784LL * 1024LL * 1024LL,
|
||||
humanize::alignment::columnar)
|
||||
== "42.1GB");
|
||||
CHECK(humanize::file_size(-1LL, humanize::alignment::columnar)
|
||||
== "Unknown");
|
||||
CHECK(humanize::file_size(std::numeric_limits<int64_t>::max(),
|
||||
humanize::alignment::columnar)
|
||||
== "8.0EB");
|
||||
}
|
||||
|
|
|
@ -38,13 +38,18 @@
|
|||
|
||||
namespace humanize {
|
||||
|
||||
enum class alignment {
|
||||
none,
|
||||
columnar,
|
||||
};
|
||||
|
||||
/**
|
||||
* Format the given size as a human-friendly string.
|
||||
*
|
||||
* @param value The value to format.
|
||||
* @return The formatted string.
|
||||
*/
|
||||
std::string file_size(file_ssize_t value);
|
||||
std::string file_size(file_ssize_t value, alignment align);
|
||||
|
||||
const std::string& sparkline(double value, nonstd::optional<double> upper);
|
||||
|
||||
|
|
|
@ -0,0 +1,265 @@
|
|||
/**
|
||||
* Copyright (c) 2022, Timothy Stack
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* * Neither the name of Timothy Stack nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* 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
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "lnav.console.hh"
|
||||
|
||||
#include "config.h"
|
||||
#include "fmt/color.h"
|
||||
#include "view_curses.hh"
|
||||
|
||||
namespace lnav {
|
||||
namespace console {
|
||||
|
||||
user_message
|
||||
user_message::error(const attr_line_t& al)
|
||||
{
|
||||
user_message retval;
|
||||
|
||||
retval.um_level = level::error;
|
||||
retval.um_message.append(al);
|
||||
return retval;
|
||||
}
|
||||
|
||||
user_message
|
||||
user_message::info(const attr_line_t& al)
|
||||
{
|
||||
user_message retval;
|
||||
|
||||
retval.um_level = level::info;
|
||||
retval.um_message.append(al);
|
||||
return retval;
|
||||
}
|
||||
|
||||
user_message
|
||||
user_message::ok(const attr_line_t& al)
|
||||
{
|
||||
user_message retval;
|
||||
|
||||
retval.um_level = level::ok;
|
||||
retval.um_message.append(al);
|
||||
return retval;
|
||||
}
|
||||
|
||||
user_message
|
||||
user_message::warning(const attr_line_t& al)
|
||||
{
|
||||
user_message retval;
|
||||
|
||||
retval.um_level = level::warning;
|
||||
retval.um_message.append(al);
|
||||
return retval;
|
||||
}
|
||||
|
||||
attr_line_t
|
||||
user_message::to_attr_line(std::set<render_flags> flags) const
|
||||
{
|
||||
attr_line_t retval;
|
||||
|
||||
if (flags.count(render_flags::prefix)) {
|
||||
switch (this->um_level) {
|
||||
case level::ok:
|
||||
retval.append(lnav::roles::ok("\u2714 "));
|
||||
break;
|
||||
case level::info:
|
||||
retval.append(lnav::roles::status("\u24d8 info")).append(": ");
|
||||
break;
|
||||
case level::warning:
|
||||
retval.append(lnav::roles::warning("\u26a0 warning"))
|
||||
.append(": ");
|
||||
break;
|
||||
case level::error:
|
||||
retval.append(lnav::roles::error("\u2718 error")).append(": ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
retval.append(this->um_message).append("\n");
|
||||
if (!this->um_reason.empty()) {
|
||||
bool first_line = true;
|
||||
for (const auto& line : this->um_reason.split_lines()) {
|
||||
attr_line_t prefix;
|
||||
|
||||
if (first_line) {
|
||||
prefix.append(lnav::roles::error(" reason")).append(": ");
|
||||
first_line = false;
|
||||
} else {
|
||||
prefix.append(lnav::roles::error(" | "));
|
||||
}
|
||||
retval.append(prefix).append(line).append("\n");
|
||||
}
|
||||
}
|
||||
if (!this->um_snippets.empty()) {
|
||||
for (const auto& snip : this->um_snippets) {
|
||||
attr_line_t header;
|
||||
|
||||
header.append(lnav::roles::comment(" --> "))
|
||||
.append(lnav::roles::file(snip.s_source));
|
||||
if (snip.s_line > 0) {
|
||||
header.append(":").append(FMT_STRING("{}"), snip.s_line);
|
||||
if (snip.s_column > 0) {
|
||||
header.append(":").append(FMT_STRING("{}"), snip.s_column);
|
||||
}
|
||||
}
|
||||
retval.append(header).append("\n");
|
||||
if (!snip.s_content.blank()) {
|
||||
for (const auto& line : snip.s_content.split_lines()) {
|
||||
retval.append(lnav::roles::comment(" | "))
|
||||
.append(line)
|
||||
.append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!this->um_notes.empty()) {
|
||||
bool first_line = true;
|
||||
for (const auto& note : this->um_notes) {
|
||||
for (const auto& line : note.split_lines()) {
|
||||
attr_line_t prefix;
|
||||
|
||||
if (first_line) {
|
||||
prefix.append(lnav::roles::comment(" = note")).append(": ");
|
||||
first_line = false;
|
||||
} else {
|
||||
prefix.append(" ");
|
||||
}
|
||||
|
||||
retval.append(prefix).append(line).append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!this->um_help.empty()) {
|
||||
bool first_line = true;
|
||||
for (const auto& line : this->um_help.split_lines()) {
|
||||
attr_line_t prefix;
|
||||
|
||||
if (first_line) {
|
||||
prefix.append(lnav::roles::comment(" = help")).append(": ");
|
||||
first_line = false;
|
||||
} else {
|
||||
prefix.append(" ");
|
||||
}
|
||||
|
||||
retval.append(prefix).append(line).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
println(FILE* file, const attr_line_t& al)
|
||||
{
|
||||
const auto& str = al.get_string();
|
||||
|
||||
if (!isatty(fileno(file))) {
|
||||
fmt::print(file, "{}\n", str);
|
||||
return;
|
||||
}
|
||||
|
||||
string_attrs_t style_attrs;
|
||||
|
||||
for (const auto& sa : al.get_attrs()) {
|
||||
if (sa.sa_type != &VC_ROLE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
style_attrs.emplace_back(sa);
|
||||
}
|
||||
|
||||
std::sort(style_attrs.begin(), style_attrs.end(), [](auto lhs, auto rhs) {
|
||||
return lhs.sa_range < rhs.sa_range;
|
||||
});
|
||||
|
||||
auto start = size_t{0};
|
||||
for (const auto& attr : style_attrs) {
|
||||
fmt::print(
|
||||
file, "{}", str.substr(start, attr.sa_range.lr_start - start));
|
||||
if (attr.sa_type == &VC_ROLE) {
|
||||
auto saw = string_attr_wrapper<role_t>(&attr);
|
||||
auto role = saw.get();
|
||||
auto line_style = fmt::text_style();
|
||||
|
||||
switch (role) {
|
||||
case role_t::VCR_ERROR:
|
||||
line_style = fmt::fg(fmt::terminal_color::red);
|
||||
break;
|
||||
case role_t::VCR_WARNING:
|
||||
line_style = fmt::fg(fmt::terminal_color::yellow);
|
||||
break;
|
||||
case role_t::VCR_COMMENT:
|
||||
line_style = fmt::fg(fmt::terminal_color::cyan);
|
||||
break;
|
||||
case role_t::VCR_OK:
|
||||
line_style = fmt::emphasis::bold
|
||||
| fmt::fg(fmt::terminal_color::red);
|
||||
break;
|
||||
case role_t::VCR_STATUS:
|
||||
line_style = fmt::emphasis::bold
|
||||
| fmt::fg(fmt::terminal_color::magenta);
|
||||
break;
|
||||
case role_t::VCR_VARIABLE:
|
||||
line_style = fmt::emphasis::underline;
|
||||
break;
|
||||
case role_t::VCR_SYMBOL:
|
||||
case role_t::VCR_NUMBER:
|
||||
case role_t::VCR_FILE:
|
||||
line_style = fmt::emphasis::bold;
|
||||
break;
|
||||
case role_t::VCR_H1:
|
||||
case role_t::VCR_H2:
|
||||
case role_t::VCR_H3:
|
||||
case role_t::VCR_H4:
|
||||
case role_t::VCR_H5:
|
||||
case role_t::VCR_H6:
|
||||
line_style = fmt::emphasis::underline;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fmt::print(
|
||||
file,
|
||||
line_style,
|
||||
"{}",
|
||||
str.substr(attr.sa_range.lr_start, attr.sa_range.length()));
|
||||
}
|
||||
start = attr.sa_range.lr_end;
|
||||
}
|
||||
fmt::print(file, "{}\n", str.substr(start));
|
||||
}
|
||||
|
||||
void
|
||||
print(FILE* file, const user_message& um)
|
||||
{
|
||||
println(file, um.to_attr_line().rtrim());
|
||||
}
|
||||
|
||||
} // namespace console
|
||||
} // namespace lnav
|
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
* Copyright (c) 2022, Timothy Stack
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* * Neither the name of Timothy Stack nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* 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
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lnav_console_hh
|
||||
#define lnav_console_hh
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "base/attr_line.hh"
|
||||
|
||||
namespace lnav {
|
||||
namespace console {
|
||||
|
||||
void println(FILE* file, const attr_line_t& al);
|
||||
|
||||
struct snippet {
|
||||
static snippet from(std::string src, const attr_line_t& content)
|
||||
{
|
||||
snippet retval;
|
||||
|
||||
retval.s_source = std::move(src);
|
||||
retval.s_content = content;
|
||||
return retval;
|
||||
}
|
||||
|
||||
snippet& with_line(int32_t line)
|
||||
{
|
||||
this->s_line = line;
|
||||
return *this;
|
||||
}
|
||||
|
||||
snippet& with_column(int32_t column)
|
||||
{
|
||||
this->s_column = column;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string s_source;
|
||||
int32_t s_line{0};
|
||||
int32_t s_column{0};
|
||||
attr_line_t s_content;
|
||||
};
|
||||
|
||||
struct user_message {
|
||||
enum class level {
|
||||
ok,
|
||||
info,
|
||||
warning,
|
||||
error,
|
||||
};
|
||||
|
||||
static user_message error(const attr_line_t& al);
|
||||
|
||||
static user_message warning(const attr_line_t& al);
|
||||
|
||||
static user_message info(const attr_line_t& al);
|
||||
|
||||
static user_message ok(const attr_line_t& al);
|
||||
|
||||
user_message& with_reason(const attr_line_t& al)
|
||||
{
|
||||
this->um_reason = al;
|
||||
this->um_reason.rtrim();
|
||||
return *this;
|
||||
}
|
||||
|
||||
user_message& with_errno_reason()
|
||||
{
|
||||
this->um_reason = strerror(errno);
|
||||
return *this;
|
||||
}
|
||||
|
||||
user_message& with_snippet(const snippet& sn)
|
||||
{
|
||||
this->um_snippets.emplace_back(sn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
user_message& with_snippets(std::vector<snippet> snippets)
|
||||
{
|
||||
this->um_snippets.insert(this->um_snippets.end(),
|
||||
std::make_move_iterator(snippets.begin()),
|
||||
std::make_move_iterator(snippets.end()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
user_message& with_note(const attr_line_t& al)
|
||||
{
|
||||
this->um_notes.emplace_back(al);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
user_message& with_help(const attr_line_t& al)
|
||||
{
|
||||
this->um_help = al;
|
||||
this->um_help.rtrim();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
enum class render_flags {
|
||||
prefix,
|
||||
};
|
||||
|
||||
attr_line_t to_attr_line(std::set<render_flags> flags
|
||||
= {render_flags::prefix}) const;
|
||||
|
||||
level um_level{level::ok};
|
||||
attr_line_t um_message;
|
||||
std::vector<snippet> um_snippets;
|
||||
attr_line_t um_reason;
|
||||
std::vector<attr_line_t> um_notes;
|
||||
attr_line_t um_help;
|
||||
};
|
||||
|
||||
void print(FILE* file, const user_message& um);
|
||||
|
||||
} // namespace console
|
||||
} // namespace lnav
|
||||
|
||||
#endif
|
|
@ -38,3 +38,10 @@ string_attr_type<const intern_string_t> SA_FORMAT("format");
|
|||
string_attr_type<void> SA_REMOVED("removed");
|
||||
string_attr_type<std::string> SA_INVALID("invalid");
|
||||
string_attr_type<std::string> SA_ERROR("error");
|
||||
|
||||
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<int64_t> VC_GRAPHIC("graphic");
|
||||
string_attr_type<int64_t> VC_FOREGROUND("foreground");
|
||||
string_attr_type<int64_t> VC_BACKGROUND("background");
|
|
@ -0,0 +1,346 @@
|
|||
/**
|
||||
* Copyright (c) 2020, Timothy Stack
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* * Neither the name of Timothy Stack nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* 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
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lnav_string_attr_type_hh
|
||||
#define lnav_string_attr_type_hh
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "base/intern_string.hh"
|
||||
#include "mapbox/variant.hpp"
|
||||
|
||||
class logfile;
|
||||
struct bookmark_metadata;
|
||||
|
||||
/** Roles that can be mapped to curses attributes using attrs_for_role() */
|
||||
enum class role_t : int32_t {
|
||||
VCR_NONE = -1,
|
||||
|
||||
VCR_TEXT, /*< Raw text. */
|
||||
VCR_IDENTIFIER,
|
||||
VCR_SEARCH, /*< A search hit. */
|
||||
VCR_OK,
|
||||
VCR_ERROR, /*< An error message. */
|
||||
VCR_WARNING, /*< A warning message. */
|
||||
VCR_ALT_ROW, /*< Highlight for alternating rows in a list */
|
||||
VCR_HIDDEN,
|
||||
VCR_ADJUSTED_TIME,
|
||||
VCR_SKEWED_TIME,
|
||||
VCR_OFFSET_TIME,
|
||||
VCR_INVALID_MSG,
|
||||
VCR_STATUS, /*< Normal status line text. */
|
||||
VCR_WARN_STATUS,
|
||||
VCR_ALERT_STATUS, /*< Alert status line text. */
|
||||
VCR_ACTIVE_STATUS, /*< */
|
||||
VCR_ACTIVE_STATUS2, /*< */
|
||||
VCR_STATUS_TITLE,
|
||||
VCR_STATUS_SUBTITLE,
|
||||
VCR_STATUS_STITCH_TITLE_TO_SUB,
|
||||
VCR_STATUS_STITCH_SUB_TO_TITLE,
|
||||
VCR_STATUS_STITCH_SUB_TO_NORMAL,
|
||||
VCR_STATUS_STITCH_NORMAL_TO_SUB,
|
||||
VCR_STATUS_STITCH_TITLE_TO_NORMAL,
|
||||
VCR_STATUS_STITCH_NORMAL_TO_TITLE,
|
||||
VCR_STATUS_TITLE_HOTKEY,
|
||||
VCR_STATUS_DISABLED_TITLE,
|
||||
VCR_STATUS_HOTKEY,
|
||||
VCR_INACTIVE_STATUS,
|
||||
VCR_INACTIVE_ALERT_STATUS,
|
||||
VCR_SCROLLBAR,
|
||||
VCR_SCROLLBAR_ERROR,
|
||||
VCR_SCROLLBAR_WARNING,
|
||||
VCR_FOCUSED,
|
||||
VCR_DISABLED_FOCUSED,
|
||||
VCR_POPUP,
|
||||
VCR_COLOR_HINT,
|
||||
|
||||
VCR_KEYWORD,
|
||||
VCR_STRING,
|
||||
VCR_COMMENT,
|
||||
VCR_DOC_DIRECTIVE,
|
||||
VCR_VARIABLE,
|
||||
VCR_SYMBOL,
|
||||
VCR_NUMBER,
|
||||
VCR_RE_SPECIAL,
|
||||
VCR_RE_REPEAT,
|
||||
VCR_FILE,
|
||||
|
||||
VCR_DIFF_DELETE, /*< Deleted line in a diff. */
|
||||
VCR_DIFF_ADD, /*< Added line in a diff. */
|
||||
VCR_DIFF_SECTION, /*< Section marker in a diff. */
|
||||
|
||||
VCR_LOW_THRESHOLD,
|
||||
VCR_MED_THRESHOLD,
|
||||
VCR_HIGH_THRESHOLD,
|
||||
|
||||
VCR_H1,
|
||||
VCR_H2,
|
||||
VCR_H3,
|
||||
VCR_H4,
|
||||
VCR_H5,
|
||||
VCR_H6,
|
||||
|
||||
VCR__MAX
|
||||
};
|
||||
|
||||
using string_attr_value = mapbox::util::variant<int64_t,
|
||||
role_t,
|
||||
const intern_string_t,
|
||||
std::string,
|
||||
std::shared_ptr<logfile>,
|
||||
bookmark_metadata*>;
|
||||
|
||||
class string_attr_type_base {
|
||||
public:
|
||||
explicit string_attr_type_base(const char* name) noexcept : sat_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
const char* const sat_name;
|
||||
};
|
||||
|
||||
using string_attr_pair
|
||||
= std::pair<const string_attr_type_base*, string_attr_value>;
|
||||
|
||||
template<typename T>
|
||||
class string_attr_type : public string_attr_type_base {
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
explicit string_attr_type(const char* name) noexcept
|
||||
: string_attr_type_base(name)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename U = T>
|
||||
std::enable_if_t<!std::is_void<U>::value, string_attr_pair> value(
|
||||
const U& val) const
|
||||
{
|
||||
return std::make_pair(this, val);
|
||||
}
|
||||
|
||||
template<typename U = T>
|
||||
std::enable_if_t<std::is_void<U>::value, string_attr_pair> value() const
|
||||
{
|
||||
return std::make_pair(this, string_attr_value{});
|
||||
}
|
||||
};
|
||||
|
||||
extern string_attr_type<void> SA_ORIGINAL_LINE;
|
||||
extern string_attr_type<void> SA_BODY;
|
||||
extern string_attr_type<void> SA_HIDDEN;
|
||||
extern string_attr_type<const intern_string_t> SA_FORMAT;
|
||||
extern string_attr_type<void> SA_REMOVED;
|
||||
extern string_attr_type<std::string> SA_INVALID;
|
||||
extern string_attr_type<std::string> SA_ERROR;
|
||||
|
||||
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<int64_t> VC_GRAPHIC;
|
||||
extern string_attr_type<int64_t> VC_FOREGROUND;
|
||||
extern string_attr_type<int64_t> VC_BACKGROUND;
|
||||
|
||||
namespace lnav {
|
||||
namespace roles {
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
error(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_ERROR));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
warning(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_WARNING));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
status(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_STATUS));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
ok(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_OK));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
file(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_FILE));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
symbol(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_SYMBOL));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
keyword(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_KEYWORD));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
variable(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_VARIABLE));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
number(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_NUMBER));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
comment(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_COMMENT));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
h1(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_H1));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
h2(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_H2));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
h3(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_H3));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
h4(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_H4));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
h5(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_H5));
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline std::pair<S, string_attr_pair>
|
||||
h6(S str)
|
||||
{
|
||||
return std::make_pair(std::move(str),
|
||||
VC_ROLE.template value(role_t::VCR_H6));
|
||||
}
|
||||
|
||||
namespace literals {
|
||||
|
||||
inline std::pair<std::string, string_attr_pair> operator"" _symbol(
|
||||
const char* str, std::size_t len)
|
||||
{
|
||||
return std::make_pair(std::string(str, len),
|
||||
VC_ROLE.template value(role_t::VCR_SYMBOL));
|
||||
}
|
||||
|
||||
inline std::pair<std::string, string_attr_pair> operator"" _variable(
|
||||
const char* str, std::size_t len)
|
||||
{
|
||||
return std::make_pair(std::string(str, len),
|
||||
VC_ROLE.template value(role_t::VCR_VARIABLE));
|
||||
}
|
||||
|
||||
inline std::pair<std::string, string_attr_pair> operator"" _h1(const char* str,
|
||||
std::size_t len)
|
||||
{
|
||||
return std::make_pair(std::string(str, len),
|
||||
VC_ROLE.template value(role_t::VCR_H1));
|
||||
}
|
||||
|
||||
inline std::pair<std::string, string_attr_pair> operator"" _h2(const char* str,
|
||||
std::size_t len)
|
||||
{
|
||||
return std::make_pair(std::string(str, len),
|
||||
VC_ROLE.template value(role_t::VCR_H2));
|
||||
}
|
||||
|
||||
inline std::pair<std::string, string_attr_pair> operator"" _h3(const char* str,
|
||||
std::size_t len)
|
||||
{
|
||||
return std::make_pair(std::string(str, len),
|
||||
VC_ROLE.template value(role_t::VCR_H3));
|
||||
}
|
||||
|
||||
} // namespace literals
|
||||
|
||||
} // namespace roles
|
||||
} // namespace lnav
|
||||
|
||||
#endif
|
|
@ -27,6 +27,7 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
|
@ -253,6 +254,13 @@ strtonum(T& num_out, const char* string, size_t len)
|
|||
return retval;
|
||||
}
|
||||
|
||||
bool
|
||||
is_blank(const std::string& str)
|
||||
{
|
||||
return std::all_of(
|
||||
str.begin(), str.end(), [](const auto ch) { return isspace(ch); });
|
||||
}
|
||||
|
||||
template size_t strtonum<long long>(long long& num_out,
|
||||
const char* string,
|
||||
size_t len);
|
||||
|
|
|
@ -188,6 +188,8 @@ utf8_string_length(const std::string& str)
|
|||
|
||||
bool is_url(const char* fn);
|
||||
|
||||
bool is_blank(const std::string& str);
|
||||
|
||||
size_t abbreviate_str(char* str, size_t len, size_t max_len);
|
||||
|
||||
void split_ws(const std::string& str, std::vector<std::string>& toks_out);
|
||||
|
|
|
@ -33,4 +33,53 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
std::set<std::string> bookmark_metadata::KNOWN_TAGS;
|
||||
std::unordered_set<std::string> bookmark_metadata::KNOWN_TAGS;
|
||||
|
||||
void
|
||||
bookmark_metadata::add_tag(const std::string& tag)
|
||||
{
|
||||
if (std::find(this->bm_tags.begin(), this->bm_tags.end(), tag)
|
||||
== this->bm_tags.end())
|
||||
{
|
||||
this->bm_tags.push_back(tag);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
bookmark_metadata::remove_tag(const std::string& tag)
|
||||
{
|
||||
auto iter = std::find(this->bm_tags.begin(), this->bm_tags.end(), tag);
|
||||
bool retval = false;
|
||||
|
||||
if (iter != this->bm_tags.end()) {
|
||||
this->bm_tags.erase(iter);
|
||||
retval = true;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool
|
||||
bookmark_metadata::empty() const
|
||||
{
|
||||
return this->bm_name.empty() && this->bm_comment.empty()
|
||||
&& this->bm_tags.empty();
|
||||
}
|
||||
|
||||
void
|
||||
bookmark_metadata::clear()
|
||||
{
|
||||
this->bm_comment.clear();
|
||||
this->bm_tags.clear();
|
||||
}
|
||||
|
||||
bookmark_type_t*
|
||||
bookmark_type_t::find_type(const std::string& name)
|
||||
{
|
||||
auto iter = std::find_if(type_begin(), type_end(), mark_eq(name));
|
||||
bookmark_type_t* retval = nullptr;
|
||||
|
||||
if (iter != type_end()) {
|
||||
retval = (*iter);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -34,51 +34,26 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/lnav_log.hh"
|
||||
|
||||
struct bookmark_metadata {
|
||||
static std::set<std::string> KNOWN_TAGS;
|
||||
static std::unordered_set<std::string> KNOWN_TAGS;
|
||||
|
||||
std::string bm_name;
|
||||
std::string bm_comment;
|
||||
std::vector<std::string> bm_tags;
|
||||
|
||||
void add_tag(const std::string& tag)
|
||||
{
|
||||
if (std::find(this->bm_tags.begin(), this->bm_tags.end(), tag)
|
||||
== this->bm_tags.end())
|
||||
{
|
||||
this->bm_tags.push_back(tag);
|
||||
}
|
||||
};
|
||||
void add_tag(const std::string& tag);
|
||||
|
||||
bool remove_tag(const std::string& tag)
|
||||
{
|
||||
auto iter = std::find(this->bm_tags.begin(), this->bm_tags.end(), tag);
|
||||
bool retval = false;
|
||||
bool remove_tag(const std::string& tag);
|
||||
|
||||
if (iter != this->bm_tags.end()) {
|
||||
this->bm_tags.erase(iter);
|
||||
retval = true;
|
||||
}
|
||||
return retval;
|
||||
};
|
||||
bool empty() const;
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return this->bm_name.empty() && this->bm_comment.empty()
|
||||
&& this->bm_tags.empty();
|
||||
};
|
||||
|
||||
void clear()
|
||||
{
|
||||
this->bm_comment.clear();
|
||||
this->bm_tags.clear();
|
||||
};
|
||||
void clear();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -96,12 +71,12 @@ struct bookmark_metadata {
|
|||
*/
|
||||
template<typename LineType>
|
||||
class bookmark_vector : public std::vector<LineType> {
|
||||
typedef std::vector<LineType> base_vector;
|
||||
using base_vector = std::vector<LineType>;
|
||||
|
||||
public:
|
||||
typedef typename base_vector::size_type size_type;
|
||||
typedef typename base_vector::iterator iterator;
|
||||
typedef typename base_vector::const_iterator const_iterator;
|
||||
using size_type = typename base_vector::size_type;
|
||||
using iterator = typename base_vector::iterator;
|
||||
using const_iterator = typename base_vector::const_iterator;
|
||||
|
||||
/**
|
||||
* Insert a bookmark into this vector, but only if it is not already in the
|
||||
|
@ -111,11 +86,11 @@ public:
|
|||
*/
|
||||
iterator insert_once(LineType vl)
|
||||
{
|
||||
iterator lb, retval;
|
||||
iterator retval;
|
||||
|
||||
require(vl >= 0);
|
||||
|
||||
lb = std::lower_bound(this->begin(), this->end(), vl);
|
||||
auto lb = std::lower_bound(this->begin(), this->end(), vl);
|
||||
if (lb == this->end() || *lb != vl) {
|
||||
this->insert(lb, vl);
|
||||
retval = this->end();
|
||||
|
@ -132,11 +107,11 @@ public:
|
|||
|
||||
if (stop == LineType(-1)) {
|
||||
return std::make_pair(lb, this->end());
|
||||
} else {
|
||||
auto up = std::upper_bound(this->begin(), this->end(), stop);
|
||||
|
||||
return std::make_pair(lb, up);
|
||||
}
|
||||
|
||||
auto up = std::upper_bound(this->begin(), this->end(), stop);
|
||||
|
||||
return std::make_pair(lb, up);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -164,45 +139,36 @@ public:
|
|||
*/
|
||||
class bookmark_type_t {
|
||||
public:
|
||||
typedef std::vector<bookmark_type_t*>::iterator type_iterator;
|
||||
using type_iterator = std::vector<bookmark_type_t*>::iterator;
|
||||
|
||||
static type_iterator type_begin()
|
||||
{
|
||||
return get_all_types().begin();
|
||||
};
|
||||
}
|
||||
|
||||
static type_iterator type_end()
|
||||
{
|
||||
return get_all_types().end();
|
||||
};
|
||||
}
|
||||
|
||||
static bookmark_type_t* find_type(const std::string& name)
|
||||
{
|
||||
auto iter = find_if(type_begin(), type_end(), mark_eq(name));
|
||||
bookmark_type_t* retval = nullptr;
|
||||
|
||||
if (iter != type_end()) {
|
||||
retval = (*iter);
|
||||
}
|
||||
return retval;
|
||||
};
|
||||
static bookmark_type_t* find_type(const std::string& name);
|
||||
|
||||
static std::vector<bookmark_type_t*>& get_all_types()
|
||||
{
|
||||
static std::vector<bookmark_type_t*> all_types;
|
||||
|
||||
return all_types;
|
||||
};
|
||||
}
|
||||
|
||||
explicit bookmark_type_t(std::string name) : bt_name(std::move(name))
|
||||
{
|
||||
get_all_types().push_back(this);
|
||||
};
|
||||
}
|
||||
|
||||
const std::string& get_name() const
|
||||
{
|
||||
return this->bt_name;
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
struct mark_eq {
|
||||
|
@ -227,7 +193,7 @@ bookmark_vector<LineType>::next(LineType start) const
|
|||
|
||||
require(start >= -1);
|
||||
|
||||
auto ub = upper_bound(this->cbegin(), this->cend(), start);
|
||||
auto ub = std::upper_bound(this->cbegin(), this->cend(), start);
|
||||
if (ub != this->cend()) {
|
||||
retval = *ub;
|
||||
}
|
||||
|
@ -245,7 +211,7 @@ bookmark_vector<LineType>::prev(LineType start) const
|
|||
|
||||
require(start >= 0);
|
||||
|
||||
auto lb = lower_bound(this->cbegin(), this->cend(), start);
|
||||
auto lb = std::lower_bound(this->cbegin(), this->cend(), start);
|
||||
if (lb != this->cbegin()) {
|
||||
lb -= 1;
|
||||
retval = *lb;
|
||||
|
@ -261,7 +227,7 @@ bookmark_vector<LineType>::prev(LineType start) const
|
|||
*/
|
||||
template<typename LineType>
|
||||
struct bookmarks {
|
||||
typedef std::map<const bookmark_type_t*, bookmark_vector<LineType> > type;
|
||||
using type = std::map<const bookmark_type_t*, bookmark_vector<LineType>>;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -158,18 +158,18 @@ void
|
|||
bottom_status_source::update_hits(textview_curses* tc)
|
||||
{
|
||||
status_field& sf = this->bss_fields[BSF_HITS];
|
||||
view_colors::role_t new_role;
|
||||
role_t new_role;
|
||||
|
||||
if (tc->is_searching()) {
|
||||
this->bss_hit_spinner += 1;
|
||||
if (this->bss_hit_spinner % 2) {
|
||||
new_role = view_colors::VCR_ACTIVE_STATUS;
|
||||
new_role = role_t::VCR_ACTIVE_STATUS;
|
||||
} else {
|
||||
new_role = view_colors::VCR_ACTIVE_STATUS2;
|
||||
new_role = role_t::VCR_ACTIVE_STATUS2;
|
||||
}
|
||||
sf.set_cylon(true);
|
||||
} else {
|
||||
new_role = view_colors::VCR_STATUS;
|
||||
new_role = role_t::VCR_STATUS;
|
||||
sf.set_cylon(false);
|
||||
}
|
||||
// this->bss_error.clear();
|
||||
|
@ -186,7 +186,7 @@ bottom_status_source::update_loading(file_off_t off, file_size_t total)
|
|||
|
||||
if (total == 0 || (size_t) off == total) {
|
||||
sf.set_cylon(false);
|
||||
sf.set_role(view_colors::VCR_STATUS);
|
||||
sf.set_role(role_t::VCR_STATUS);
|
||||
if (this->bss_paused) {
|
||||
sf.set_value("\xE2\x80\x96 Paused");
|
||||
} else {
|
||||
|
@ -199,7 +199,7 @@ bottom_status_source::update_loading(file_off_t off, file_size_t total)
|
|||
this->bss_load_percent = pct;
|
||||
|
||||
sf.set_cylon(true);
|
||||
sf.set_role(view_colors::VCR_ACTIVE_STATUS2);
|
||||
sf.set_role(role_t::VCR_ACTIVE_STATUS2);
|
||||
sf.set_value(" Loading %2d%% ", pct);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,9 +85,9 @@ public:
|
|||
void update_loading(file_off_t off, file_size_t total);
|
||||
|
||||
private:
|
||||
status_field bss_prompt{1024, view_colors::VCR_STATUS};
|
||||
status_field bss_error{1024, view_colors::VCR_ALERT_STATUS};
|
||||
status_field bss_line_error{1024, view_colors::VCR_ALERT_STATUS};
|
||||
status_field bss_prompt{1024, role_t::VCR_STATUS};
|
||||
status_field bss_error{1024, role_t::VCR_ALERT_STATUS};
|
||||
status_field bss_line_error{1024, role_t::VCR_ALERT_STATUS};
|
||||
status_field bss_fields[BSF__MAX];
|
||||
int bss_hit_spinner{0};
|
||||
int bss_load_percent{0};
|
||||
|
|
|
@ -31,12 +31,14 @@
|
|||
|
||||
#include "command_executor.hh"
|
||||
|
||||
#include "base/ansi_scrubber.hh"
|
||||
#include "base/fs_util.hh"
|
||||
#include "base/injector.hh"
|
||||
#include "base/string_util.hh"
|
||||
#include "bound_tags.hh"
|
||||
#include "config.h"
|
||||
#include "db_sub_source.hh"
|
||||
#include "help_text_formatter.hh"
|
||||
#include "lnav.hh"
|
||||
#include "lnav_config.hh"
|
||||
#include "lnav_util.hh"
|
||||
|
@ -101,14 +103,14 @@ sql_progress_finished()
|
|||
lnav_data.ld_views[LNV_DB].redo_search();
|
||||
}
|
||||
|
||||
Result<std::string, std::string> execute_from_file(
|
||||
Result<std::string, lnav::console::user_message> execute_from_file(
|
||||
exec_context& ec,
|
||||
const ghc::filesystem::path& path,
|
||||
int line_number,
|
||||
char mode,
|
||||
const std::string& cmdline);
|
||||
|
||||
Result<std::string, std::string>
|
||||
Result<std::string, lnav::console::user_message>
|
||||
execute_command(exec_context& ec, const std::string& cmdline)
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
|
@ -122,15 +124,18 @@ execute_command(exec_context& ec, const std::string& cmdline)
|
|||
|
||||
if ((iter = lnav_commands.find(args[0])) == lnav_commands.end()) {
|
||||
return ec.make_error("unknown command - {}", args[0]);
|
||||
} else {
|
||||
return iter->second->c_func(ec, cmdline, args);
|
||||
}
|
||||
|
||||
ec.ec_current_help = &iter->second->c_help;
|
||||
auto retval = iter->second->c_func(ec, cmdline, args);
|
||||
ec.ec_current_help = nullptr;
|
||||
return retval;
|
||||
}
|
||||
|
||||
return ec.make_error("no command to execute");
|
||||
}
|
||||
|
||||
Result<std::string, std::string>
|
||||
Result<std::string, lnav::console::user_message>
|
||||
execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg)
|
||||
{
|
||||
db_label_source& dls = lnav_data.ld_db_row_source;
|
||||
|
@ -153,7 +158,11 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg)
|
|||
auto cmd_iter = sql_cmd_map->find(args[0]);
|
||||
|
||||
if (cmd_iter != sql_cmd_map->end()) {
|
||||
return cmd_iter->second->c_func(ec, stmt_str, args);
|
||||
ec.ec_current_help = &cmd_iter->second->c_help;
|
||||
auto retval = cmd_iter->second->c_func(ec, stmt_str, args);
|
||||
ec.ec_current_help = nullptr;
|
||||
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,9 +172,12 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg)
|
|||
|
||||
ec.ec_accumulator->clear();
|
||||
|
||||
std::pair<std::string, int> source = ec.ec_source.top();
|
||||
sql_progress_guard progress_guard(
|
||||
sql_progress, sql_progress_finished, source.first, source.second);
|
||||
auto source = ec.ec_source.top();
|
||||
sql_progress_guard progress_guard(sql_progress,
|
||||
sql_progress_finished,
|
||||
source.s_source,
|
||||
source.s_line,
|
||||
source.s_content);
|
||||
gettimeofday(&start_tv, nullptr);
|
||||
retcode = sqlite3_prepare_v2(
|
||||
lnav_data.ld_db.in(), stmt_str.c_str(), -1, stmt.out(), nullptr);
|
||||
|
@ -174,7 +186,8 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg)
|
|||
|
||||
alt_msg = "";
|
||||
return ec.make_error("{}", errmsg);
|
||||
} else if (stmt == nullptr) {
|
||||
}
|
||||
if (stmt == nullptr) {
|
||||
alt_msg = "";
|
||||
return ec.make_error("No statement given");
|
||||
}
|
||||
|
@ -301,8 +314,11 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg)
|
|||
|
||||
log_error("sqlite3_step error code: %d", retcode);
|
||||
errmsg = sqlite3_errmsg(lnav_data.ld_db);
|
||||
if (startswith(errmsg, "lnav-error:")) {
|
||||
return Err(lnav::from_json<lnav::console::user_message>(
|
||||
&errmsg[11]));
|
||||
}
|
||||
return ec.make_error("{}", errmsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -409,7 +425,7 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg)
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
execute_file_contents(exec_context& ec,
|
||||
const ghc::filesystem::path& path,
|
||||
bool multiline)
|
||||
|
@ -490,7 +506,7 @@ execute_file_contents(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
Result<std::string, std::string>
|
||||
Result<std::string, lnav::console::user_message>
|
||||
execute_file(exec_context& ec, const std::string& path_and_args, bool multiline)
|
||||
{
|
||||
available_scripts scripts;
|
||||
|
@ -583,7 +599,7 @@ execute_file(exec_context& ec, const std::string& path_and_args, bool multiline)
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
Result<std::string, std::string>
|
||||
Result<std::string, lnav::console::user_message>
|
||||
execute_from_file(exec_context& ec,
|
||||
const ghc::filesystem::path& path,
|
||||
int line_number,
|
||||
|
@ -591,7 +607,7 @@ execute_from_file(exec_context& ec,
|
|||
const std::string& cmdline)
|
||||
{
|
||||
std::string retval, alt_msg;
|
||||
auto _sg = ec.enter_source(path.string(), line_number);
|
||||
auto _sg = ec.enter_source(path.string(), line_number, cmdline);
|
||||
|
||||
switch (mode) {
|
||||
case ':':
|
||||
|
@ -621,7 +637,7 @@ execute_from_file(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
Result<std::string, std::string>
|
||||
Result<std::string, lnav::console::user_message>
|
||||
execute_any(exec_context& ec, const std::string& cmdline_with_mode)
|
||||
{
|
||||
std::string retval, alt_msg, cmdline = cmdline_with_mode.substr(1);
|
||||
|
@ -663,7 +679,8 @@ execute_any(exec_context& ec, const std::string& cmdline_with_mode)
|
|||
void
|
||||
execute_init_commands(
|
||||
exec_context& ec,
|
||||
std::vector<std::pair<Result<std::string, std::string>, std::string>>& msgs)
|
||||
std::vector<std::pair<Result<std::string, lnav::console::user_message>,
|
||||
std::string>>& msgs)
|
||||
{
|
||||
if (lnav_data.ld_cmd_init_done) {
|
||||
return;
|
||||
|
@ -678,29 +695,30 @@ execute_init_commands(
|
|||
|
||||
wait_for_children();
|
||||
|
||||
ec.ec_source.emplace("command-option", option_index++);
|
||||
switch (cmd.at(0)) {
|
||||
case ':':
|
||||
msgs.emplace_back(execute_command(ec, cmd.substr(1)), alt_msg);
|
||||
break;
|
||||
case '/':
|
||||
lnav_data.ld_view_stack.top() |
|
||||
[cmd](auto tc) { tc->execute_search(cmd.substr(1)); };
|
||||
break;
|
||||
case ';':
|
||||
setup_logline_table(ec);
|
||||
msgs.emplace_back(execute_sql(ec, cmd.substr(1), alt_msg),
|
||||
alt_msg);
|
||||
break;
|
||||
case '|':
|
||||
msgs.emplace_back(execute_file(ec, cmd.substr(1)), alt_msg);
|
||||
break;
|
||||
{
|
||||
auto _sg = ec.enter_source("command-option", option_index++, cmd);
|
||||
switch (cmd.at(0)) {
|
||||
case ':':
|
||||
msgs.emplace_back(execute_command(ec, cmd.substr(1)),
|
||||
alt_msg);
|
||||
break;
|
||||
case '/':
|
||||
lnav_data.ld_view_stack.top() |
|
||||
[cmd](auto tc) { tc->execute_search(cmd.substr(1)); };
|
||||
break;
|
||||
case ';':
|
||||
setup_logline_table(ec);
|
||||
msgs.emplace_back(execute_sql(ec, cmd.substr(1), alt_msg),
|
||||
alt_msg);
|
||||
break;
|
||||
case '|':
|
||||
msgs.emplace_back(execute_file(ec, cmd.substr(1)), alt_msg);
|
||||
break;
|
||||
}
|
||||
|
||||
rescan_files();
|
||||
rebuild_indexes_repeatedly();
|
||||
}
|
||||
|
||||
rescan_files();
|
||||
rebuild_indexes_repeatedly();
|
||||
|
||||
ec.ec_source.pop();
|
||||
}
|
||||
lnav_data.ld_commands.clear();
|
||||
|
||||
|
@ -854,19 +872,6 @@ add_global_vars(exec_context& ec)
|
|||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
exec_context::get_error_prefix()
|
||||
{
|
||||
if (this->ec_source.size() <= 1) {
|
||||
return "error: ";
|
||||
}
|
||||
|
||||
std::pair<std::string, int> source = this->ec_source.top();
|
||||
|
||||
return fmt::format(
|
||||
FMT_STRING("{}:{}: error: "), source.first, source.second);
|
||||
}
|
||||
|
||||
void
|
||||
exec_context::set_output(const std::string& name,
|
||||
FILE* file,
|
||||
|
@ -903,10 +908,28 @@ exec_context::exec_context(std::vector<logline_value>* line_values,
|
|||
{
|
||||
this->ec_local_vars.push(std::map<std::string, std::string>());
|
||||
this->ec_path_stack.emplace_back(".");
|
||||
this->ec_source.emplace("command", 1);
|
||||
this->ec_source.emplace(
|
||||
lnav::console::snippet::from("command", "").with_line(1));
|
||||
this->ec_output_stack.emplace_back("screen", nonstd::nullopt);
|
||||
}
|
||||
|
||||
void
|
||||
exec_context::add_error_context(lnav::console::user_message& um)
|
||||
{
|
||||
if (!this->ec_source.empty()) {
|
||||
auto source = this->ec_source.top();
|
||||
|
||||
um.with_snippet(source);
|
||||
}
|
||||
|
||||
if (this->ec_current_help != nullptr) {
|
||||
attr_line_t help;
|
||||
|
||||
format_help_text_for_term(*this->ec_current_help, -1, help, true);
|
||||
um.with_help(help);
|
||||
}
|
||||
}
|
||||
|
||||
exec_context::output_guard::output_guard(exec_context& context,
|
||||
std::string name,
|
||||
const nonstd::optional<output_t>& file)
|
||||
|
|
|
@ -37,9 +37,11 @@
|
|||
#include <sqlite3.h>
|
||||
|
||||
#include "base/auto_fd.hh"
|
||||
#include "base/lnav.console.hh"
|
||||
#include "bookmarks.hh"
|
||||
#include "fmt/format.h"
|
||||
#include "ghc/filesystem.hpp"
|
||||
#include "help_text.hh"
|
||||
#include "optional.hpp"
|
||||
#include "shlex.resolver.hh"
|
||||
#include "vis_line.hh"
|
||||
|
@ -82,14 +84,18 @@ struct exec_context {
|
|||
return *this;
|
||||
}
|
||||
|
||||
std::string get_error_prefix();
|
||||
void add_error_context(lnav::console::user_message& um);
|
||||
|
||||
template<typename... Args>
|
||||
Result<std::string, std::string> make_error(fmt::string_view format_str,
|
||||
const Args&... args)
|
||||
Result<std::string, lnav::console::user_message> make_error(
|
||||
fmt::string_view format_str, const Args&... args)
|
||||
{
|
||||
return Err(this->get_error_prefix()
|
||||
+ fmt::vformat(format_str, fmt::make_format_args(args...)));
|
||||
auto retval = lnav::console::user_message::error(
|
||||
fmt::vformat(format_str, fmt::make_format_args(args...)));
|
||||
|
||||
this->add_error_context(retval);
|
||||
|
||||
return Err(retval);
|
||||
}
|
||||
|
||||
nonstd::optional<FILE*> get_output()
|
||||
|
@ -132,9 +138,12 @@ struct exec_context {
|
|||
exec_context& sg_context;
|
||||
};
|
||||
|
||||
source_guard enter_source(const std::string& path, int line_number)
|
||||
source_guard enter_source(const std::string& path,
|
||||
int line_number,
|
||||
const std::string& content)
|
||||
{
|
||||
this->ec_source.emplace(path, line_number);
|
||||
this->ec_source.emplace(
|
||||
lnav::console::snippet::from(path, content).with_line(line_number));
|
||||
return {*this};
|
||||
}
|
||||
|
||||
|
@ -155,7 +164,8 @@ struct exec_context {
|
|||
std::stack<std::map<std::string, std::string>> ec_local_vars;
|
||||
std::map<std::string, std::string> ec_global_vars;
|
||||
std::vector<ghc::filesystem::path> ec_path_stack;
|
||||
std::stack<std::pair<std::string, int>> ec_source;
|
||||
std::stack<lnav::console::snippet> ec_source;
|
||||
help_text* ec_current_help{nullptr};
|
||||
|
||||
std::vector<std::pair<std::string, nonstd::optional<output_t>>>
|
||||
ec_output_stack;
|
||||
|
@ -166,21 +176,19 @@ struct exec_context {
|
|||
pipe_callback_t ec_pipe_callback;
|
||||
};
|
||||
|
||||
Result<std::string, std::string> execute_command(exec_context& ec,
|
||||
const std::string& cmdline);
|
||||
Result<std::string, lnav::console::user_message> execute_command(
|
||||
exec_context& ec, const std::string& cmdline);
|
||||
|
||||
Result<std::string, std::string> execute_sql(exec_context& ec,
|
||||
const std::string& sql,
|
||||
std::string& alt_msg);
|
||||
Result<std::string, std::string> execute_file(exec_context& ec,
|
||||
const std::string& path_and_args,
|
||||
bool multiline = true);
|
||||
Result<std::string, std::string> execute_any(exec_context& ec,
|
||||
const std::string& cmdline);
|
||||
Result<std::string, lnav::console::user_message> execute_sql(
|
||||
exec_context& ec, const std::string& sql, std::string& alt_msg);
|
||||
Result<std::string, lnav::console::user_message> execute_file(
|
||||
exec_context& ec, const std::string& path_and_args, bool multiline = true);
|
||||
Result<std::string, lnav::console::user_message> execute_any(
|
||||
exec_context& ec, const std::string& cmdline);
|
||||
void execute_init_commands(
|
||||
exec_context& ec,
|
||||
std::vector<std::pair<Result<std::string, std::string>, std::string>>&
|
||||
msgs);
|
||||
std::vector<std::pair<Result<std::string, lnav::console::user_message>,
|
||||
std::string>>& msgs);
|
||||
|
||||
std::future<std::string> pipe_callback(exec_context& ec,
|
||||
const std::string& cmdline,
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
#ifndef curl_looper_hh
|
||||
#define curl_looper_hh
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
@ -41,6 +39,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "base/isc.hh"
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(HAVE_LIBCURL)
|
||||
|
||||
|
@ -67,7 +66,7 @@ public:
|
|||
|
||||
# include <curl/curl.h>
|
||||
|
||||
# include "auto_mem.hh"
|
||||
# include "base/auto_mem.hh"
|
||||
# include "base/lnav_log.hh"
|
||||
# include "base/time_util.hh"
|
||||
|
||||
|
|
|
@ -112,11 +112,11 @@ 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, view_curses::VC_STYLE.value(A_BOLD));
|
||||
sa.emplace_back(lr2, VC_STYLE.value(A_BOLD));
|
||||
}
|
||||
lr.lr_start += this->dls_cell_width[lpc];
|
||||
lr.lr_end = lr.lr_start + 1;
|
||||
sa.emplace_back(lr, view_curses::VC_GRAPHIC.value(ACS_VLINE));
|
||||
sa.emplace_back(lr, VC_GRAPHIC.value(ACS_VLINE));
|
||||
lr.lr_start += 1;
|
||||
}
|
||||
|
||||
|
@ -344,10 +344,10 @@ db_overlay_source::list_overlay_count(const listview_curses& lv)
|
|||
string_attrs_t& sa = this->dos_lines.back().get_attrs();
|
||||
struct line_range lr(1, 2);
|
||||
|
||||
sa.emplace_back(lr, view_curses::VC_GRAPHIC.value(ACS_LTEE));
|
||||
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, view_curses::VC_STYLE.value(A_BOLD));
|
||||
sa.emplace_back(lr, VC_STYLE.value(A_BOLD));
|
||||
|
||||
double num_value = 0.0;
|
||||
|
||||
|
@ -390,10 +390,10 @@ db_overlay_source::list_overlay_count(const listview_curses& lv)
|
|||
string_attrs_t& sa = this->dos_lines.back().get_attrs();
|
||||
struct line_range lr(1, 2);
|
||||
|
||||
sa.emplace_back(lr, view_curses::VC_GRAPHIC.value(ACS_LLCORNER));
|
||||
sa.emplace_back(lr, VC_GRAPHIC.value(ACS_LLCORNER));
|
||||
lr.lr_start = 2;
|
||||
lr.lr_end = -1;
|
||||
sa.emplace_back(lr, view_curses::VC_GRAPHIC.value(ACS_HLINE));
|
||||
sa.emplace_back(lr, VC_GRAPHIC.value(ACS_HLINE));
|
||||
|
||||
retval += 1;
|
||||
}
|
||||
|
@ -443,12 +443,12 @@ db_overlay_source::list_value_for_overlay(const listview_curses& lv,
|
|||
if (!this->dos_labels->dls_headers[lpc].hm_graphable) {
|
||||
attrs = A_UNDERLINE;
|
||||
}
|
||||
sa.emplace_back(header_range, view_curses::VC_STYLE.value(attrs));
|
||||
sa.emplace_back(header_range, VC_STYLE.value(attrs));
|
||||
}
|
||||
|
||||
struct line_range lr(0);
|
||||
|
||||
sa.emplace_back(lr, view_curses::VC_STYLE.value(A_BOLD | A_UNDERLINE));
|
||||
sa.emplace_back(lr, VC_STYLE.value(A_BOLD | A_UNDERLINE));
|
||||
return true;
|
||||
} else if (this->dos_active && y >= 2
|
||||
&& ((size_t) y) < (this->dos_lines.size() + 2))
|
||||
|
|
|
@ -48,13 +48,13 @@ public:
|
|||
{
|
||||
this->tss_fields[TSF_TITLE].set_width(14);
|
||||
this->tss_fields[TSF_TITLE].set_left_pad(1);
|
||||
this->tss_fields[TSF_TITLE].set_role(view_colors::VCR_STATUS_TITLE);
|
||||
this->tss_fields[TSF_TITLE].set_role(role_t::VCR_STATUS_TITLE);
|
||||
this->tss_fields[TSF_STITCH_TITLE].set_width(2);
|
||||
this->tss_fields[TSF_STITCH_TITLE].set_stitch_value(
|
||||
view_colors::VCR_STATUS_STITCH_TITLE_TO_NORMAL,
|
||||
view_colors::VCR_STATUS_STITCH_NORMAL_TO_TITLE);
|
||||
role_t::VCR_STATUS_STITCH_TITLE_TO_NORMAL,
|
||||
role_t::VCR_STATUS_STITCH_NORMAL_TO_TITLE);
|
||||
this->tss_fields[TSF_DESCRIPTION].set_share(1);
|
||||
this->tss_fields[TSF_DESCRIPTION].set_role(view_colors::VCR_STATUS);
|
||||
this->tss_fields[TSF_DESCRIPTION].set_role(role_t::VCR_STATUS);
|
||||
};
|
||||
|
||||
size_t statusview_fields() override
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "auto_mem.hh"
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/lnav_log.hh"
|
||||
#include "config.h"
|
||||
|
||||
|
|
|
@ -29,10 +29,9 @@
|
|||
|
||||
#include "field_overlay_source.hh"
|
||||
|
||||
#include "ansi_scrubber.hh"
|
||||
#include "base/ansi_scrubber.hh"
|
||||
#include "base/humanize.time.hh"
|
||||
#include "config.h"
|
||||
#include "lnav_util.hh"
|
||||
#include "log_format_ext.hh"
|
||||
#include "log_vtab_impl.hh"
|
||||
#include "readline_highlighters.hh"
|
||||
|
@ -145,7 +144,7 @@ field_overlay_source::build_summary_lines(const listview_curses& lv)
|
|||
"%'.2lf") "/min; "
|
||||
"Time span: " ANSI_BOLD("%s"),
|
||||
lss.file_count(),
|
||||
view_colors::VCR_ERROR,
|
||||
role_t::VCR_ERROR,
|
||||
error_rate,
|
||||
time_span.c_str());
|
||||
} else {
|
||||
|
@ -158,7 +157,7 @@ field_overlay_source::build_summary_lines(const listview_curses& lv)
|
|||
"Time span: " ANSI_BOLD("%s"),
|
||||
lss.file_count(),
|
||||
tss.size(),
|
||||
view_colors::VCR_ERROR,
|
||||
role_t::VCR_ERROR,
|
||||
error_rate,
|
||||
time_span.c_str());
|
||||
}
|
||||
|
@ -167,18 +166,18 @@ field_overlay_source::build_summary_lines(const listview_curses& lv)
|
|||
.with_attr(string_attr(
|
||||
line_range(sum_msg.find("Error rate"),
|
||||
sum_msg.find("Error rate") + rate_len),
|
||||
view_curses::VC_STYLE.value(A_REVERSE)))
|
||||
VC_STYLE.value(A_REVERSE)))
|
||||
.with_attr(
|
||||
string_attr(line_range(1, 2),
|
||||
view_curses::VC_GRAPHIC.value(ACS_ULCORNER)))
|
||||
VC_GRAPHIC.value(ACS_ULCORNER)))
|
||||
.with_attr(string_attr(
|
||||
line_range(2, 6), view_curses::VC_GRAPHIC.value(ACS_HLINE)))
|
||||
line_range(2, 6), VC_GRAPHIC.value(ACS_HLINE)))
|
||||
.with_attr(string_attr(
|
||||
line_range(sum_msg.length() + 1, sum_msg.length() + 5),
|
||||
view_curses::VC_GRAPHIC.value(ACS_HLINE)))
|
||||
VC_GRAPHIC.value(ACS_HLINE)))
|
||||
.with_attr(string_attr(
|
||||
line_range(sum_msg.length() + 5, sum_msg.length() + 6),
|
||||
view_curses::VC_GRAPHIC.value(ACS_URCORNER)))
|
||||
VC_GRAPHIC.value(ACS_URCORNER)))
|
||||
.right_justify(width - 2);
|
||||
}
|
||||
}
|
||||
|
@ -234,11 +233,11 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
|
|||
auto al = attr_line_t(emsg)
|
||||
.with_attr(string_attr(
|
||||
line_range{1, 2},
|
||||
view_curses::VC_GRAPHIC.value(ACS_LLCORNER)))
|
||||
VC_GRAPHIC.value(ACS_LLCORNER)))
|
||||
.with_attr(
|
||||
string_attr(line_range{0, 22},
|
||||
view_curses::VC_ROLE.value(
|
||||
view_colors::VCR_INVALID_MSG)));
|
||||
VC_ROLE.value(
|
||||
role_t::VCR_INVALID_MSG)));
|
||||
this->fos_lines.emplace_back(al);
|
||||
}
|
||||
}
|
||||
|
@ -259,12 +258,12 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
|
|||
time_lr.lr_start = 1;
|
||||
time_lr.lr_end = 2;
|
||||
time_line.with_attr(
|
||||
string_attr(time_lr, view_curses::VC_GRAPHIC.value(ACS_LLCORNER)));
|
||||
string_attr(time_lr, VC_GRAPHIC.value(ACS_LLCORNER)));
|
||||
time_str.append(" Out-Of-Time-Order Message");
|
||||
time_lr.lr_start = 3;
|
||||
time_lr.lr_end = time_str.length();
|
||||
time_line.with_attr(string_attr(
|
||||
time_lr, view_curses::VC_ROLE.value(view_colors::VCR_SKEWED_TIME)));
|
||||
time_lr, VC_ROLE.value(role_t::VCR_SKEWED_TIME)));
|
||||
time_str.append(" --");
|
||||
}
|
||||
|
||||
|
@ -273,7 +272,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, view_curses::VC_STYLE.value(A_BOLD)));
|
||||
string_attr(time_lr, VC_STYLE.value(A_BOLD)));
|
||||
time_str.append(" -- ");
|
||||
time_lr.lr_start = time_str.length();
|
||||
time_str.append(humanize::time::point::from_tv(ll->get_timeval())
|
||||
|
@ -281,7 +280,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, view_curses::VC_STYLE.value(A_BOLD)));
|
||||
string_attr(time_lr, VC_STYLE.value(A_BOLD)));
|
||||
|
||||
struct line_range time_range = find_string_attr_range(
|
||||
this->fos_log_helper.ldh_line_attrs, &logline::L_TIMESTAMP);
|
||||
|
@ -312,7 +311,7 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
|
|||
time_lr.lr_end = time_str.length();
|
||||
time_line.with_attr(string_attr(
|
||||
time_lr,
|
||||
view_curses::VC_ROLE.value(view_colors::VCR_SKEWED_TIME)));
|
||||
VC_ROLE.value(role_t::VCR_SKEWED_TIME)));
|
||||
|
||||
timersub(&curr_tv, &actual_tv, &diff_tv);
|
||||
time_str.append("; Diff: ");
|
||||
|
@ -321,7 +320,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, view_curses::VC_STYLE.value(A_BOLD)));
|
||||
string_attr(time_lr, VC_STYLE.value(A_BOLD)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,7 +418,7 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
|
|||
+ format_name + ":");
|
||||
this->fos_lines.back().with_attr(string_attr(
|
||||
line_range(32, 32 + format_name.length()),
|
||||
view_curses::VC_STYLE.value(vc.attrs_for_ident(format_name)
|
||||
VC_STYLE.value(vc.attrs_for_ident(format_name)
|
||||
| A_BOLD)));
|
||||
last_format = curr_format;
|
||||
}
|
||||
|
@ -455,12 +454,12 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
|
|||
auto prefix_len = field_name.length() - orig_field_name.length();
|
||||
al.with_attr(string_attr(
|
||||
line_range(3 + prefix_len, 3 + prefix_len + field_name.size()),
|
||||
view_curses::VC_STYLE.value(
|
||||
VC_STYLE.value(
|
||||
vc.attrs_for_ident(orig_field_name))));
|
||||
} else {
|
||||
al.with_attr(string_attr(
|
||||
line_range(8, 8 + lv.lv_meta.lvm_struct_name.size()),
|
||||
view_curses::VC_STYLE.value(
|
||||
VC_STYLE.value(
|
||||
vc.attrs_for_ident(lv.lv_meta.lvm_struct_name))));
|
||||
}
|
||||
|
||||
|
@ -473,7 +472,7 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
|
|||
al.clear()
|
||||
.append(" extract(")
|
||||
.append(lv.lv_meta.lvm_name.get(),
|
||||
view_curses::VC_STYLE.value(
|
||||
VC_STYLE.value(
|
||||
vc.attrs_for_ident(lv.lv_meta.lvm_name)))
|
||||
.append(")")
|
||||
.append(this->fos_known_key_size - lv.lv_meta.lvm_name.size()
|
||||
|
@ -536,12 +535,12 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
|
|||
" Discovered fields for logline table from message format: ");
|
||||
this->fos_lines.back().with_attr(string_attr(
|
||||
line_range(23, 23 + 7),
|
||||
view_curses::VC_STYLE.value(vc.attrs_for_ident("logline"))));
|
||||
VC_STYLE.value(vc.attrs_for_ident("logline"))));
|
||||
auto& al = this->fos_lines.back();
|
||||
auto& disc_str = al.get_string();
|
||||
|
||||
al.with_attr(string_attr(line_range(disc_str.length(), -1),
|
||||
view_curses::VC_STYLE.value(A_BOLD)));
|
||||
VC_STYLE.value(A_BOLD)));
|
||||
disc_str.append(this->fos_log_helper.ldh_msg_format);
|
||||
}
|
||||
|
||||
|
@ -556,7 +555,7 @@ field_overlay_source::build_field_lines(const listview_curses& lv)
|
|||
|
||||
al.with_attr(
|
||||
string_attr(line_range(3, 3 + name.length()),
|
||||
view_curses::VC_STYLE.value(vc.attrs_for_ident(name))));
|
||||
VC_STYLE.value(vc.attrs_for_ident(name))));
|
||||
|
||||
this->fos_lines.emplace_back(al);
|
||||
this->add_key_line_attrs(
|
||||
|
@ -585,7 +584,7 @@ field_overlay_source::build_meta_line(const listview_curses& lv,
|
|||
al.with_string(" + ")
|
||||
.with_attr(string_attr(
|
||||
line_range(1, 2),
|
||||
view_curses::VC_GRAPHIC.value(
|
||||
VC_GRAPHIC.value(
|
||||
line_meta.bm_tags.empty() ? ACS_LLCORNER : ACS_LTEE)))
|
||||
.append(line_meta.bm_comment);
|
||||
al.insert(0, filename_width, ' ');
|
||||
|
@ -595,10 +594,10 @@ field_overlay_source::build_meta_line(const listview_curses& lv,
|
|||
attr_line_t al;
|
||||
|
||||
al.with_string(" +").with_attr(string_attr(
|
||||
line_range(1, 2), view_curses::VC_GRAPHIC.value(ACS_LLCORNER)));
|
||||
line_range(1, 2), VC_GRAPHIC.value(ACS_LLCORNER)));
|
||||
for (const auto& str : line_meta.bm_tags) {
|
||||
al.append(1, ' ').append(
|
||||
str, view_curses::VC_STYLE.value(vc.attrs_for_ident(str)));
|
||||
str, VC_STYLE.value(vc.attrs_for_ident(str)));
|
||||
}
|
||||
|
||||
const auto* tc = dynamic_cast<const textview_curses*>(&lv);
|
||||
|
|
|
@ -51,11 +51,11 @@ public:
|
|||
string_attrs_t& sa = this->fos_lines.back().get_attrs();
|
||||
struct line_range lr(1, 2);
|
||||
int64_t graphic = (int64_t) (last_line ? ACS_LLCORNER : ACS_LTEE);
|
||||
sa.emplace_back(lr, view_curses::VC_GRAPHIC.value(graphic));
|
||||
sa.emplace_back(lr, VC_GRAPHIC.value(graphic));
|
||||
|
||||
lr.lr_start = 3 + key_size + 3;
|
||||
lr.lr_end = -1;
|
||||
sa.emplace_back(lr, view_curses::VC_STYLE.value(A_BOLD));
|
||||
sa.emplace_back(lr, VC_STYLE.value(A_BOLD));
|
||||
};
|
||||
|
||||
bool list_value_for_overlay(const listview_curses& lv,
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "base/humanize.network.hh"
|
||||
#include "base/isc.hh"
|
||||
#include "base/opt_util.hh"
|
||||
#include "base/string_util.hh"
|
||||
#include "config.h"
|
||||
#include "lnav_util.hh"
|
||||
#include "logfile.hh"
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "files_sub_source.hh"
|
||||
|
||||
#include "base/ansi_scrubber.hh"
|
||||
#include "base/humanize.hh"
|
||||
#include "base/humanize.network.hh"
|
||||
#include "base/opt_util.hh"
|
||||
|
@ -284,7 +285,8 @@ files_sub_source::text_value_for_line(textview_curses& tc,
|
|||
value_out = fmt::format(FMT_STRING(" {:<{}} {:>8} {} \u2014 {} {}"),
|
||||
fn,
|
||||
filename_width,
|
||||
humanize::file_size(lf->get_index_size()),
|
||||
humanize::file_size(lf->get_index_size(),
|
||||
humanize::alignment::columnar),
|
||||
start_time,
|
||||
end_time,
|
||||
fmt::join(file_notes, "; "));
|
||||
|
@ -308,19 +310,19 @@ files_sub_source::text_attrs_for_line(textview_curses& tc,
|
|||
|
||||
if (selected) {
|
||||
value_out.emplace_back(line_range{0, 1},
|
||||
view_curses::VC_GRAPHIC.value(ACS_RARROW));
|
||||
VC_GRAPHIC.value(ACS_RARROW));
|
||||
}
|
||||
|
||||
if (line < fc.fc_name_to_errors.size()) {
|
||||
if (selected) {
|
||||
value_out.emplace_back(
|
||||
line_range{0, -1},
|
||||
view_curses::VC_ROLE.value(view_colors::VCR_DISABLED_FOCUSED));
|
||||
VC_ROLE.value(role_t::VCR_DISABLED_FOCUSED));
|
||||
}
|
||||
|
||||
value_out.emplace_back(
|
||||
line_range{4 + (int) filename_width, -1},
|
||||
view_curses::VC_ROLE_FG.value(view_colors::VCR_ERROR));
|
||||
VC_ROLE_FG.value(role_t::VCR_ERROR));
|
||||
return;
|
||||
}
|
||||
line -= fc.fc_name_to_errors.size();
|
||||
|
@ -329,11 +331,11 @@ files_sub_source::text_attrs_for_line(textview_curses& tc,
|
|||
if (selected) {
|
||||
value_out.emplace_back(
|
||||
line_range{0, -1},
|
||||
view_curses::VC_ROLE.value(view_colors::VCR_DISABLED_FOCUSED));
|
||||
VC_ROLE.value(role_t::VCR_DISABLED_FOCUSED));
|
||||
}
|
||||
if (line == fc.fc_other_files.size() - 1) {
|
||||
value_out.emplace_back(line_range{0, -1},
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
VC_STYLE.value(A_UNDERLINE));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -343,7 +345,7 @@ files_sub_source::text_attrs_for_line(textview_curses& tc,
|
|||
if (selected) {
|
||||
value_out.emplace_back(
|
||||
line_range{0, -1},
|
||||
view_curses::VC_ROLE.value(view_colors::VCR_FOCUSED));
|
||||
VC_ROLE.value(role_t::VCR_FOCUSED));
|
||||
}
|
||||
|
||||
auto& lss = lnav_data.ld_log_source;
|
||||
|
@ -355,10 +357,10 @@ files_sub_source::text_attrs_for_line(textview_curses& tc,
|
|||
visible = ' ';
|
||||
}
|
||||
value_out.emplace_back(line_range{2, 3},
|
||||
view_curses::VC_GRAPHIC.value(visible));
|
||||
VC_GRAPHIC.value(visible));
|
||||
if (visible == ACS_DIAMOND) {
|
||||
value_out.emplace_back(line_range{2, 3},
|
||||
view_curses::VC_FOREGROUND.value(
|
||||
VC_FOREGROUND.value(
|
||||
vcolors.ansi_to_theme_color(COLOR_GREEN)));
|
||||
}
|
||||
|
||||
|
@ -366,12 +368,12 @@ 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, view_curses::VC_STYLE.value(A_BOLD));
|
||||
value_out.emplace_back(lr, VC_STYLE.value(A_BOLD));
|
||||
|
||||
lr.lr_start = this->fss_last_line_len;
|
||||
lr.lr_end = -1;
|
||||
value_out.emplace_back(lr,
|
||||
view_curses::VC_FOREGROUND.value(
|
||||
VC_FOREGROUND.value(
|
||||
vcolors.ansi_to_theme_color(COLOR_YELLOW)));
|
||||
}
|
||||
|
||||
|
@ -417,8 +419,10 @@ files_overlay_source::list_value_for_overlay(const listview_curses& lv,
|
|||
"... {:>8}/{}",
|
||||
PROG[spinner_index() % PROG_SIZE],
|
||||
prog.ep_path.filename().string(),
|
||||
humanize::file_size(prog.ep_out_size),
|
||||
humanize::file_size(prog.ep_total_size)));
|
||||
humanize::file_size(prog.ep_out_size,
|
||||
humanize::alignment::none),
|
||||
humanize::file_size(prog.ep_total_size,
|
||||
humanize::alignment::none)));
|
||||
return true;
|
||||
}
|
||||
if (!sp->sp_tailers.empty()) {
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "filter_status_source.hh"
|
||||
|
||||
#include "base/ansi_scrubber.hh"
|
||||
#include "base/opt_util.hh"
|
||||
#include "config.h"
|
||||
#include "files_sub_source.hh"
|
||||
|
@ -49,32 +50,32 @@ static auto CLOSE_HELP = ANSI_BOLD("X") ": Close";
|
|||
filter_status_source::filter_status_source()
|
||||
{
|
||||
this->tss_fields[TSF_TITLE].set_width(14);
|
||||
this->tss_fields[TSF_TITLE].set_role(view_colors::VCR_STATUS_TITLE);
|
||||
this->tss_fields[TSF_TITLE].set_role(role_t::VCR_STATUS_TITLE);
|
||||
this->tss_fields[TSF_TITLE].set_value(" " ANSI_ROLE("T") "ext Filters ",
|
||||
view_colors::VCR_STATUS_TITLE_HOTKEY);
|
||||
role_t::VCR_STATUS_TITLE_HOTKEY);
|
||||
|
||||
this->tss_fields[TSF_STITCH_TITLE].set_width(2);
|
||||
this->tss_fields[TSF_STITCH_TITLE].set_stitch_value(
|
||||
view_colors::VCR_STATUS_STITCH_TITLE_TO_NORMAL,
|
||||
view_colors::VCR_STATUS_STITCH_NORMAL_TO_TITLE);
|
||||
role_t::VCR_STATUS_STITCH_TITLE_TO_NORMAL,
|
||||
role_t::VCR_STATUS_STITCH_NORMAL_TO_TITLE);
|
||||
|
||||
this->tss_fields[TSF_COUNT].set_min_width(16);
|
||||
this->tss_fields[TSF_COUNT].set_share(1);
|
||||
this->tss_fields[TSF_COUNT].set_role(view_colors::VCR_STATUS);
|
||||
this->tss_fields[TSF_COUNT].set_role(role_t::VCR_STATUS);
|
||||
|
||||
this->tss_fields[TSF_FILTERED].set_min_width(20);
|
||||
this->tss_fields[TSF_FILTERED].set_share(1);
|
||||
this->tss_fields[TSF_FILTERED].set_role(view_colors::VCR_STATUS);
|
||||
this->tss_fields[TSF_FILTERED].set_role(role_t::VCR_STATUS);
|
||||
|
||||
this->tss_fields[TSF_FILES_TITLE].set_width(7);
|
||||
this->tss_fields[TSF_FILES_TITLE].set_role(
|
||||
view_colors::VCR_STATUS_DISABLED_TITLE);
|
||||
role_t::VCR_STATUS_DISABLED_TITLE);
|
||||
this->tss_fields[TSF_FILES_TITLE].set_value(" " ANSI_ROLE("F") "iles ",
|
||||
view_colors::VCR_STATUS_HOTKEY);
|
||||
role_t::VCR_STATUS_HOTKEY);
|
||||
|
||||
this->tss_fields[TSF_FILES_RIGHT_STITCH].set_width(2);
|
||||
this->tss_fields[TSF_FILES_RIGHT_STITCH].set_stitch_value(
|
||||
view_colors::VCR_STATUS, view_colors::VCR_STATUS);
|
||||
role_t::VCR_STATUS, role_t::VCR_STATUS);
|
||||
|
||||
this->tss_fields[TSF_HELP].right_justify(true);
|
||||
this->tss_fields[TSF_HELP].set_width(20);
|
||||
|
@ -83,7 +84,7 @@ filter_status_source::filter_status_source()
|
|||
|
||||
this->tss_error.set_min_width(20);
|
||||
this->tss_error.set_share(1);
|
||||
this->tss_error.set_role(view_colors::VCR_ALERT_STATUS);
|
||||
this->tss_error.set_role(role_t::VCR_ALERT_STATUS);
|
||||
}
|
||||
|
||||
size_t
|
||||
|
@ -106,27 +107,27 @@ filter_status_source::statusview_fields()
|
|||
if (lnav_data.ld_mode == LNM_FILES || lnav_data.ld_mode == LNM_SEARCH_FILES)
|
||||
{
|
||||
this->tss_fields[TSF_FILES_TITLE].set_value(
|
||||
" " ANSI_ROLE("F") "iles ", view_colors::VCR_STATUS_TITLE_HOTKEY);
|
||||
" " ANSI_ROLE("F") "iles ", role_t::VCR_STATUS_TITLE_HOTKEY);
|
||||
this->tss_fields[TSF_FILES_TITLE].set_role(
|
||||
view_colors::VCR_STATUS_TITLE);
|
||||
role_t::VCR_STATUS_TITLE);
|
||||
this->tss_fields[TSF_FILES_RIGHT_STITCH].set_stitch_value(
|
||||
view_colors::VCR_STATUS_STITCH_TITLE_TO_NORMAL,
|
||||
view_colors::VCR_STATUS_STITCH_NORMAL_TO_TITLE);
|
||||
role_t::VCR_STATUS_STITCH_TITLE_TO_NORMAL,
|
||||
role_t::VCR_STATUS_STITCH_NORMAL_TO_TITLE);
|
||||
this->tss_fields[TSF_TITLE].set_value(" " ANSI_ROLE("T") "ext Filters ",
|
||||
view_colors::VCR_STATUS_HOTKEY);
|
||||
role_t::VCR_STATUS_HOTKEY);
|
||||
this->tss_fields[TSF_TITLE].set_role(
|
||||
view_colors::VCR_STATUS_DISABLED_TITLE);
|
||||
role_t::VCR_STATUS_DISABLED_TITLE);
|
||||
this->tss_fields[TSF_STITCH_TITLE].set_stitch_value(
|
||||
view_colors::VCR_STATUS, view_colors::VCR_STATUS);
|
||||
role_t::VCR_STATUS, role_t::VCR_STATUS);
|
||||
} else {
|
||||
this->tss_fields[TSF_FILES_TITLE].set_value(
|
||||
" " ANSI_ROLE("F") "iles ", view_colors::VCR_STATUS_HOTKEY);
|
||||
" " ANSI_ROLE("F") "iles ", role_t::VCR_STATUS_HOTKEY);
|
||||
if (lnav_data.ld_active_files.fc_name_to_errors.empty()) {
|
||||
this->tss_fields[TSF_FILES_TITLE].set_role(
|
||||
view_colors::VCR_STATUS_DISABLED_TITLE);
|
||||
role_t::VCR_STATUS_DISABLED_TITLE);
|
||||
} else {
|
||||
this->tss_fields[TSF_FILES_TITLE].set_role(
|
||||
view_colors::VCR_ALERT_STATUS);
|
||||
role_t::VCR_ALERT_STATUS);
|
||||
|
||||
auto& fc = lnav_data.ld_active_files;
|
||||
if (fc.fc_name_to_errors.size() == 1) {
|
||||
|
@ -138,15 +139,15 @@ filter_status_source::statusview_fields()
|
|||
}
|
||||
}
|
||||
this->tss_fields[TSF_FILES_RIGHT_STITCH].set_stitch_value(
|
||||
view_colors::VCR_STATUS_STITCH_NORMAL_TO_TITLE,
|
||||
view_colors::VCR_STATUS_STITCH_TITLE_TO_NORMAL);
|
||||
role_t::VCR_STATUS_STITCH_NORMAL_TO_TITLE,
|
||||
role_t::VCR_STATUS_STITCH_TITLE_TO_NORMAL);
|
||||
this->tss_fields[TSF_TITLE].set_value(
|
||||
" " ANSI_ROLE("T") "ext Filters ",
|
||||
view_colors::VCR_STATUS_TITLE_HOTKEY);
|
||||
this->tss_fields[TSF_TITLE].set_role(view_colors::VCR_STATUS_TITLE);
|
||||
role_t::VCR_STATUS_TITLE_HOTKEY);
|
||||
this->tss_fields[TSF_TITLE].set_role(role_t::VCR_STATUS_TITLE);
|
||||
this->tss_fields[TSF_STITCH_TITLE].set_stitch_value(
|
||||
view_colors::VCR_STATUS_STITCH_TITLE_TO_NORMAL,
|
||||
view_colors::VCR_STATUS_STITCH_NORMAL_TO_TITLE);
|
||||
role_t::VCR_STATUS_STITCH_TITLE_TO_NORMAL,
|
||||
role_t::VCR_STATUS_STITCH_NORMAL_TO_TITLE);
|
||||
}
|
||||
|
||||
lnav_data.ld_view_stack.top() | [this](auto tc) {
|
||||
|
@ -209,13 +210,13 @@ 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(
|
||||
view_colors::VCR_STATUS);
|
||||
role_t::VCR_STATUS);
|
||||
al.with_attr(string_attr(line_range{0, -1},
|
||||
view_curses::VC_STYLE.value(A_BOLD)));
|
||||
VC_STYLE.value(A_BOLD)));
|
||||
}
|
||||
} else {
|
||||
this->tss_fields[TSF_FILTERED].set_role(
|
||||
view_colors::VCR_ALERT_STATUS);
|
||||
role_t::VCR_ALERT_STATUS);
|
||||
this->bss_last_filtered_count = tss->get_filtered_count();
|
||||
timer.start_fade(this->bss_filter_counter, 3);
|
||||
}
|
||||
|
|
|
@ -72,8 +72,8 @@ public:
|
|||
|
||||
status_field& statusview_value_for_field(int field) override;
|
||||
|
||||
status_field fss_prompt{1024, view_colors::VCR_STATUS};
|
||||
status_field fss_error{1024, view_colors::VCR_ALERT_STATUS};
|
||||
status_field fss_prompt{1024, role_t::VCR_STATUS};
|
||||
status_field fss_error{1024, role_t::VCR_ALERT_STATUS};
|
||||
|
||||
private:
|
||||
status_field fss_help;
|
||||
|
|
|
@ -61,7 +61,7 @@ filter_sub_source::filter_sub_source()
|
|||
this->fss_match_view.set_sub_source(&this->fss_match_source);
|
||||
this->fss_match_view.set_height(0_vl);
|
||||
this->fss_match_view.set_show_scrollbar(true);
|
||||
this->fss_match_view.set_default_role(view_colors::VCR_POPUP);
|
||||
this->fss_match_view.set_default_role(role_t::VCR_POPUP);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -353,36 +353,35 @@ filter_sub_source::text_attrs_for_line(textview_curses& tc,
|
|||
|
||||
if (selected) {
|
||||
value_out.emplace_back(line_range{0, 1},
|
||||
view_curses::VC_GRAPHIC.value(ACS_RARROW));
|
||||
VC_GRAPHIC.value(ACS_RARROW));
|
||||
}
|
||||
|
||||
chtype enabled = tf->is_enabled() ? ACS_DIAMOND : ' ';
|
||||
|
||||
line_range lr{2, 3};
|
||||
value_out.emplace_back(lr, view_curses::VC_GRAPHIC.value(enabled));
|
||||
value_out.emplace_back(lr, VC_GRAPHIC.value(enabled));
|
||||
if (tf->is_enabled()) {
|
||||
value_out.emplace_back(lr,
|
||||
view_curses::VC_FOREGROUND.value(
|
||||
VC_FOREGROUND.value(
|
||||
vcolors.ansi_to_theme_color(COLOR_GREEN)));
|
||||
}
|
||||
|
||||
int fg_role = tf->get_type() == text_filter::INCLUDE
|
||||
? view_colors::VCR_OK
|
||||
: view_colors::VCR_ERROR;
|
||||
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},
|
||||
view_curses::VC_ROLE_FG.value(fg_role));
|
||||
VC_ROLE_FG.value(fg_role));
|
||||
value_out.emplace_back(line_range{4, 7},
|
||||
view_curses::VC_STYLE.value(A_BOLD));
|
||||
VC_STYLE.value(A_BOLD));
|
||||
|
||||
value_out.emplace_back(line_range{8, 17},
|
||||
view_curses::VC_STYLE.value(A_BOLD));
|
||||
VC_STYLE.value(A_BOLD));
|
||||
value_out.emplace_back(line_range{23, 24},
|
||||
view_curses::VC_GRAPHIC.value(ACS_VLINE));
|
||||
VC_GRAPHIC.value(ACS_VLINE));
|
||||
|
||||
if (selected) {
|
||||
value_out.emplace_back(
|
||||
line_range{0, -1},
|
||||
view_curses::VC_ROLE.value(view_colors::VCR_FOCUSED));
|
||||
VC_ROLE.value(role_t::VCR_FOCUSED));
|
||||
}
|
||||
|
||||
attr_line_t content{tf->get_id()};
|
||||
|
@ -624,7 +623,7 @@ filter_sub_source::rl_display_matches(readline_curses* rc)
|
|||
|
||||
for (auto& match : matches) {
|
||||
if (match == current_match) {
|
||||
al.append(match, view_curses::VC_STYLE.value(A_REVERSE));
|
||||
al.append(match, VC_STYLE.value(A_REVERSE));
|
||||
selected_line = line;
|
||||
} else {
|
||||
al.append(match);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/injector.hh"
|
||||
#include "base/lnav_log.hh"
|
||||
#include "config.h"
|
||||
|
|
|
@ -32,18 +32,18 @@
|
|||
#ifndef grep_proc_hh
|
||||
#define grep_proc_hh
|
||||
|
||||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <deque>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "base/auto_fd.hh"
|
||||
#include "auto_mem.hh"
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/lnav_log.hh"
|
||||
#include "line_buffer.hh"
|
||||
#include "pcrepp/pcrepp.hh"
|
||||
|
|
|
@ -32,13 +32,15 @@
|
|||
|
||||
#include "help_text_formatter.hh"
|
||||
|
||||
#include "ansi_scrubber.hh"
|
||||
#include "base/ansi_scrubber.hh"
|
||||
#include "base/string_util.hh"
|
||||
#include "config.h"
|
||||
#include "fmt/format.h"
|
||||
#include "fmt/printf.h"
|
||||
#include "readline_highlighters.hh"
|
||||
|
||||
using namespace lnav::roles::literals;
|
||||
|
||||
std::multimap<std::string, help_text*> help_text::TAGGED;
|
||||
|
||||
static std::vector<help_text*>
|
||||
|
@ -83,7 +85,6 @@ format_help_text_for_term(const help_text& ht,
|
|||
{
|
||||
static const size_t body_indent = 2;
|
||||
|
||||
view_colors& vc = view_colors::singleton();
|
||||
text_wrap_settings tws;
|
||||
size_t start_index = out.get_string().length();
|
||||
|
||||
|
@ -91,29 +92,27 @@ format_help_text_for_term(const help_text& ht,
|
|||
|
||||
switch (ht.ht_context) {
|
||||
case help_context_t::HC_COMMAND: {
|
||||
out.append("Synopsis", view_curses::VC_STYLE.value(A_UNDERLINE))
|
||||
out.append("Synopsis"_h2)
|
||||
.append("\n")
|
||||
.append(body_indent, ' ')
|
||||
.append(":")
|
||||
.append(ht.ht_name, view_curses::VC_STYLE.value(A_BOLD));
|
||||
.append(lnav::roles::symbol(ht.ht_name));
|
||||
for (const auto& param : ht.ht_parameters) {
|
||||
out.append(" ");
|
||||
if (param.ht_nargs == help_nargs_t::HN_OPTIONAL) {
|
||||
out.append("[");
|
||||
}
|
||||
out.append(param.ht_name,
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append(lnav::roles::variable(param.ht_name));
|
||||
if (param.ht_nargs == help_nargs_t::HN_OPTIONAL) {
|
||||
out.append("]");
|
||||
}
|
||||
if (param.ht_nargs == help_nargs_t::HN_ONE_OR_MORE) {
|
||||
out.append("1", view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append("1"_variable);
|
||||
out.append(" [");
|
||||
out.append("...", view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append("..."_variable);
|
||||
out.append(" ");
|
||||
out.append(param.ht_name,
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append("N", view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append(lnav::roles::variable(param.ht_name));
|
||||
out.append("N"_variable);
|
||||
out.append("]");
|
||||
}
|
||||
}
|
||||
|
@ -130,13 +129,12 @@ format_help_text_for_term(const help_text& ht,
|
|||
bool needs_comma = false;
|
||||
|
||||
if (!synopsis_only) {
|
||||
out.append("Synopsis", view_curses::VC_STYLE.value(A_UNDERLINE))
|
||||
.append("\n");
|
||||
out.append("Synopsis"_h2).append("\n");
|
||||
}
|
||||
|
||||
line_start = out.length();
|
||||
out.append(body_indent, ' ')
|
||||
.append(ht.ht_name, view_curses::VC_STYLE.value(A_BOLD))
|
||||
.append(lnav::roles::symbol(ht.ht_name))
|
||||
.append("(");
|
||||
for (const auto& param : ht.ht_parameters) {
|
||||
if (!param.ht_flag_name && needs_comma) {
|
||||
|
@ -153,15 +151,13 @@ format_help_text_for_term(const help_text& ht,
|
|||
}
|
||||
if (param.ht_flag_name) {
|
||||
out.append(" ")
|
||||
.append(param.ht_flag_name,
|
||||
view_curses::VC_STYLE.value(A_BOLD))
|
||||
.append(lnav::roles::symbol(param.ht_flag_name))
|
||||
.append(" ");
|
||||
}
|
||||
if (param.ht_nargs == help_nargs_t::HN_OPTIONAL) {
|
||||
out.append("[");
|
||||
}
|
||||
out.append(param.ht_name,
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append(lnav::roles::variable(param.ht_name));
|
||||
if (param.ht_nargs == help_nargs_t::HN_OPTIONAL) {
|
||||
out.append("]");
|
||||
}
|
||||
|
@ -183,29 +179,27 @@ format_help_text_for_term(const help_text& ht,
|
|||
break;
|
||||
}
|
||||
case help_context_t::HC_SQL_COMMAND: {
|
||||
out.append("Synopsis", view_curses::VC_STYLE.value(A_UNDERLINE))
|
||||
out.append("Synopsis"_h2)
|
||||
.append("\n")
|
||||
.append(body_indent, ' ')
|
||||
.append(";")
|
||||
.append(ht.ht_name, view_curses::VC_STYLE.value(A_BOLD));
|
||||
.append(lnav::roles::symbol(ht.ht_name));
|
||||
for (const auto& param : ht.ht_parameters) {
|
||||
out.append(" ");
|
||||
if (param.ht_nargs == help_nargs_t::HN_OPTIONAL) {
|
||||
out.append("[");
|
||||
}
|
||||
out.append(param.ht_name,
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append(lnav::roles::variable(param.ht_name));
|
||||
if (param.ht_nargs == help_nargs_t::HN_OPTIONAL) {
|
||||
out.append("]");
|
||||
}
|
||||
if (param.ht_nargs == help_nargs_t::HN_ONE_OR_MORE) {
|
||||
out.append("1", view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append("1"_variable);
|
||||
out.append(" [");
|
||||
out.append("...", view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append("..."_variable);
|
||||
out.append(" ");
|
||||
out.append(param.ht_name,
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append("N", view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append(lnav::roles::variable(param.ht_name));
|
||||
out.append("N"_variable);
|
||||
out.append("]");
|
||||
}
|
||||
}
|
||||
|
@ -222,12 +216,14 @@ format_help_text_for_term(const help_text& ht,
|
|||
bool is_infix = ht.ht_context == help_context_t::HC_SQL_INFIX;
|
||||
|
||||
if (!synopsis_only) {
|
||||
out.append("Synopsis", view_curses::VC_STYLE.value(A_UNDERLINE))
|
||||
.append("\n");
|
||||
out.append("Synopsis"_h2).append("\n");
|
||||
}
|
||||
out.append(body_indent, ' ');
|
||||
if (is_infix) {
|
||||
out.append(ht.ht_name);
|
||||
} else {
|
||||
out.append(lnav::roles::keyword(ht.ht_name));
|
||||
}
|
||||
out.append(body_indent, ' ')
|
||||
.append(ht.ht_name,
|
||||
view_curses::VC_STYLE.value(is_infix ? 0 : A_BOLD));
|
||||
for (const auto& param : ht.ht_parameters) {
|
||||
if (break_all
|
||||
|| (int) (out.get_string().length() - start_index
|
||||
|
@ -249,33 +245,29 @@ format_help_text_for_term(const help_text& ht,
|
|||
}
|
||||
if (param.ht_flag_name) {
|
||||
out.ensure_space().append(
|
||||
param.ht_flag_name,
|
||||
view_curses::VC_STYLE.value(A_BOLD));
|
||||
lnav::roles::keyword(param.ht_flag_name));
|
||||
}
|
||||
if (param.ht_group_start) {
|
||||
out.ensure_space().append(
|
||||
param.ht_group_start,
|
||||
view_curses::VC_STYLE.value(A_BOLD));
|
||||
lnav::roles::keyword(param.ht_group_start));
|
||||
}
|
||||
if (param.ht_name[0]) {
|
||||
out.ensure_space().append(
|
||||
param.ht_name,
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
lnav::roles::variable(param.ht_name));
|
||||
if (!param.ht_parameters.empty()) {
|
||||
if (param.ht_nargs == help_nargs_t::HN_ZERO_OR_MORE
|
||||
|| param.ht_nargs == help_nargs_t::HN_ONE_OR_MORE)
|
||||
{
|
||||
out.append(
|
||||
"1", view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append("1"_variable);
|
||||
}
|
||||
if (param.ht_parameters[0].ht_flag_name) {
|
||||
out.append(" ")
|
||||
.append(param.ht_parameters[0].ht_flag_name,
|
||||
view_curses::VC_STYLE.value(A_BOLD))
|
||||
.append(lnav::roles::keyword(
|
||||
param.ht_parameters[0].ht_flag_name))
|
||||
.append(" ");
|
||||
}
|
||||
out.append(param.ht_parameters[0].ht_name,
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append(lnav::roles::variable(
|
||||
param.ht_parameters[0].ht_name));
|
||||
}
|
||||
}
|
||||
if (param.ht_nargs == help_nargs_t::HN_ZERO_OR_MORE
|
||||
|
@ -284,38 +276,35 @@ format_help_text_for_term(const help_text& ht,
|
|||
bool needs_comma = param.ht_parameters.empty()
|
||||
|| !param.ht_flag_name;
|
||||
|
||||
out.append("1", view_curses::VC_STYLE.value(A_UNDERLINE))
|
||||
out.append("1"_variable)
|
||||
.append(" [")
|
||||
.append(needs_comma ? ", " : "")
|
||||
.append("...")
|
||||
.append(needs_comma ? "" : " ")
|
||||
.append((needs_comma || !param.ht_flag_name)
|
||||
? ""
|
||||
: param.ht_flag_name,
|
||||
view_curses::VC_STYLE.value(A_BOLD))
|
||||
.append(lnav::roles::keyword(
|
||||
(needs_comma || !param.ht_flag_name)
|
||||
? ""
|
||||
: param.ht_flag_name))
|
||||
.append(" ")
|
||||
.append(param.ht_name,
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE))
|
||||
.append("N", view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
.append(lnav::roles::variable(param.ht_name))
|
||||
.append("N"_variable);
|
||||
if (!param.ht_parameters.empty()) {
|
||||
if (param.ht_parameters[0].ht_flag_name) {
|
||||
out.append(" ")
|
||||
.append(param.ht_parameters[0].ht_flag_name,
|
||||
view_curses::VC_STYLE.value(A_BOLD))
|
||||
.append(lnav::roles::keyword(
|
||||
param.ht_parameters[0].ht_flag_name))
|
||||
.append(" ");
|
||||
}
|
||||
|
||||
out.append(param.ht_parameters[0].ht_name,
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE))
|
||||
.append("N",
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE));
|
||||
out.append(lnav::roles::variable(
|
||||
param.ht_parameters[0].ht_name))
|
||||
.append("N"_variable);
|
||||
}
|
||||
out.append("]");
|
||||
}
|
||||
if (param.ht_group_end) {
|
||||
out.ensure_space().append(
|
||||
param.ht_group_end,
|
||||
view_curses::VC_STYLE.value(A_BOLD));
|
||||
lnav::roles::keyword(param.ht_group_end));
|
||||
}
|
||||
if (param.ht_nargs == help_nargs_t::HN_ZERO_OR_MORE
|
||||
|| param.ht_nargs == help_nargs_t::HN_OPTIONAL)
|
||||
|
@ -345,8 +334,8 @@ format_help_text_for_term(const help_text& ht,
|
|||
= std::max(strlen(param.ht_name), max_param_name_width);
|
||||
}
|
||||
|
||||
out.append(ht.ht_parameters.size() == 1 ? "Parameter" : "Parameters",
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE))
|
||||
out.append(ht.ht_parameters.size() == 1 ? "Parameter"_h2
|
||||
: "Parameters"_h2)
|
||||
.append("\n");
|
||||
|
||||
for (const auto& param : ht.ht_parameters) {
|
||||
|
@ -355,10 +344,7 @@ format_help_text_for_term(const help_text& ht,
|
|||
}
|
||||
|
||||
out.append(body_indent, ' ')
|
||||
.append(
|
||||
param.ht_name,
|
||||
view_curses::VC_STYLE.value(
|
||||
vc.attrs_for_role(view_colors::VCR_VARIABLE) | A_BOLD))
|
||||
.append(lnav::roles::variable(param.ht_name))
|
||||
.append(max_param_name_width - strlen(param.ht_name), ' ')
|
||||
.append(" ")
|
||||
.append(attr_line_t::from_ansi_str(param.ht_summary),
|
||||
|
@ -374,8 +360,7 @@ format_help_text_for_term(const help_text& ht,
|
|||
= std::max(strlen(result.ht_name), max_result_name_width);
|
||||
}
|
||||
|
||||
out.append(ht.ht_results.size() == 1 ? "Result" : "Results",
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE))
|
||||
out.append(ht.ht_results.size() == 1 ? "Result"_h2 : "Results"_h2)
|
||||
.append("\n");
|
||||
|
||||
for (const auto& result : ht.ht_results) {
|
||||
|
@ -384,10 +369,7 @@ format_help_text_for_term(const help_text& ht,
|
|||
}
|
||||
|
||||
out.append(body_indent, ' ')
|
||||
.append(
|
||||
result.ht_name,
|
||||
view_curses::VC_STYLE.value(
|
||||
vc.attrs_for_role(view_colors::VCR_VARIABLE) | A_BOLD))
|
||||
.append(lnav::roles::variable(result.ht_name))
|
||||
.append(max_result_name_width - strlen(result.ht_name), ' ')
|
||||
.append(" ")
|
||||
.append(attr_line_t::from_ansi_str(result.ht_summary),
|
||||
|
@ -416,9 +398,7 @@ format_help_text_for_term(const help_text& ht,
|
|||
}
|
||||
stable_sort(related_refs.begin(), related_refs.end());
|
||||
|
||||
out.append("See Also", view_curses::VC_STYLE.value(A_UNDERLINE))
|
||||
.append("\n")
|
||||
.append(body_indent, ' ');
|
||||
out.append("See Also"_h2).append("\n").append(body_indent, ' ');
|
||||
|
||||
bool first = true;
|
||||
size_t line_start = out.length();
|
||||
|
@ -430,7 +410,7 @@ format_help_text_for_term(const help_text& ht,
|
|||
out.append("\n").append(body_indent, ' ');
|
||||
line_start = out.length();
|
||||
}
|
||||
out.append(ref, view_curses::VC_STYLE.value(A_BOLD));
|
||||
out.append(lnav::roles::symbol(ref));
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
@ -449,8 +429,7 @@ format_example_text_for_term(const help_text& ht,
|
|||
if (!ht.ht_example.empty()) {
|
||||
int count = 1;
|
||||
|
||||
out.append(ht.ht_example.size() == 1 ? "Example" : "Examples",
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE))
|
||||
out.append(ht.ht_example.size() == 1 ? "Example"_h2 : "Examples"_h2)
|
||||
.append("\n");
|
||||
for (const auto& ex : ht.ht_example) {
|
||||
attr_line_t ex_line(ex.he_cmd);
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
#include <functional>
|
||||
|
||||
#include "attr_line.hh"
|
||||
#include "base/attr_line.hh"
|
||||
#include "help_text.hh"
|
||||
|
||||
using help_example_to_attr_line_fun_t
|
||||
|
|
|
@ -132,7 +132,7 @@ highlighter::annotate(attr_line_t& al, int start) const
|
|||
if (lr.lr_end > lr.lr_start
|
||||
&& (this->h_nestable
|
||||
|| find_string_attr_containing(
|
||||
sa, &view_curses::VC_STYLE, lr)
|
||||
sa, &VC_STYLE, lr)
|
||||
== sa.end()))
|
||||
{
|
||||
int attrs = 0;
|
||||
|
@ -142,20 +142,20 @@ highlighter::annotate(attr_line_t& al, int start) const
|
|||
}
|
||||
if (!this->h_fg.empty()) {
|
||||
sa.emplace_back(lr,
|
||||
view_curses::VC_FOREGROUND.value(
|
||||
VC_FOREGROUND.value(
|
||||
vc.match_color(this->h_fg)));
|
||||
}
|
||||
if (!this->h_bg.empty()) {
|
||||
sa.emplace_back(lr,
|
||||
view_curses::VC_BACKGROUND.value(
|
||||
VC_BACKGROUND.value(
|
||||
vc.match_color(this->h_bg)));
|
||||
}
|
||||
if (this->h_role != view_colors::VCR_NONE) {
|
||||
if (this->h_role != role_t::VCR_NONE) {
|
||||
sa.emplace_back(lr,
|
||||
view_curses::VC_ROLE.value(this->h_role));
|
||||
VC_ROLE.value(this->h_role));
|
||||
}
|
||||
if (attrs) {
|
||||
sa.emplace_back(lr, view_curses::VC_STYLE.value(attrs));
|
||||
sa.emplace_back(lr, VC_STYLE.value(attrs));
|
||||
}
|
||||
|
||||
off = matches[1];
|
||||
|
|
|
@ -70,7 +70,7 @@ struct highlighter {
|
|||
return *this;
|
||||
}
|
||||
|
||||
highlighter& with_role(view_colors::role_t role)
|
||||
highlighter& with_role(role_t role)
|
||||
{
|
||||
this->h_role = role;
|
||||
|
||||
|
@ -123,7 +123,7 @@ struct highlighter {
|
|||
void annotate(attr_line_t& al, int start) const;
|
||||
|
||||
std::string h_pattern;
|
||||
view_colors::role_t h_role{view_colors::VCR_NONE};
|
||||
role_t h_role{role_t::VCR_NONE};
|
||||
styling::color_unit h_fg{styling::color_unit::make_empty()};
|
||||
styling::color_unit h_bg{styling::color_unit::make_empty()};
|
||||
pcre* h_code;
|
||||
|
|
|
@ -135,13 +135,13 @@ hist_source2::init()
|
|||
|
||||
this->hs_chart
|
||||
.with_attrs_for_ident(HT_NORMAL,
|
||||
vc.attrs_for_role(view_colors::VCR_TEXT))
|
||||
vc.attrs_for_role(role_t::VCR_TEXT))
|
||||
.with_attrs_for_ident(HT_WARNING,
|
||||
vc.attrs_for_role(view_colors::VCR_WARNING))
|
||||
vc.attrs_for_role(role_t::VCR_WARNING))
|
||||
.with_attrs_for_ident(HT_ERROR,
|
||||
vc.attrs_for_role(view_colors::VCR_ERROR))
|
||||
vc.attrs_for_role(role_t::VCR_ERROR))
|
||||
.with_attrs_for_ident(HT_MARK,
|
||||
vc.attrs_for_role(view_colors::VCR_KEYWORD));
|
||||
vc.attrs_for_role(role_t::VCR_KEYWORD));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -62,7 +62,7 @@ struct stacked_bar_chart_base {
|
|||
explicit show_one(int so_index) : so_index(so_index) {}
|
||||
};
|
||||
|
||||
typedef mapbox::util::variant<show_none, show_all, show_one> show_state;
|
||||
using show_state = mapbox::util::variant<show_none, show_all, show_one>;
|
||||
|
||||
enum class direction {
|
||||
forward,
|
||||
|
@ -228,7 +228,7 @@ public:
|
|||
|
||||
if (ci.ci_attrs != 0) {
|
||||
value_out.emplace_back(
|
||||
lr, view_curses::VC_STYLE.value(ci.ci_attrs | A_REVERSE));
|
||||
lr, VC_STYLE.value(ci.ci_attrs | A_REVERSE));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -328,7 +328,7 @@ public:
|
|||
hist_source2()
|
||||
{
|
||||
this->clear();
|
||||
};
|
||||
}
|
||||
|
||||
~hist_source2() override = default;
|
||||
|
||||
|
@ -337,22 +337,22 @@ public:
|
|||
void set_time_slice(int64_t slice)
|
||||
{
|
||||
this->hs_time_slice = slice;
|
||||
};
|
||||
}
|
||||
|
||||
int64_t get_time_slice() const
|
||||
{
|
||||
return this->hs_time_slice;
|
||||
};
|
||||
}
|
||||
|
||||
size_t text_line_count() override
|
||||
{
|
||||
return this->hs_line_count;
|
||||
};
|
||||
}
|
||||
|
||||
size_t text_line_width(textview_curses& curses) override
|
||||
{
|
||||
return 48 + 8 * 4;
|
||||
};
|
||||
}
|
||||
|
||||
void clear();
|
||||
|
||||
|
@ -374,7 +374,7 @@ public:
|
|||
line_flags_t flags) override
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
nonstd::optional<struct timeval> time_for_row(vis_line_t row) override;
|
||||
|
||||
|
@ -397,7 +397,7 @@ private:
|
|||
bucket_block()
|
||||
{
|
||||
memset(this->bb_buckets, 0, sizeof(this->bb_buckets));
|
||||
};
|
||||
}
|
||||
|
||||
unsigned int bb_used{0};
|
||||
bucket_t bb_buckets[BLOCK_SIZE];
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "hotkeys.hh"
|
||||
|
||||
#include "base/ansi_scrubber.hh"
|
||||
#include "base/injector.hh"
|
||||
#include "base/math_util.hh"
|
||||
#include "base/opt_util.hh"
|
||||
|
|
|
@ -318,11 +318,12 @@ SELECT *result-column* FROM *table* WHERE *\[cond\]* GROUP BY *grouping-expr* OR
|
|||
Query the database and return zero or more rows of data.
|
||||
|
||||
**Parameters**
|
||||
* **result-column** --- The expression used to generate a result for this column.
|
||||
* **table** --- The table(s) to query for data
|
||||
* **cond** --- The conditions used to select the rows to return.
|
||||
* **grouping-expr** --- The expression to use when grouping rows.
|
||||
* **ordering-term** --- The values to use when ordering the result set.
|
||||
* **limit-expr** --- The maximum number of rows to return
|
||||
* **limit-expr** --- The maximum number of rows to return.
|
||||
|
||||
**Examples**
|
||||
To select all of the columns from the table 'syslog_log':
|
||||
|
|
|
@ -40,8 +40,8 @@
|
|||
#include <unistd.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "auto_mem.hh"
|
||||
#include "base/auto_fd.hh"
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/file_range.hh"
|
||||
#include "base/lnav_log.hh"
|
||||
#include "base/result.h"
|
||||
|
|
|
@ -275,8 +275,8 @@ listview_curses::do_update()
|
|||
gutter_y++)
|
||||
{
|
||||
int range_start = 0, range_end;
|
||||
view_colors::role_t role = this->vc_default_role;
|
||||
view_colors::role_t bar_role = view_colors::VCR_SCROLLBAR;
|
||||
role_t role = this->vc_default_role;
|
||||
role_t bar_role = role_t::VCR_SCROLLBAR;
|
||||
int attrs;
|
||||
chtype ch = ACS_VLINE;
|
||||
|
||||
|
|
|
@ -90,8 +90,8 @@ public:
|
|||
int start,
|
||||
int end,
|
||||
chtype& ch_out,
|
||||
view_colors::role_t& role_out,
|
||||
view_colors::role_t& bar_role_out)
|
||||
role_t& role_out,
|
||||
role_t& bar_role_out)
|
||||
{
|
||||
ch_out = ACS_VLINE;
|
||||
};
|
||||
|
|
286
src/lnav.cc
286
src/lnav.cc
|
@ -74,14 +74,16 @@
|
|||
#endif
|
||||
|
||||
#include "all_logs_vtab.hh"
|
||||
#include "ansi_scrubber.hh"
|
||||
#include "base/ansi_scrubber.hh"
|
||||
#include "base/fs_util.hh"
|
||||
#include "base/func_util.hh"
|
||||
#include "base/future_util.hh"
|
||||
#include "base/humanize.hh"
|
||||
#include "base/humanize.network.hh"
|
||||
#include "base/humanize.time.hh"
|
||||
#include "base/injector.bind.hh"
|
||||
#include "base/isc.hh"
|
||||
#include "base/lnav.console.hh"
|
||||
#include "base/lnav_log.hh"
|
||||
#include "base/paths.hh"
|
||||
#include "base/string_util.hh"
|
||||
|
@ -155,6 +157,7 @@
|
|||
#endif
|
||||
|
||||
using namespace std::literals::chrono_literals;
|
||||
using namespace lnav::roles::literals;
|
||||
|
||||
static bool initial_build = false;
|
||||
static std::multimap<lnav_flags_t, std::string> DEFAULT_FILES;
|
||||
|
@ -177,18 +180,20 @@ const int ZOOM_LEVELS[] = {
|
|||
|
||||
const ssize_t ZOOM_COUNT = sizeof(ZOOM_LEVELS) / sizeof(int);
|
||||
|
||||
const char* lnav_zoom_strings[] = {"1-second",
|
||||
"30-second",
|
||||
"1-minute",
|
||||
"5-minute",
|
||||
"15-minute",
|
||||
"1-hour",
|
||||
"4-hour",
|
||||
"8-hour",
|
||||
"1-day",
|
||||
"1-week",
|
||||
const char* lnav_zoom_strings[] = {
|
||||
"1-second",
|
||||
"30-second",
|
||||
"1-minute",
|
||||
"5-minute",
|
||||
"15-minute",
|
||||
"1-hour",
|
||||
"4-hour",
|
||||
"8-hour",
|
||||
"1-day",
|
||||
"1-week",
|
||||
|
||||
nullptr};
|
||||
nullptr,
|
||||
};
|
||||
|
||||
static const char* view_titles[LNV__MAX] = {
|
||||
"LOG",
|
||||
|
@ -299,12 +304,14 @@ bool
|
|||
setup_logline_table(exec_context& ec)
|
||||
{
|
||||
// Hidden columns don't show up in the table_info pragma.
|
||||
static const char* hidden_table_columns[] = {"log_time_msecs",
|
||||
"log_path",
|
||||
"log_text",
|
||||
"log_body",
|
||||
static const char* hidden_table_columns[] = {
|
||||
"log_time_msecs",
|
||||
"log_path",
|
||||
"log_text",
|
||||
"log_body",
|
||||
|
||||
nullptr};
|
||||
nullptr,
|
||||
};
|
||||
|
||||
textview_curses& log_view = lnav_data.ld_views[LNV_LOG];
|
||||
bool retval = false;
|
||||
|
@ -751,15 +758,11 @@ append_default_files(lnav_flags_t flag)
|
|||
if (lnav_data.ld_flags & flag) {
|
||||
auto cwd = ghc::filesystem::current_path();
|
||||
|
||||
std::pair<std::multimap<lnav_flags_t, std::string>::iterator,
|
||||
std::multimap<lnav_flags_t, std::string>::iterator>
|
||||
range;
|
||||
for (range = DEFAULT_FILES.equal_range(flag);
|
||||
for (auto range = DEFAULT_FILES.equal_range(flag);
|
||||
range.first != range.second;
|
||||
range.first++)
|
||||
{
|
||||
std::string path = range.first->second;
|
||||
struct stat st;
|
||||
auto path = range.first->second;
|
||||
|
||||
if (access(path.c_str(), R_OK) == 0) {
|
||||
auto_mem<char> abspath;
|
||||
|
@ -770,11 +773,13 @@ append_default_files(lnav_flags_t flag)
|
|||
} else {
|
||||
lnav_data.ld_active_files.fc_file_names[abspath.in()];
|
||||
}
|
||||
} else if (stat(path.c_str(), &st) == 0) {
|
||||
fprintf(stderr,
|
||||
"error: cannot read -- %s%s\n",
|
||||
cwd.c_str(),
|
||||
path.c_str());
|
||||
} else if (lnav::filesystem::stat_file(path).isOk()) {
|
||||
lnav::console::print(
|
||||
stderr,
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("default syslog file is not readable -- ")
|
||||
.append(lnav::roles::file(cwd))
|
||||
.append(lnav::roles::file(path))));
|
||||
retval = false;
|
||||
}
|
||||
}
|
||||
|
@ -842,6 +847,27 @@ rl_blur(readline_curses* rc)
|
|||
|
||||
readline_context::command_map_t lnav_commands;
|
||||
|
||||
static attr_line_t
|
||||
command_arg_help()
|
||||
{
|
||||
return attr_line_t()
|
||||
.append(
|
||||
"command arguments must start with one of the following symbols "
|
||||
"to denote the type of command:\n")
|
||||
.append(" ")
|
||||
.append(":"_symbol)
|
||||
.append(" - ")
|
||||
.append("an lnav command (e.g. :goto 42)\n")
|
||||
.append(" ")
|
||||
.append(";"_symbol)
|
||||
.append(" - ")
|
||||
.append("an SQL statement (e.g. SELECT * FROM syslog_log)\n")
|
||||
.append(" ")
|
||||
.append("|"_symbol)
|
||||
.append(" - ")
|
||||
.append("an lnav script (e.g. |rename-stdin foo)\n");
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
|
@ -1045,9 +1071,7 @@ public:
|
|||
me.me_y = y - tc->get_y() - 1;
|
||||
|
||||
tc->handle_mouse(me);
|
||||
};
|
||||
|
||||
private:
|
||||
}
|
||||
};
|
||||
|
||||
static bool
|
||||
|
@ -1512,6 +1536,8 @@ looper()
|
|||
highlight_source_t::THEME);
|
||||
lnav_data.ld_files_view.set_overlay_source(&lnav_data.ld_files_overlay);
|
||||
|
||||
lnav_data.ld_user_message_view.set_window(lnav_data.ld_window);
|
||||
|
||||
lnav_data.ld_status[LNS_TOP].set_top(0);
|
||||
lnav_data.ld_status[LNS_BOTTOM].set_top(-(rlc.get_height() + 1));
|
||||
for (auto& sc : lnav_data.ld_status) {
|
||||
|
@ -1530,6 +1556,7 @@ looper()
|
|||
&lnav_data.ld_preview_status_source);
|
||||
|
||||
lnav_data.ld_match_view.set_show_bottom_border(true);
|
||||
lnav_data.ld_user_message_view.set_show_bottom_border(true);
|
||||
|
||||
for (auto& sc : lnav_data.ld_status) {
|
||||
sc.window_change();
|
||||
|
@ -1713,6 +1740,7 @@ looper()
|
|||
lnav_data.ld_example_view.do_update();
|
||||
lnav_data.ld_match_view.do_update();
|
||||
lnav_data.ld_preview_view.do_update();
|
||||
lnav_data.ld_user_message_view.do_update();
|
||||
if (ui_clock::now() >= next_status_update_time) {
|
||||
for (auto& sc : lnav_data.ld_status) {
|
||||
sc.do_update();
|
||||
|
@ -1824,6 +1852,8 @@ looper()
|
|||
ch, tc->get_top());
|
||||
};
|
||||
|
||||
lnav_data.ld_user_message_source.clear();
|
||||
|
||||
if (!lnav_data.ld_looping) {
|
||||
// No reason to keep processing input after the
|
||||
// user has quit. The view stack will also be
|
||||
|
@ -1953,8 +1983,9 @@ looper()
|
|||
|
||||
if (initial_build) {
|
||||
static bool ran_cleanup = false;
|
||||
std::vector<std::pair<Result<std::string, std::string>,
|
||||
std::string>>
|
||||
std::vector<std::pair<
|
||||
Result<std::string, lnav::console::user_message>,
|
||||
std::string>>
|
||||
cmd_results;
|
||||
|
||||
execute_init_commands(ec, cmd_results);
|
||||
|
@ -2024,6 +2055,7 @@ looper()
|
|||
lnav_data.ld_match_view.set_needs_update();
|
||||
lnav_data.ld_filter_view.set_needs_update();
|
||||
lnav_data.ld_files_view.set_needs_update();
|
||||
lnav_data.ld_user_message_view.set_needs_update();
|
||||
}
|
||||
|
||||
if (lnav_data.ld_child_terminated) {
|
||||
|
@ -2127,20 +2159,18 @@ get_textview_for_mode(ln_mode_t mode)
|
|||
}
|
||||
|
||||
static void
|
||||
print_errors(std::vector<std::string> error_list)
|
||||
print_errors(std::vector<lnav::console::user_message> error_list)
|
||||
{
|
||||
for (auto& iter : error_list) {
|
||||
fprintf(stderr,
|
||||
"%s%s",
|
||||
iter.c_str(),
|
||||
iter[iter.size() - 1] == '\n' ? "" : "\n");
|
||||
lnav::console::print(stderr, iter);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
std::vector<std::string> config_errors, loader_errors;
|
||||
std::vector<lnav::console::user_message> config_errors;
|
||||
std::vector<lnav::console::user_message> loader_errors;
|
||||
exec_context& ec = lnav_data.ld_exec_context;
|
||||
int lpc, c, retval = EXIT_SUCCESS;
|
||||
|
||||
|
@ -2223,15 +2253,22 @@ main(int argc, char* argv[])
|
|||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(
|
||||
lnav::console::print(
|
||||
stderr,
|
||||
"error: command arguments should start with a "
|
||||
"colon, semi-colon, or pipe-symbol to denote:\n");
|
||||
fprintf(stderr,
|
||||
"error: a built-in command, SQL query, "
|
||||
"or a file path that contains commands to "
|
||||
"execute\n");
|
||||
usage();
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("invalid value for ")
|
||||
.append_quoted("-c"_symbol)
|
||||
.append(" option"))
|
||||
.with_snippet(lnav::console::snippet::from(
|
||||
"arg",
|
||||
attr_line_t(" -c ")
|
||||
.append(optarg)
|
||||
.append("\n")
|
||||
.append(4, ' ')
|
||||
.append(lnav::roles::error(
|
||||
"^ command type prefix "
|
||||
"is missing"))))
|
||||
.with_help(command_arg_help()));
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
|
@ -2244,12 +2281,18 @@ main(int argc, char* argv[])
|
|||
|| strcmp("/dev/stdin", optarg) == 0) {
|
||||
exec_stdin = true;
|
||||
}
|
||||
lnav_data.ld_commands.push_back("|" + std::string(optarg));
|
||||
lnav_data.ld_commands.emplace_back(
|
||||
fmt::format(FMT_STRING("|{}"), optarg));
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
if (access(optarg, X_OK) != 0) {
|
||||
perror("invalid config path");
|
||||
lnav::console::print(
|
||||
stderr,
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("invalid configuration directory: ")
|
||||
.append(lnav::roles::file(optarg)))
|
||||
.with_errno_reason());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
lnav_data.ld_config_paths.emplace_back(optarg);
|
||||
|
@ -2305,14 +2348,15 @@ main(int argc, char* argv[])
|
|||
if (isatty(STDIN_FILENO) && read(STDIN_FILENO, &b, 1) == -1) {
|
||||
perror("Read key from STDIN");
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'v':
|
||||
lnav_data.ld_flags |= LNF_VERBOSE;
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
printf("%s\n", VCS_PACKAGE_STRING);
|
||||
fmt::print("{}\n", VCS_PACKAGE_STRING);
|
||||
exit(0);
|
||||
break;
|
||||
|
||||
|
@ -2361,7 +2405,26 @@ main(int argc, char* argv[])
|
|||
= lnav::paths::dotlnav() / "configs/installed";
|
||||
|
||||
if (argc == 0) {
|
||||
fprintf(stderr, "error: expecting file format paths\n");
|
||||
const auto install_reason
|
||||
= attr_line_t("the ")
|
||||
.append("-i"_symbol)
|
||||
.append(
|
||||
" option expects one or more log format definition "
|
||||
"files to install in your lnav configuration "
|
||||
"directory");
|
||||
const auto install_help
|
||||
= attr_line_t(
|
||||
"log format definitions are JSON files that tell lnav "
|
||||
"how to understand log files\n")
|
||||
.append(
|
||||
"See: https://docs.lnav.org/en/latest/formats.html");
|
||||
|
||||
lnav::console::print(stderr,
|
||||
lnav::console::user_message::error(
|
||||
"missing format files to install")
|
||||
.with_reason(install_reason)
|
||||
.with_help(install_help));
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -2380,27 +2443,35 @@ main(int argc, char* argv[])
|
|||
|
||||
auto file_type_result = detect_config_file_type(argv[lpc]);
|
||||
if (file_type_result.isErr()) {
|
||||
fprintf(stderr,
|
||||
"error: %s\n",
|
||||
file_type_result.unwrapErr().c_str());
|
||||
lnav::console::print(
|
||||
stderr,
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("unable to open configuration file: ")
|
||||
.append(lnav::roles::file(argv[lpc])))
|
||||
.with_reason(file_type_result.unwrapErr()));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto file_type = file_type_result.unwrap();
|
||||
|
||||
std::string dst_name;
|
||||
auto src_path = ghc::filesystem::path(argv[lpc]);
|
||||
ghc::filesystem::path dst_name;
|
||||
if (file_type == config_file_type::CONFIG) {
|
||||
dst_name = basename(argv[lpc]);
|
||||
dst_name = src_path.filename();
|
||||
} else {
|
||||
std::vector<intern_string_t> format_list
|
||||
= load_format_file(argv[lpc], loader_errors);
|
||||
auto format_list = load_format_file(src_path, loader_errors);
|
||||
|
||||
if (!loader_errors.empty()) {
|
||||
print_errors(loader_errors);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (format_list.empty()) {
|
||||
fprintf(
|
||||
stderr, "error: format file is empty: %s\n", argv[lpc]);
|
||||
lnav::console::print(
|
||||
stderr,
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("invalid format file: ")
|
||||
.append(lnav::roles::file(src_path.string())))
|
||||
.with_reason("there must be at least one format "
|
||||
"definition in the file"));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -2442,7 +2513,11 @@ main(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "info: installed: %s\n", dst_path.c_str());
|
||||
lnav::console::print(
|
||||
stderr,
|
||||
lnav::console::user_message::ok(
|
||||
attr_line_t("installed -- ")
|
||||
.append(lnav::roles::file(dst_path))));
|
||||
}
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
|
@ -2541,6 +2616,8 @@ main(int argc, char* argv[])
|
|||
.add_child_view(&lnav_data.ld_filter_source.fss_editor);
|
||||
lnav_data.ld_files_view.set_sub_source(&lnav_data.ld_files_source)
|
||||
.add_input_delegate(lnav_data.ld_files_source);
|
||||
lnav_data.ld_user_message_view.set_sub_source(
|
||||
&lnav_data.ld_user_message_source);
|
||||
|
||||
for (lpc = 0; lpc < LNV__MAX; lpc++) {
|
||||
lnav_data.ld_views[lpc].set_gutter_source(new log_gutter_source());
|
||||
|
@ -2775,26 +2852,31 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
|
|||
lnav_data.ld_active_files.fc_file_names[argv[lpc]].with_tail(
|
||||
!(lnav_data.ld_flags & LNF_HEADLESS));
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Cannot stat file: %s -- %s\n",
|
||||
argv[lpc],
|
||||
strerror(errno));
|
||||
lnav::console::print(
|
||||
stderr,
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("unable to open file: ")
|
||||
.append(lnav::roles::file(argv[lpc])))
|
||||
.with_errno_reason());
|
||||
retval = EXIT_FAILURE;
|
||||
}
|
||||
} else if (access(argv[lpc], R_OK) == -1) {
|
||||
fprintf(stderr,
|
||||
"Cannot read file: %s -- %s\n",
|
||||
argv[lpc],
|
||||
strerror(errno));
|
||||
lnav::console::print(stderr,
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("cannot read file: ")
|
||||
.append(lnav::roles::file(argv[lpc])))
|
||||
.with_errno_reason());
|
||||
retval = EXIT_FAILURE;
|
||||
} else if (S_ISFIFO(st.st_mode)) {
|
||||
auto_fd fifo_fd;
|
||||
|
||||
if ((fifo_fd = open(argv[lpc], O_RDONLY)) == -1) {
|
||||
fprintf(stderr,
|
||||
"Cannot open fifo: %s -- %s\n",
|
||||
argv[lpc],
|
||||
strerror(errno));
|
||||
lnav::console::print(
|
||||
stderr,
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("cannot open fifo: ")
|
||||
.append(lnav::roles::file(argv[lpc])))
|
||||
.with_errno_reason());
|
||||
retval = EXIT_FAILURE;
|
||||
} else {
|
||||
auto fifo_tmp_fd
|
||||
|
@ -2901,7 +2983,15 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
|
|||
if (!(lnav_data.ld_flags & (LNF_HEADLESS | LNF_CHECK_CONFIG))
|
||||
&& !isatty(STDOUT_FILENO))
|
||||
{
|
||||
fprintf(stderr, "error: stdout is not a tty.\n");
|
||||
lnav::console::print(
|
||||
stderr,
|
||||
lnav::console::user_message::error(
|
||||
"unable to display interactive text UI")
|
||||
.with_reason("stdout is not a TTY")
|
||||
.with_help(attr_line_t("pass the ")
|
||||
.append("-n"_symbol)
|
||||
.append(" option to run lnav in headless mode "
|
||||
"or don't redirect stdout")));
|
||||
retval = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -2955,7 +3045,9 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
|
|||
&& lnav_data.ld_commands.empty() && lnav_data.ld_pt_search.empty()
|
||||
&& !(lnav_data.ld_flags & (LNF_HELP | LNF_NO_DEFAULT)))
|
||||
{
|
||||
fprintf(stderr, "error: no log files given/found.\n");
|
||||
lnav::console::print(
|
||||
stderr,
|
||||
lnav::console::user_message::error("no log files given/found"));
|
||||
retval = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -3002,7 +3094,8 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
|
|||
|
||||
if (lnav_data.ld_flags & LNF_HEADLESS) {
|
||||
std::vector<
|
||||
std::pair<Result<std::string, std::string>, std::string>>
|
||||
std::pair<Result<std::string, lnav::console::user_message>,
|
||||
std::string>>
|
||||
cmd_results;
|
||||
textview_curses *log_tc, *text_tc, *tc;
|
||||
bool output_view = true;
|
||||
|
@ -3012,10 +3105,12 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
|
|||
if (!lnav_data.ld_active_files.fc_name_to_errors.empty()) {
|
||||
for (const auto& pair :
|
||||
lnav_data.ld_active_files.fc_name_to_errors) {
|
||||
fprintf(stderr,
|
||||
"error: unable to open file: %s -- %s\n",
|
||||
pair.first.c_str(),
|
||||
pair.second.fei_description.c_str());
|
||||
lnav::console::print(
|
||||
stderr,
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("unable to open file: ")
|
||||
.append(lnav::roles::file(pair.first)))
|
||||
.with_reason(pair.second.fei_description));
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
|
@ -3064,7 +3159,7 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
|
|||
|
||||
for (auto& pair : cmd_results) {
|
||||
if (pair.first.isErr()) {
|
||||
fprintf(stderr, "%s\n", pair.first.unwrapErr().c_str());
|
||||
lnav::console::print(stderr, pair.first.unwrapErr());
|
||||
output_view = false;
|
||||
} else {
|
||||
auto msg = pair.first.unwrap();
|
||||
|
@ -3182,27 +3277,36 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
|
|||
&& !(lnav_data.ld_flags & LNF_QUIET)
|
||||
&& !(lnav_data.ld_flags & LNF_HEADLESS))
|
||||
{
|
||||
if (ghc::filesystem::file_size(stdin_tmp_path)
|
||||
> MAX_STDIN_CAPTURE_SIZE) {
|
||||
ghc::filesystem::permissions(stdin_tmp_path,
|
||||
ghc::filesystem::perms::owner_read);
|
||||
auto stdin_size = ghc::filesystem::file_size(stdin_tmp_path);
|
||||
if (stdin_size > MAX_STDIN_CAPTURE_SIZE) {
|
||||
log_info("not saving large stdin capture -- %s",
|
||||
stdin_tmp_path.c_str());
|
||||
ghc::filesystem::remove(stdin_tmp_path);
|
||||
} else {
|
||||
auto home = getenv("HOME");
|
||||
auto home = getenv_opt("HOME");
|
||||
auto path_str = stdin_tmp_path.string();
|
||||
|
||||
if (home != nullptr && startswith(path_str, home)) {
|
||||
path_str = path_str.substr(strlen(home));
|
||||
if (home && startswith(path_str, home.value())) {
|
||||
path_str = path_str.substr(strlen(home.value()));
|
||||
if (path_str[0] != '/') {
|
||||
path_str.insert(0, 1, '/');
|
||||
}
|
||||
path_str.insert(0, 1, '~');
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"info: stdin was captured, you can reopen it using -- "
|
||||
"lnav %s\n",
|
||||
path_str.c_str());
|
||||
lnav::console::print(
|
||||
stderr,
|
||||
lnav::console::user_message::info(
|
||||
attr_line_t()
|
||||
.append(lnav::roles::number(humanize::file_size(
|
||||
stdin_size, humanize::alignment::none)))
|
||||
.append(" of data from stdin was captured and "
|
||||
"will be saved for one day. You can "
|
||||
"reopen it by running:\n")
|
||||
.append(" {} ", lnav_data.ld_program_name)
|
||||
.append(lnav::roles::file(path_str))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <sys/time.h>
|
||||
|
||||
#include "archive_manager.hh"
|
||||
#include "base/ansi_scrubber.hh"
|
||||
#include "base/future_util.hh"
|
||||
#include "base/isc.hh"
|
||||
#include "bottom_status_source.hh"
|
||||
|
@ -256,6 +257,10 @@ struct lnav_data_t {
|
|||
textview_curses ld_match_view;
|
||||
plain_text_source ld_preview_source;
|
||||
textview_curses ld_preview_view;
|
||||
plain_text_source ld_user_message_source;
|
||||
textview_curses ld_user_message_view;
|
||||
std::chrono::time_point<std::chrono::steady_clock>
|
||||
ld_user_message_expiration;
|
||||
|
||||
view_stack<textview_curses> ld_view_stack;
|
||||
textview_curses* ld_last_view;
|
||||
|
|
|
@ -40,9 +40,8 @@
|
|||
#include <glob.h>
|
||||
#include <sys/stat.h>
|
||||
#include <termios.h>
|
||||
#include <yajl/api/yajl_tree.h>
|
||||
|
||||
#include "auto_mem.hh"
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/fs_util.hh"
|
||||
#include "base/humanize.network.hh"
|
||||
#include "base/injector.hh"
|
||||
|
@ -181,7 +180,7 @@ refresh_pt_search()
|
|||
return retval;
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_adjust_log_time(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -251,7 +250,7 @@ com_adjust_log_time(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_unix_time(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -313,7 +312,7 @@ com_unix_time(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_current_time(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -337,7 +336,7 @@ com_current_time(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_goto(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
||||
{
|
||||
std::string retval;
|
||||
|
@ -445,7 +444,7 @@ com_goto(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_relative_goto(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -484,7 +483,7 @@ com_relative_goto(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_mark(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
||||
{
|
||||
std::string retval;
|
||||
|
@ -501,7 +500,7 @@ com_mark(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_mark_expr(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -576,7 +575,7 @@ com_mark_expr_prompt(exec_context& ec, const std::string& cmdline)
|
|||
trim(lnav_data.ld_log_source.get_sql_marker_text()));
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_clear_mark_expr(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -593,7 +592,7 @@ com_clear_mark_expr(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_goto_mark(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -673,7 +672,7 @@ com_goto_mark(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_goto_location(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -855,7 +854,7 @@ write_line_to(FILE* outfile, const attr_line_t& al)
|
|||
}
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_save_to(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -1276,7 +1275,7 @@ com_save_to(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_pipe_to(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -1439,7 +1438,7 @@ com_pipe_to(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_redirect_to(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -1503,7 +1502,7 @@ com_redirect_to(exec_context& ec,
|
|||
return Ok("info: redirecting output to file -- " + split_args[0]);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_highlight(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -1566,7 +1565,7 @@ com_highlight(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_clear_highlight(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -1602,7 +1601,7 @@ com_clear_highlight(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_help(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
||||
{
|
||||
std::string retval;
|
||||
|
@ -1615,10 +1614,10 @@ com_help(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string> com_enable_filter(
|
||||
static Result<std::string, lnav::console::user_message> com_enable_filter(
|
||||
exec_context& ec, std::string cmdline, std::vector<std::string>& args);
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_filter(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -1715,7 +1714,7 @@ com_filter(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_delete_filter(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -1745,7 +1744,7 @@ com_delete_filter(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_enable_filter(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -1780,7 +1779,7 @@ com_enable_filter(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_disable_filter(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -1815,7 +1814,7 @@ com_disable_filter(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_filter_expr(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -1899,7 +1898,7 @@ com_filter_expr_prompt(exec_context& ec, const std::string& cmdline)
|
|||
trim(lnav_data.ld_log_source.get_sql_filter_text()));
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_clear_filter_expr(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -1917,7 +1916,7 @@ com_clear_filter_expr(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_enable_word_wrap(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -1934,7 +1933,7 @@ com_enable_word_wrap(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_disable_word_wrap(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -1953,7 +1952,7 @@ com_disable_word_wrap(exec_context& ec,
|
|||
|
||||
static std::set<std::string> custom_logline_tables;
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_create_logline_table(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -2008,7 +2007,7 @@ com_create_logline_table(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_delete_logline_table(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -2048,7 +2047,7 @@ com_delete_logline_table(exec_context& ec,
|
|||
|
||||
static std::set<std::string> custom_search_tables;
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_create_search_table(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -2117,7 +2116,7 @@ com_create_search_table(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_delete_search_table(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -2154,7 +2153,7 @@ com_delete_search_table(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_session(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -2218,7 +2217,7 @@ com_session(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_open(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
||||
{
|
||||
std::string retval;
|
||||
|
@ -2424,7 +2423,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),
|
||||
view_curses::VC_STYLE.value(A_BOLD))
|
||||
VC_STYLE.value(A_BOLD))
|
||||
.append(" files not shown ...");
|
||||
}
|
||||
lnav_data.ld_preview_status_source.get_description()
|
||||
|
@ -2482,7 +2481,7 @@ com_open(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_close(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
||||
{
|
||||
std::string retval;
|
||||
|
@ -2546,7 +2545,7 @@ com_close(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_file_visibility(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -2662,7 +2661,7 @@ com_file_visibility(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_hide_file(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -2678,7 +2677,7 @@ com_hide_file(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_show_file(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -2694,7 +2693,7 @@ com_show_file(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_show_only_this_file(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -2709,7 +2708,7 @@ com_show_only_this_file(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_comment(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -2772,7 +2771,7 @@ com_comment_prompt(exec_context& ec, const std::string& cmdline)
|
|||
return "";
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_clear_comment(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -2817,7 +2816,7 @@ com_clear_comment(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_tag(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
||||
{
|
||||
std::string retval;
|
||||
|
@ -2862,7 +2861,7 @@ com_tag(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_untag(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
||||
{
|
||||
std::string retval;
|
||||
|
@ -2914,7 +2913,7 @@ com_untag(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_delete_tags(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -2935,7 +2934,7 @@ com_delete_tags(exec_context& ec,
|
|||
"The :delete-tag command only works in the log view");
|
||||
}
|
||||
|
||||
std::set<std::string>& known_tags = bookmark_metadata::KNOWN_TAGS;
|
||||
auto& known_tags = bookmark_metadata::KNOWN_TAGS;
|
||||
std::vector<std::string> tags;
|
||||
|
||||
for (size_t lpc = 1; lpc < args.size(); lpc++) {
|
||||
|
@ -2989,7 +2988,7 @@ com_delete_tags(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_partition_name(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3023,7 +3022,7 @@ com_partition_name(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_clear_partition(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3064,7 +3063,7 @@ com_clear_partition(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_pt_time(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3136,7 +3135,7 @@ com_pt_time(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_summarize(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3154,10 +3153,12 @@ com_summarize(exec_context& ec,
|
|||
auto_mem<char, sqlite3_free> query_frag;
|
||||
std::vector<std::string> other_columns;
|
||||
std::vector<std::string> num_columns;
|
||||
const auto& top_source = ec.ec_source.top();
|
||||
sql_progress_guard progress_guard(sql_progress,
|
||||
sql_progress_finished,
|
||||
ec.ec_source.top().first,
|
||||
ec.ec_source.top().second);
|
||||
top_source.s_source,
|
||||
top_source.s_line,
|
||||
top_source.s_content);
|
||||
auto_mem<sqlite3_stmt> stmt(sqlite3_finalize);
|
||||
int retcode;
|
||||
std::string query;
|
||||
|
@ -3334,7 +3335,7 @@ com_summarize(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_add_test(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3378,7 +3379,7 @@ com_add_test(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_switch_to_view(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3411,7 +3412,7 @@ com_switch_to_view(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_toggle_filtering(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3429,7 +3430,7 @@ com_toggle_filtering(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_zoom_to(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3497,7 +3498,7 @@ com_zoom_to(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_reset_session(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3511,7 +3512,7 @@ com_reset_session(exec_context& ec,
|
|||
return Ok(std::string());
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_load_session(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3525,7 +3526,7 @@ com_load_session(exec_context& ec,
|
|||
return Ok(std::string());
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_save_session(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3538,7 +3539,7 @@ com_save_session(exec_context& ec,
|
|||
return Ok(std::string());
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_set_min_log_level(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3565,7 +3566,7 @@ com_set_min_log_level(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_toggle_field(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3643,7 +3644,7 @@ com_toggle_field(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_hide_line(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3744,7 +3745,7 @@ com_hide_line(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_show_lines(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3765,7 +3766,7 @@ com_show_lines(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_hide_unmarked(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3791,7 +3792,7 @@ com_hide_unmarked(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_show_unmarked(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3807,7 +3808,7 @@ com_show_unmarked(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_rebuild(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3820,7 +3821,7 @@ com_rebuild(exec_context& ec,
|
|||
return Ok(std::string());
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_shexec(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3833,7 +3834,7 @@ com_shexec(exec_context& ec,
|
|||
return Ok(std::string());
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_poll_now(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3847,7 +3848,7 @@ com_poll_now(exec_context& ec,
|
|||
return Ok(std::string());
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_redraw(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3861,7 +3862,7 @@ com_redraw(exec_context& ec,
|
|||
return Ok(std::string());
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_echo(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
||||
{
|
||||
std::string retval = "error: expecting a message";
|
||||
|
@ -3911,7 +3912,7 @@ com_echo(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_alt_msg(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -3939,7 +3940,7 @@ com_alt_msg(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_eval(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
||||
{
|
||||
std::string retval;
|
||||
|
@ -4003,7 +4004,7 @@ com_eval(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_config(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -4014,16 +4015,15 @@ com_config(exec_context& ec,
|
|||
args.emplace_back("config-option");
|
||||
} else if (args.size() > 1) {
|
||||
yajlpp_parse_context ypc("input", &lnav_config_handlers);
|
||||
std::vector<std::string> errors;
|
||||
std::vector<lnav::console::user_message> errors;
|
||||
std::string option = args[1];
|
||||
|
||||
lnav_config = rollback_lnav_config;
|
||||
ypc.set_path(option)
|
||||
.with_obj(lnav_config)
|
||||
.with_error_reporter(
|
||||
[&errors](const auto& ypc, auto level, auto* msg) {
|
||||
errors.push_back(msg);
|
||||
});
|
||||
.with_error_reporter([&errors](const auto& ypc, auto msg) {
|
||||
errors.push_back(msg);
|
||||
});
|
||||
ypc.ypc_active_paths.insert(option);
|
||||
ypc.update_callbacks();
|
||||
|
||||
|
@ -4103,7 +4103,6 @@ com_config(exec_context& ec,
|
|||
|
||||
auto consumed
|
||||
= strtonum(val, value.c_str(), value.length());
|
||||
log_debug("got val %d", (int) val);
|
||||
if (consumed != value.length()) {
|
||||
return ec.make_error("expecting an integer, found: {}",
|
||||
value);
|
||||
|
@ -4124,22 +4123,24 @@ com_config(exec_context& ec,
|
|||
}
|
||||
|
||||
if (!errors.empty()) {
|
||||
return ec.make_error(errors[0]);
|
||||
return Err(errors[0]);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
intern_string_t path = intern_string::lookup(option);
|
||||
|
||||
lnav_config_locations[path]
|
||||
= {intern_string::lookup(ec.ec_source.top().first),
|
||||
ec.ec_source.top().second};
|
||||
lnav_config_locations[path] = {
|
||||
intern_string::lookup(ec.ec_source.top().s_source),
|
||||
ec.ec_source.top().s_line,
|
||||
};
|
||||
reload_config(errors);
|
||||
|
||||
if (!errors.empty()) {
|
||||
lnav_config = rollback_lnav_config;
|
||||
reload_config(errors);
|
||||
return Err("error: " + errors[0]);
|
||||
} else if (!ec.ec_dry_run) {
|
||||
return Err(errors[0]);
|
||||
}
|
||||
if (!ec.ec_dry_run) {
|
||||
retval = "info: changed config option -- " + option;
|
||||
rollback_lnav_config = lnav_config;
|
||||
save_config();
|
||||
|
@ -4157,7 +4158,7 @@ com_config(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_reset_config(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -4497,7 +4498,7 @@ public:
|
|||
std::string dsvs_error_msg;
|
||||
};
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_spectrogram(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -4560,7 +4561,7 @@ com_spectrogram(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_quit(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
|
||||
{
|
||||
if (args.empty()) {
|
||||
|
@ -4802,7 +4803,7 @@ user_prompt(std::vector<std::string>& args)
|
|||
lnav_data.ld_status[LNS_BOTTOM].do_update();
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
com_prompt(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
|
|
@ -46,8 +46,8 @@
|
|||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "auto_mem.hh"
|
||||
#include "base/auto_fd.hh"
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/auto_pid.hh"
|
||||
#include "base/fs_util.hh"
|
||||
#include "base/injector.bind.hh"
|
||||
|
@ -59,6 +59,7 @@
|
|||
#include "config.h"
|
||||
#include "default-config.h"
|
||||
#include "styling.hh"
|
||||
#include "view_curses.hh"
|
||||
#include "yajlpp/yajlpp.hh"
|
||||
#include "yajlpp/yajlpp_def.hh"
|
||||
|
||||
|
@ -124,7 +125,7 @@ ensure_dotlnav()
|
|||
|
||||
auto path = lnav::paths::dotlnav();
|
||||
|
||||
for (auto sub_path : subdirs) {
|
||||
for (const auto* sub_path : subdirs) {
|
||||
auto full_path = path / sub_path;
|
||||
|
||||
log_perror(mkdir(full_path.c_str(), 0755));
|
||||
|
@ -164,7 +165,7 @@ ensure_dotlnav()
|
|||
continue;
|
||||
}
|
||||
|
||||
log_debug("Removing old stdin capture: %s", gl->gl_pathv[lpc]);
|
||||
log_info("Removing old stdin capture: %s", gl->gl_pathv[lpc]);
|
||||
log_perror(remove(gl->gl_pathv[lpc]));
|
||||
}
|
||||
}
|
||||
|
@ -315,8 +316,9 @@ read_repo_path(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static const struct json_path_container format_handlers
|
||||
= {json_path_handler("format-repos#", read_repo_path)};
|
||||
static const struct json_path_container format_handlers = {
|
||||
json_path_handler("format-repos#", read_repo_path),
|
||||
};
|
||||
|
||||
void
|
||||
install_extra_formats()
|
||||
|
@ -351,7 +353,7 @@ install_extra_formats()
|
|||
yajl_config(jhandle, yajl_allow_comments, 1);
|
||||
while ((rc = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
if (yajl_parse(jhandle, buffer, rc) != yajl_status_ok) {
|
||||
auto msg = yajl_get_error(jhandle, 1, buffer, rc);
|
||||
auto* msg = yajl_get_error(jhandle, 1, buffer, rc);
|
||||
fprintf(
|
||||
stderr, "Unable to parse remote-config.json -- %s", msg);
|
||||
yajl_free_error(jhandle, msg);
|
||||
|
@ -359,7 +361,7 @@ install_extra_formats()
|
|||
}
|
||||
}
|
||||
if (yajl_complete_parse(jhandle) != yajl_status_ok) {
|
||||
auto msg = yajl_get_error(jhandle, 1, buffer, rc);
|
||||
auto* msg = yajl_get_error(jhandle, 1, buffer, rc);
|
||||
|
||||
fprintf(stderr, "Unable to parse remote-config.json -- %s", msg);
|
||||
yajl_free_error(jhandle, msg);
|
||||
|
@ -368,23 +370,19 @@ install_extra_formats()
|
|||
}
|
||||
|
||||
struct userdata {
|
||||
userdata(std::vector<std::string>& errors) : ud_errors(errors){};
|
||||
explicit userdata(std::vector<lnav::console::user_message>& errors)
|
||||
: ud_errors(errors){};
|
||||
|
||||
std::vector<std::string>& ud_errors;
|
||||
std::vector<lnav::console::user_message>& ud_errors;
|
||||
};
|
||||
|
||||
static void
|
||||
config_error_reporter(const yajlpp_parse_context& ypc,
|
||||
lnav_log_level_t level,
|
||||
const char* msg)
|
||||
const lnav::console::user_message& msg)
|
||||
{
|
||||
if (level >= lnav_log_level_t::ERROR) {
|
||||
struct userdata* ud = (userdata*) ypc.ypc_userdata;
|
||||
auto* ud = (userdata*) ypc.ypc_userdata;
|
||||
|
||||
ud->ud_errors.emplace_back(msg);
|
||||
} else {
|
||||
fprintf(stderr, "warning:%s\n", msg);
|
||||
}
|
||||
ud->ud_errors.emplace_back(msg);
|
||||
}
|
||||
|
||||
static const struct json_path_container key_command_handlers = {
|
||||
|
@ -393,38 +391,40 @@ static const struct json_path_container key_command_handlers = {
|
|||
.with_description(
|
||||
"The command to execute for the given key sequence. Use a script "
|
||||
"to execute more complicated operations.")
|
||||
.with_pattern("[:|;].*")
|
||||
.with_pattern("^[:|;].*")
|
||||
.with_example(":goto next hour")
|
||||
.FOR_FIELD(key_command, kc_cmd),
|
||||
.for_field(&key_command::kc_cmd),
|
||||
yajlpp::property_handler("alt-msg")
|
||||
.with_synopsis("<msg>")
|
||||
.with_description(
|
||||
"The help message to display after the key is pressed.")
|
||||
.FOR_FIELD(key_command, kc_alt_msg)};
|
||||
.for_field<>(&key_command::kc_alt_msg),
|
||||
};
|
||||
|
||||
static const struct json_path_container keymap_def_handlers
|
||||
= {yajlpp::pattern_property_handler("(?<key_seq>(?:x[0-9a-f]{2})+)")
|
||||
.with_synopsis("<utf8-key-code-in-hex>")
|
||||
.with_description(
|
||||
"Map of key codes to commands to execute. The field names are "
|
||||
"the keys to be mapped using as a hexadecimal representation of "
|
||||
"the UTF-8 encoding. Each byte of the UTF-8 should start with "
|
||||
"an 'x' followed by the hexadecimal representation of the byte.")
|
||||
.with_obj_provider<key_command, key_map>(
|
||||
[](const yajlpp_provider_context& ypc, key_map* km) {
|
||||
key_command& retval
|
||||
= km->km_seq_to_cmd[ypc.ypc_extractor.get_substr(
|
||||
"key_seq")];
|
||||
static const struct json_path_container keymap_def_handlers = {
|
||||
yajlpp::pattern_property_handler("(?<key_seq>(?:x[0-9a-f]{2})+)")
|
||||
.with_synopsis("<utf8-key-code-in-hex>")
|
||||
.with_description(
|
||||
"Map of key codes to commands to execute. The field names are "
|
||||
"the keys to be mapped using as a hexadecimal representation of "
|
||||
"the UTF-8 encoding. Each byte of the UTF-8 should start with "
|
||||
"an 'x' followed by the hexadecimal representation of the byte.")
|
||||
.with_obj_provider<key_command, key_map>(
|
||||
[](const yajlpp_provider_context& ypc, key_map* km) {
|
||||
key_command& retval
|
||||
= km->km_seq_to_cmd[ypc.ypc_extractor.get_substr(
|
||||
"key_seq")];
|
||||
|
||||
return &retval;
|
||||
})
|
||||
.with_path_provider<key_map>(
|
||||
[](key_map* km, std::vector<std::string>& paths_out) {
|
||||
for (const auto& iter : km->km_seq_to_cmd) {
|
||||
paths_out.emplace_back(iter.first);
|
||||
}
|
||||
})
|
||||
.with_children(key_command_handlers)};
|
||||
return &retval;
|
||||
})
|
||||
.with_path_provider<key_map>(
|
||||
[](key_map* km, std::vector<std::string>& paths_out) {
|
||||
for (const auto& iter : km->km_seq_to_cmd) {
|
||||
paths_out.emplace_back(iter.first);
|
||||
}
|
||||
})
|
||||
.with_children(key_command_handlers),
|
||||
};
|
||||
|
||||
static const struct json_path_container keymap_defs_handlers = {
|
||||
yajlpp::pattern_property_handler("(?<keymap_name>[\\w\\-]+)")
|
||||
|
@ -442,7 +442,8 @@ static const struct json_path_container keymap_defs_handlers = {
|
|||
paths_out.emplace_back(iter.first);
|
||||
}
|
||||
})
|
||||
.with_children(keymap_def_handlers)};
|
||||
.with_children(keymap_def_handlers),
|
||||
};
|
||||
|
||||
static const struct json_path_container global_var_handlers = {
|
||||
yajlpp::pattern_property_handler("(?<var_name>\\w+)")
|
||||
|
@ -456,7 +457,8 @@ static const struct json_path_container global_var_handlers = {
|
|||
paths_out.emplace_back(iter.first);
|
||||
}
|
||||
})
|
||||
.FOR_FIELD(_lnav_config, lc_global_vars)};
|
||||
.FOR_FIELD(_lnav_config, lc_global_vars),
|
||||
};
|
||||
|
||||
static const struct json_path_container style_config_handlers =
|
||||
json_path_container{
|
||||
|
@ -469,7 +471,7 @@ static const struct json_path_container style_config_handlers =
|
|||
.with_example("#fff")
|
||||
.with_example("Green")
|
||||
.with_example("$black")
|
||||
.FOR_FIELD(style_config, sc_color),
|
||||
.for_field(&style_config::sc_color),
|
||||
yajlpp::property_handler("background-color")
|
||||
.with_synopsis("#hex|color_name")
|
||||
.with_description(
|
||||
|
@ -478,13 +480,13 @@ static const struct json_path_container style_config_handlers =
|
|||
"variable reference.")
|
||||
.with_example("#2d2a2e")
|
||||
.with_example("Green")
|
||||
.FOR_FIELD(style_config, sc_background_color),
|
||||
.for_field(&style_config::sc_background_color),
|
||||
yajlpp::property_handler("underline")
|
||||
.with_description("Indicates that the text should be underlined.")
|
||||
.FOR_FIELD(style_config, sc_underline),
|
||||
.for_field(&style_config::sc_underline),
|
||||
yajlpp::property_handler("bold")
|
||||
.with_description("Indicates that the text should be bolded.")
|
||||
.FOR_FIELD(style_config, sc_bold),
|
||||
.for_field(&style_config::sc_bold),
|
||||
}
|
||||
.with_definition_id("style");
|
||||
|
||||
|
@ -594,103 +596,147 @@ static const struct json_path_container theme_styles_handlers = {
|
|||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_scrollbar;
|
||||
})
|
||||
.with_children(style_config_handlers)};
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("h1")
|
||||
.with_description("Styling for top-level headers")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_header[0];
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("h2")
|
||||
.with_description("Styling for 2nd-level headers")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_header[1];
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("h3")
|
||||
.with_description("Styling for 3rd-level headers")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_header[2];
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("h4")
|
||||
.with_description("Styling for 4th-level headers")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_header[3];
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("h5")
|
||||
.with_description("Styling for 5th-level headers")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_header[4];
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("h6")
|
||||
.with_description("Styling for 6th-level headers")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_header[5];
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
};
|
||||
|
||||
static const struct json_path_container theme_syntax_styles_handlers
|
||||
= {yajlpp::property_handler("keyword")
|
||||
.with_description("Styling for keywords in source files")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_keyword;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("string")
|
||||
.with_description("Styling for single/double-quoted strings in text")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_string;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("comment")
|
||||
.with_description("Styling for comments in source files")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_comment;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("doc-directive")
|
||||
.with_description(
|
||||
"Styling for documentation directives in source files")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_doc_directive;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("variable")
|
||||
.with_description("Styling for variables in text")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_variable;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("symbol")
|
||||
.with_description("Styling for symbols in source files")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_symbol;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("number")
|
||||
.with_description("Styling for numbers in source files")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_number;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("re-special")
|
||||
.with_description(
|
||||
"Styling for special characters in regular expressions")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_re_special;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("re-repeat")
|
||||
.with_description("Styling for repeats in regular expressions")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_re_repeat;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
static const struct json_path_container theme_syntax_styles_handlers = {
|
||||
yajlpp::property_handler("keyword")
|
||||
.with_description("Styling for keywords in source files")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_keyword;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("string")
|
||||
.with_description("Styling for single/double-quoted strings in text")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_string;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("comment")
|
||||
.with_description("Styling for comments in source files")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_comment;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("doc-directive")
|
||||
.with_description(
|
||||
"Styling for documentation directives in source files")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_doc_directive;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("variable")
|
||||
.with_description("Styling for variables in text")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_variable;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("symbol")
|
||||
.with_description("Styling for symbols in source files")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_symbol;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("number")
|
||||
.with_description("Styling for numbers in source files")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_number;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("re-special")
|
||||
.with_description(
|
||||
"Styling for special characters in regular expressions")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_re_special;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("re-repeat")
|
||||
.with_description("Styling for repeats in regular expressions")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_re_repeat;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
|
||||
yajlpp::property_handler("diff-delete")
|
||||
.with_description("Styling for deleted lines in diffs")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_diff_delete;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("diff-add")
|
||||
.with_description("Styling for added lines in diffs")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_diff_add;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("diff-section")
|
||||
.with_description("Styling for diffs")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_diff_section;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("file")
|
||||
.with_description("Styling for file names in source files")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_file;
|
||||
})
|
||||
.with_children(style_config_handlers)};
|
||||
yajlpp::property_handler("diff-delete")
|
||||
.with_description("Styling for deleted lines in diffs")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_diff_delete;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("diff-add")
|
||||
.with_description("Styling for added lines in diffs")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_diff_add;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("diff-section")
|
||||
.with_description("Styling for diffs")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_diff_section;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
yajlpp::property_handler("file")
|
||||
.with_description("Styling for file names in source files")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
return &root->lt_style_file;
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
};
|
||||
|
||||
static const struct json_path_container theme_status_styles_handlers = {
|
||||
yajlpp::property_handler("text")
|
||||
|
@ -772,24 +818,25 @@ static const struct json_path_container theme_status_styles_handlers = {
|
|||
.with_children(style_config_handlers),
|
||||
};
|
||||
|
||||
static const struct json_path_container theme_log_level_styles_handlers
|
||||
= {yajlpp::pattern_property_handler(
|
||||
"(?<level>trace|debug5|debug4|debug3|debug2|debug|info|stats|notice|"
|
||||
"warning|error|critical|fatal|invalid)")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
style_config& sc = root->lt_level_styles[string2level(
|
||||
ypc.ypc_extractor.get_substr_i("level").get())];
|
||||
static const struct json_path_container theme_log_level_styles_handlers = {
|
||||
yajlpp::pattern_property_handler(
|
||||
"(?<level>trace|debug5|debug4|debug3|debug2|debug|info|stats|notice|"
|
||||
"warning|error|critical|fatal|invalid)")
|
||||
.with_obj_provider<style_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
style_config& sc = root->lt_level_styles[string2level(
|
||||
ypc.ypc_extractor.get_substr_i("level").get())];
|
||||
|
||||
return ≻
|
||||
})
|
||||
.with_path_provider<lnav_theme>(
|
||||
[](struct lnav_theme* cfg, std::vector<std::string>& paths_out) {
|
||||
for (int lpc = LEVEL_TRACE; lpc < LEVEL__MAX; lpc++) {
|
||||
paths_out.emplace_back(level_names[lpc]);
|
||||
}
|
||||
})
|
||||
.with_children(style_config_handlers)};
|
||||
return ≻
|
||||
})
|
||||
.with_path_provider<lnav_theme>(
|
||||
[](struct lnav_theme* cfg, std::vector<std::string>& paths_out) {
|
||||
for (int lpc = LEVEL_TRACE; lpc < LEVEL__MAX; lpc++) {
|
||||
paths_out.emplace_back(level_names[lpc]);
|
||||
}
|
||||
})
|
||||
.with_children(style_config_handlers),
|
||||
};
|
||||
|
||||
static const struct json_path_container highlighter_handlers = {
|
||||
yajlpp::property_handler("pattern")
|
||||
|
@ -807,36 +854,38 @@ static const struct json_path_container highlighter_handlers = {
|
|||
.with_children(style_config_handlers),
|
||||
};
|
||||
|
||||
static const struct json_path_container theme_highlights_handlers
|
||||
= {yajlpp::pattern_property_handler("(?<highlight_name>\\w+)")
|
||||
.with_obj_provider<highlighter_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
highlighter_config& hc
|
||||
= root->lt_highlights[ypc.ypc_extractor
|
||||
.get_substr_i("highlight_name")
|
||||
.get()];
|
||||
static const struct json_path_container theme_highlights_handlers = {
|
||||
yajlpp::pattern_property_handler("(?<highlight_name>\\w+)")
|
||||
.with_obj_provider<highlighter_config, lnav_theme>(
|
||||
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
||||
highlighter_config& hc
|
||||
= root->lt_highlights[ypc.ypc_extractor
|
||||
.get_substr_i("highlight_name")
|
||||
.get()];
|
||||
|
||||
return &hc;
|
||||
})
|
||||
.with_path_provider<lnav_theme>(
|
||||
[](struct lnav_theme* cfg, std::vector<std::string>& paths_out) {
|
||||
for (const auto& pair : cfg->lt_highlights) {
|
||||
paths_out.emplace_back(pair.first);
|
||||
}
|
||||
})
|
||||
.with_children(highlighter_handlers)};
|
||||
return &hc;
|
||||
})
|
||||
.with_path_provider<lnav_theme>(
|
||||
[](struct lnav_theme* cfg, std::vector<std::string>& paths_out) {
|
||||
for (const auto& pair : cfg->lt_highlights) {
|
||||
paths_out.emplace_back(pair.first);
|
||||
}
|
||||
})
|
||||
.with_children(highlighter_handlers),
|
||||
};
|
||||
|
||||
static const struct json_path_container theme_vars_handlers
|
||||
= {yajlpp::pattern_property_handler("(?<var_name>\\w+)")
|
||||
.with_synopsis("name")
|
||||
.with_description("A theme variable definition")
|
||||
.with_path_provider<lnav_theme>(
|
||||
[](struct lnav_theme* lt, std::vector<std::string>& paths_out) {
|
||||
for (const auto& iter : lt->lt_vars) {
|
||||
paths_out.emplace_back(iter.first);
|
||||
}
|
||||
})
|
||||
.FOR_FIELD(lnav_theme, lt_vars)};
|
||||
static const struct json_path_container theme_vars_handlers = {
|
||||
yajlpp::pattern_property_handler("(?<var_name>\\w+)")
|
||||
.with_synopsis("name")
|
||||
.with_description("A theme variable definition")
|
||||
.with_path_provider<lnav_theme>(
|
||||
[](struct lnav_theme* lt, std::vector<std::string>& paths_out) {
|
||||
for (const auto& iter : lt->lt_vars) {
|
||||
paths_out.emplace_back(iter.first);
|
||||
}
|
||||
})
|
||||
.FOR_FIELD(lnav_theme, lt_vars),
|
||||
};
|
||||
|
||||
static const struct json_path_container theme_def_handlers = {
|
||||
yajlpp::property_handler("vars")
|
||||
|
@ -881,7 +930,8 @@ static const struct json_path_container theme_defs_handlers = {
|
|||
paths_out.emplace_back(iter.first);
|
||||
}
|
||||
})
|
||||
.with_children(theme_def_handlers)};
|
||||
.with_children(theme_def_handlers),
|
||||
};
|
||||
|
||||
static const struct json_path_container ui_handlers = {
|
||||
yajlpp::property_handler("clock-format")
|
||||
|
@ -889,13 +939,13 @@ static const struct json_path_container ui_handlers = {
|
|||
.with_description("The format for the clock displayed in "
|
||||
"the top-left corner using strftime(3) conversions")
|
||||
.with_example("%a %b %d %H:%M:%S %Z")
|
||||
.FOR_FIELD(_lnav_config, lc_ui_clock_format),
|
||||
.for_field(&_lnav_config::lc_ui_clock_format),
|
||||
yajlpp::property_handler("dim-text")
|
||||
.with_synopsis("bool")
|
||||
.with_description("Reduce the brightness of text (useful for xterms). "
|
||||
"This setting can be useful when running in an xterm "
|
||||
"where the white color is very bright.")
|
||||
.FOR_FIELD(_lnav_config, lc_ui_dim_text),
|
||||
.for_field(&_lnav_config::lc_ui_dim_text),
|
||||
yajlpp::property_handler("default-colors")
|
||||
.with_synopsis("bool")
|
||||
.with_description(
|
||||
|
@ -903,15 +953,15 @@ static const struct json_path_container ui_handlers = {
|
|||
"instead of black and white for all text coloring. This setting "
|
||||
"can be useful when transparent background or alternate color "
|
||||
"theme terminal is used.")
|
||||
.FOR_FIELD(_lnav_config, lc_ui_default_colors),
|
||||
.for_field(&_lnav_config::lc_ui_default_colors),
|
||||
yajlpp::property_handler("keymap")
|
||||
.with_synopsis("keymap_name")
|
||||
.with_description("The name of the keymap to use.")
|
||||
.FOR_FIELD(_lnav_config, lc_ui_keymap),
|
||||
.for_field(&_lnav_config::lc_ui_keymap),
|
||||
yajlpp::property_handler("theme")
|
||||
.with_synopsis("theme_name")
|
||||
.with_description("The name of the theme to use.")
|
||||
.FOR_FIELD(_lnav_config, lc_ui_theme),
|
||||
.for_field(&_lnav_config::lc_ui_theme),
|
||||
yajlpp::property_handler("theme-defs")
|
||||
.with_description("Theme definitions.")
|
||||
.with_children(theme_defs_handlers),
|
||||
|
@ -1105,8 +1155,11 @@ static const struct json_path_container tuning_handlers = {
|
|||
.with_children(sysclip_handlers),
|
||||
};
|
||||
|
||||
const char* DEFAULT_CONFIG_SCHEMA
|
||||
= "https://lnav.org/schemas/config-v1.schema.json";
|
||||
|
||||
static const std::set<std::string> SUPPORTED_CONFIG_SCHEMAS = {
|
||||
"https://lnav.org/schemas/config-v1.schema.json",
|
||||
DEFAULT_CONFIG_SCHEMA,
|
||||
};
|
||||
|
||||
const char* DEFAULT_FORMAT_SCHEMA
|
||||
|
@ -1122,13 +1175,22 @@ read_id(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
|
|||
auto file_id = std::string((const char*) str, len);
|
||||
|
||||
if (SUPPORTED_CONFIG_SCHEMAS.count(file_id) == 0) {
|
||||
const auto* handler = ypc->ypc_current_handler;
|
||||
attr_line_t notes{"expecting one of the following $schema values:"};
|
||||
|
||||
for (const auto& schema : SUPPORTED_CONFIG_SCHEMAS) {
|
||||
notes.append("\n").append(
|
||||
lnav::roles::symbol(fmt::format(FMT_STRING(" {}"), schema)));
|
||||
}
|
||||
ypc->report_error(
|
||||
lnav_log_level_t::ERROR,
|
||||
"%s:%d: error: unsupported configuration $schema -- %s\n",
|
||||
ypc->ypc_source.c_str(),
|
||||
ypc->get_line_number(),
|
||||
file_id.c_str());
|
||||
return 0;
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("'")
|
||||
.append(lnav::roles::symbol(file_id))
|
||||
.append(
|
||||
"' is not a supported configuration $schema version"))
|
||||
.with_snippet(ypc->get_snippet())
|
||||
.with_note(notes)
|
||||
.with_help(handler->get_help_text(ypc)));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -1136,8 +1198,9 @@ read_id(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
|
|||
|
||||
const json_path_container lnav_config_handlers = json_path_container {
|
||||
json_path_handler("$schema", read_id)
|
||||
.with_synopsis("The URI of the schema for this file")
|
||||
.with_description("Specifies the type of this file"),
|
||||
.with_synopsis("<schema-uri>")
|
||||
.with_description("The URI that specifies the schema that describes this type of file")
|
||||
.with_example(DEFAULT_CONFIG_SCHEMA),
|
||||
|
||||
yajlpp::property_handler("tuning")
|
||||
.with_description("Internal settings")
|
||||
|
@ -1174,15 +1237,7 @@ detect_config_file_type(const ghc::filesystem::path& path)
|
|||
{
|
||||
static const char* id_path[] = {"$schema", nullptr};
|
||||
|
||||
auto read_res = lnav::filesystem::read_file(path);
|
||||
|
||||
if (read_res.isErr()) {
|
||||
return Err(fmt::format(FMT_STRING("unable to open file4: {} -- {}"),
|
||||
path.string(),
|
||||
read_res.unwrapErr()));
|
||||
}
|
||||
|
||||
auto content = read_res.unwrap();
|
||||
auto content = TRY(lnav::filesystem::read_file(path));
|
||||
if (startswith(content, "#")) {
|
||||
content.insert(0, "//");
|
||||
}
|
||||
|
@ -1192,9 +1247,8 @@ detect_config_file_type(const ghc::filesystem::path& path)
|
|||
yajl_tree_parse(content.c_str(), error_buffer, sizeof(error_buffer)),
|
||||
yajl_tree_free);
|
||||
if (content_tree == nullptr) {
|
||||
return Err(fmt::format(FMT_STRING("unable to parse file: {} -- {}"),
|
||||
path.string(),
|
||||
error_buffer));
|
||||
return Err(
|
||||
fmt::format(FMT_STRING("JSON parsing failed -- {}"), error_buffer));
|
||||
}
|
||||
|
||||
auto* id_val = yajl_tree_get(content_tree.get(), id_path, yajl_t_string);
|
||||
|
@ -1206,18 +1260,16 @@ detect_config_file_type(const ghc::filesystem::path& path)
|
|||
return Ok(config_file_type::FORMAT);
|
||||
}
|
||||
return Err(fmt::format(
|
||||
FMT_STRING("unsupported configuration version in file: {} -- {}"),
|
||||
path.string(),
|
||||
FMT_STRING("unsupported configuration version in file -- {}"),
|
||||
id_val->u.string));
|
||||
} else {
|
||||
return Ok(config_file_type::FORMAT);
|
||||
}
|
||||
return Ok(config_file_type::FORMAT);
|
||||
}
|
||||
|
||||
static void
|
||||
load_config_from(_lnav_config& lconfig,
|
||||
const ghc::filesystem::path& path,
|
||||
std::vector<std::string>& errors)
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
yajlpp_parse_context ypc(path.string(), &lnav_config_handlers);
|
||||
struct userdata ud(errors);
|
||||
|
@ -1229,14 +1281,15 @@ load_config_from(_lnav_config& lconfig,
|
|||
ypc.with_error_reporter(config_error_reporter);
|
||||
if ((fd = lnav::filesystem::openp(path, O_RDONLY)) == -1) {
|
||||
if (errno != ENOENT) {
|
||||
errors.emplace_back(fmt::format(
|
||||
FMT_STRING("error: unable to open format file -- {}"),
|
||||
path.string()));
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("unable to open configuration file: ")
|
||||
.append(lnav::roles::file(path)))
|
||||
.with_errno_reason());
|
||||
}
|
||||
} else {
|
||||
auto_mem<yajl_handle_t> handle(yajl_free);
|
||||
char buffer[2048];
|
||||
off_t offset = 0;
|
||||
ssize_t rc = -1;
|
||||
|
||||
handle = yajl_alloc(&ypc.ypc_callbacks, nullptr, &ypc);
|
||||
|
@ -1247,18 +1300,19 @@ load_config_from(_lnav_config& lconfig,
|
|||
rc = read(fd, buffer, sizeof(buffer));
|
||||
if (rc == 0) {
|
||||
break;
|
||||
} else if (rc == -1) {
|
||||
}
|
||||
if (rc == -1) {
|
||||
errors.emplace_back(
|
||||
fmt::format(FMT_STRING("{}:unable to read file -- {}"),
|
||||
path.string(),
|
||||
strerror(errno)));
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("unable to read format file: ")
|
||||
.append(lnav::roles::file(path)))
|
||||
.with_errno_reason());
|
||||
break;
|
||||
}
|
||||
if (ypc.parse((const unsigned char*) buffer, rc) != yajl_status_ok)
|
||||
{
|
||||
break;
|
||||
}
|
||||
offset += rc;
|
||||
}
|
||||
if (rc == 0) {
|
||||
ypc.complete_parse();
|
||||
|
@ -1270,7 +1324,7 @@ static void
|
|||
load_default_config(struct _lnav_config& config_obj,
|
||||
const std::string& path,
|
||||
const bin_src_file& bsf,
|
||||
std::vector<std::string>& errors)
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
yajlpp_parse_context ypc_builtin(bsf.get_name(), &lnav_config_handlers);
|
||||
auto_mem<yajl_handle_t> handle(yajl_free);
|
||||
|
@ -1298,7 +1352,7 @@ load_default_config(struct _lnav_config& config_obj,
|
|||
static void
|
||||
load_default_configs(struct _lnav_config& config_obj,
|
||||
const std::string& path,
|
||||
std::vector<std::string>& errors)
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
for (auto& bsf : lnav_config_json) {
|
||||
load_default_config(config_obj, path, bsf, errors);
|
||||
|
@ -1307,7 +1361,7 @@ load_default_configs(struct _lnav_config& config_obj,
|
|||
|
||||
void
|
||||
load_config(const std::vector<ghc::filesystem::path>& extra_paths,
|
||||
std::vector<std::string>& errors)
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
auto user_config = lnav::paths::dotlnav() / "config.json";
|
||||
|
||||
|
@ -1370,14 +1424,14 @@ load_config(const std::vector<ghc::filesystem::path>& extra_paths,
|
|||
void
|
||||
reset_config(const std::string& path)
|
||||
{
|
||||
std::vector<std::string> errors;
|
||||
std::vector<lnav::console::user_message> errors;
|
||||
|
||||
load_default_configs(lnav_config, path, errors);
|
||||
|
||||
reload_config(errors);
|
||||
|
||||
for (auto& err : errors) {
|
||||
log_debug("reset %s", err.c_str());
|
||||
for (const auto& err : errors) {
|
||||
log_debug("reset %s", err.um_message.get_string().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1418,7 +1472,7 @@ save_config()
|
|||
}
|
||||
|
||||
void
|
||||
reload_config(std::vector<std::string>& errors)
|
||||
reload_config(std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
lnav_config_listener* curr = lnav_config_listener::LISTENER_LIST;
|
||||
|
||||
|
@ -1439,10 +1493,16 @@ reload_config(std::vector<std::string>& errors)
|
|||
return;
|
||||
}
|
||||
|
||||
errors.emplace_back(fmt::format(FMT_STRING("{}:{}:{}"),
|
||||
loc_iter->second.sl_source,
|
||||
loc_iter->second.sl_line_number,
|
||||
errmsg));
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t()
|
||||
.append("invalid value for property ")
|
||||
.append_quoted(lnav::roles::symbol(path)))
|
||||
.with_reason(errmsg)
|
||||
.with_snippet(
|
||||
lnav::console::snippet::from(
|
||||
loc_iter->second.sl_source.to_string(), "")
|
||||
.with_line(loc_iter->second.sl_line_number)));
|
||||
};
|
||||
|
||||
for (const auto& jph : lnav_config_handlers.jpc_children) {
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "archive_manager.cfg.hh"
|
||||
#include "base/file_range.hh"
|
||||
#include "base/lnav.console.hh"
|
||||
#include "base/result.h"
|
||||
#include "file_vtab.cfg.hh"
|
||||
#include "ghc/filesystem.hpp"
|
||||
|
@ -117,11 +118,11 @@ Result<config_file_type, std::string> detect_config_file_type(
|
|||
const ghc::filesystem::path& path);
|
||||
|
||||
void load_config(const std::vector<ghc::filesystem::path>& extra_paths,
|
||||
std::vector<std::string>& errors);
|
||||
std::vector<lnav::console::user_message>& errors);
|
||||
|
||||
void reset_config(const std::string& path);
|
||||
|
||||
void reload_config(std::vector<std::string>& errors);
|
||||
void reload_config(std::vector<lnav::console::user_message>& errors);
|
||||
|
||||
std::string save_config();
|
||||
|
||||
|
|
251
src/lnav_util.cc
251
src/lnav_util.cc
|
@ -36,11 +36,13 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "ansi_scrubber.hh"
|
||||
#include "base/ansi_scrubber.hh"
|
||||
#include "base/result.h"
|
||||
#include "config.h"
|
||||
#include "fmt/format.h"
|
||||
#include "view_curses.hh"
|
||||
#include "yajlpp/yajlpp.hh"
|
||||
#include "yajlpp/yajlpp_def.hh"
|
||||
|
||||
bool
|
||||
change_to_parent_dir()
|
||||
|
@ -101,8 +103,249 @@ err_prefix(const std::string msg)
|
|||
return std::string(ANSI_COLOR(COLOR_RED) "\u2718" ANSI_NORM " ") + msg;
|
||||
}
|
||||
|
||||
Result<std::string, std::string>
|
||||
err_to_ok(const std::string msg)
|
||||
Result<std::string, lnav::console::user_message>
|
||||
err_to_ok(const lnav::console::user_message msg)
|
||||
{
|
||||
return Ok(err_prefix(msg));
|
||||
return Ok(msg.to_attr_line().get_string());
|
||||
}
|
||||
|
||||
namespace lnav {
|
||||
|
||||
static void
|
||||
to_json(yajlpp_gen& gen, const attr_line_t& al)
|
||||
{
|
||||
{
|
||||
yajlpp_map root_map(gen);
|
||||
|
||||
root_map.gen("str");
|
||||
root_map.gen(al.get_string());
|
||||
|
||||
root_map.gen("attrs");
|
||||
{
|
||||
yajlpp_array attr_array(gen);
|
||||
|
||||
for (const auto& sa : al.get_attrs()) {
|
||||
yajlpp_map elem_map(gen);
|
||||
|
||||
elem_map.gen("start");
|
||||
elem_map.gen(sa.sa_range.lr_start);
|
||||
elem_map.gen("end");
|
||||
elem_map.gen(sa.sa_range.lr_end);
|
||||
elem_map.gen("type");
|
||||
elem_map.gen(sa.sa_type->sat_name);
|
||||
elem_map.gen("value");
|
||||
sa.sa_value.match(
|
||||
[&](int64_t i) { elem_map.gen(i); },
|
||||
[&](role_t r) {
|
||||
elem_map.gen(lnav::enums::to_underlying(r));
|
||||
},
|
||||
[&](const intern_string_t& str) { elem_map.gen(str); },
|
||||
[&](const std::string& str) { elem_map.gen(str); },
|
||||
[&](const std::shared_ptr<logfile>& lf) {
|
||||
elem_map.gen("");
|
||||
},
|
||||
[&](const bookmark_metadata* bm) { elem_map.gen(""); });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
to_json(const attr_line_t& al)
|
||||
{
|
||||
yajlpp_gen gen;
|
||||
|
||||
yajl_gen_config(gen, yajl_gen_beautify, false);
|
||||
to_json(gen, al);
|
||||
|
||||
return gen.to_string_fragment().to_string();
|
||||
}
|
||||
|
||||
std::string
|
||||
to_json(const lnav::console::user_message& um)
|
||||
{
|
||||
yajlpp_gen gen;
|
||||
|
||||
yajl_gen_config(gen, yajl_gen_beautify, false);
|
||||
|
||||
{
|
||||
yajlpp_map root_map(gen);
|
||||
|
||||
root_map.gen("level");
|
||||
switch (um.um_level) {
|
||||
case console::user_message::level::ok:
|
||||
root_map.gen("ok");
|
||||
break;
|
||||
case console::user_message::level::info:
|
||||
root_map.gen("info");
|
||||
break;
|
||||
case console::user_message::level::warning:
|
||||
root_map.gen("warning");
|
||||
break;
|
||||
case console::user_message::level::error:
|
||||
root_map.gen("error");
|
||||
break;
|
||||
}
|
||||
|
||||
root_map.gen("message");
|
||||
to_json(gen, um.um_message);
|
||||
root_map.gen("reason");
|
||||
to_json(gen, um.um_reason);
|
||||
root_map.gen("snippets");
|
||||
{
|
||||
yajlpp_array snippet_array(gen);
|
||||
|
||||
for (const auto& snip : um.um_snippets) {
|
||||
yajlpp_map snip_map(gen);
|
||||
|
||||
snip_map.gen("source");
|
||||
snip_map.gen(snip.s_source);
|
||||
snip_map.gen("line");
|
||||
snip_map.gen(snip.s_line);
|
||||
snip_map.gen("column");
|
||||
snip_map.gen(snip.s_column);
|
||||
snip_map.gen("content");
|
||||
to_json(gen, snip.s_content);
|
||||
}
|
||||
}
|
||||
root_map.gen("help");
|
||||
to_json(gen, um.um_help);
|
||||
}
|
||||
|
||||
return gen.to_string_fragment().to_string();
|
||||
}
|
||||
|
||||
static int
|
||||
read_string_attr_type(yajlpp_parse_context* ypc,
|
||||
const unsigned char* str,
|
||||
size_t len)
|
||||
{
|
||||
auto* sa = (string_attr*) ypc->ypc_obj_stack.top();
|
||||
auto type = std::string((const char*) str, len);
|
||||
|
||||
if (type == "role") {
|
||||
sa->sa_type = &VC_ROLE;
|
||||
} else {
|
||||
ensure(false);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
read_string_attr_int_value(yajlpp_parse_context* ypc, int64_t in)
|
||||
{
|
||||
auto sa = (string_attr*) ypc->ypc_obj_stack.top();
|
||||
|
||||
if (sa->sa_type == &VC_ROLE) {
|
||||
sa->sa_value = (role_t) in;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct json_path_container string_attr_handlers = {
|
||||
yajlpp::property_handler("start").for_field(&string_attr::sa_range,
|
||||
&line_range::lr_start),
|
||||
yajlpp::property_handler("end").for_field(&string_attr::sa_range,
|
||||
&line_range::lr_end),
|
||||
yajlpp::property_handler("type").add_cb(read_string_attr_type),
|
||||
yajlpp::property_handler("value").add_cb(read_string_attr_int_value),
|
||||
};
|
||||
|
||||
static const struct json_path_container attr_line_handlers = {
|
||||
yajlpp::property_handler("str").for_field(&attr_line_t::al_string),
|
||||
yajlpp::property_handler("attrs#")
|
||||
.with_obj_provider<string_attr, attr_line_t>(
|
||||
[](const yajlpp_provider_context& ypc, attr_line_t* root) {
|
||||
root->al_attrs.resize(ypc.ypc_index + 1);
|
||||
|
||||
return &root->al_attrs[ypc.ypc_index];
|
||||
})
|
||||
.with_children(string_attr_handlers),
|
||||
};
|
||||
|
||||
template<>
|
||||
attr_line_t
|
||||
from_json(const std::string& json)
|
||||
{
|
||||
yajlpp_parse_context ypc("string", &attr_line_handlers);
|
||||
auto_mem<yajl_handle_t> handle(yajl_free);
|
||||
attr_line_t retval;
|
||||
|
||||
handle = yajl_alloc(&ypc.ypc_callbacks, nullptr, &ypc);
|
||||
ypc.with_handle(handle);
|
||||
ypc.with_obj(retval);
|
||||
ypc.parse(json);
|
||||
ypc.complete_parse();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static const json_path_container snippet_handlers = {
|
||||
yajlpp::property_handler("source").for_field(&console::snippet::s_source),
|
||||
yajlpp::property_handler("line").for_field(&console::snippet::s_line),
|
||||
yajlpp::property_handler("column").for_field(&console::snippet::s_column),
|
||||
yajlpp::property_handler("content")
|
||||
.with_obj_provider<attr_line_t, console::snippet>(
|
||||
[](const yajlpp_provider_context& ypc, console::snippet* snip) {
|
||||
return &snip->s_content;
|
||||
})
|
||||
.with_children(attr_line_handlers),
|
||||
};
|
||||
|
||||
static const json_path_handler_base::enum_value_t LEVEL_ENUM[] = {
|
||||
{"ok", lnav::console::user_message::level::ok},
|
||||
{"info", lnav::console::user_message::level::info},
|
||||
{"warning", lnav::console::user_message::level::warning},
|
||||
{"error", lnav::console::user_message::level::error},
|
||||
|
||||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
static const struct json_path_container user_message_handlers = {
|
||||
yajlpp::property_handler("level")
|
||||
.with_enum_values(LEVEL_ENUM)
|
||||
.for_field(&console::user_message::um_level),
|
||||
yajlpp::property_handler("message")
|
||||
.with_obj_provider<attr_line_t, console::user_message>(
|
||||
[](const yajlpp_provider_context& ypc,
|
||||
console::user_message* root) { return &root->um_message; })
|
||||
.with_children(attr_line_handlers),
|
||||
yajlpp::property_handler("reason")
|
||||
.with_obj_provider<attr_line_t, console::user_message>(
|
||||
[](const yajlpp_provider_context& ypc,
|
||||
console::user_message* root) { return &root->um_reason; })
|
||||
.with_children(attr_line_handlers),
|
||||
yajlpp::property_handler("snippets#")
|
||||
.with_obj_provider<console::snippet, console::user_message>(
|
||||
[](const yajlpp_provider_context& ypc,
|
||||
console::user_message* root) {
|
||||
root->um_snippets.resize(ypc.ypc_index + 1);
|
||||
|
||||
return &root->um_snippets[ypc.ypc_index];
|
||||
})
|
||||
.with_children(snippet_handlers),
|
||||
yajlpp::property_handler("help")
|
||||
.with_obj_provider<attr_line_t, console::user_message>(
|
||||
[](const yajlpp_provider_context& ypc,
|
||||
console::user_message* root) { return &root->um_help; })
|
||||
.with_children(attr_line_handlers),
|
||||
};
|
||||
|
||||
template<>
|
||||
lnav::console::user_message
|
||||
from_json(const std::string& json)
|
||||
{
|
||||
yajlpp_parse_context ypc("string", &user_message_handlers);
|
||||
auto_mem<yajl_handle_t> handle(yajl_free);
|
||||
lnav::console::user_message retval;
|
||||
|
||||
handle = yajl_alloc(&ypc.ypc_callbacks, nullptr, &ypc);
|
||||
ypc.with_handle(handle);
|
||||
ypc.with_obj(retval);
|
||||
ypc.parse(json);
|
||||
ypc.complete_parse();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
} // namespace lnav
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <time.h>
|
||||
|
||||
#include "base/intern_string.hh"
|
||||
#include "base/lnav.console.hh"
|
||||
#include "base/result.h"
|
||||
#include "byte_array.hh"
|
||||
#include "config.h"
|
||||
|
@ -229,6 +230,17 @@ finally(A act) // deduce action type
|
|||
|
||||
std::string ok_prefix(std::string msg);
|
||||
std::string err_prefix(std::string msg);
|
||||
Result<std::string, std::string> err_to_ok(std::string msg);
|
||||
Result<std::string, lnav::console::user_message> err_to_ok(
|
||||
lnav::console::user_message msg);
|
||||
|
||||
namespace lnav {
|
||||
|
||||
std::string to_json(const lnav::console::user_message& um);
|
||||
std::string to_json(const attr_line_t& al);
|
||||
|
||||
template<typename T>
|
||||
T from_json(const std::string& str);
|
||||
|
||||
} // namespace lnav
|
||||
|
||||
#endif
|
||||
|
|
|
@ -638,7 +638,7 @@ bool
|
|||
external_log_format::scan_for_partial(shared_buffer_ref& sbr,
|
||||
size_t& len_out) const
|
||||
{
|
||||
if (this->elf_type != ELF_TYPE_TEXT) {
|
||||
if (this->elf_type != elf_type_t::ELF_TYPE_TEXT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -660,13 +660,26 @@ external_log_format::scan_for_partial(shared_buffer_ref& sbr,
|
|||
return (int) len_out > pat->p_timestamp_end;
|
||||
}
|
||||
|
||||
std::vector<lnav::console::snippet>
|
||||
external_log_format::get_snippets() const
|
||||
{
|
||||
std::vector<lnav::console::snippet> retval;
|
||||
|
||||
for (const auto& src_pair : this->elf_format_sources) {
|
||||
retval.emplace_back(lnav::console::snippet::from(src_pair.first, "")
|
||||
.with_line(src_pair.second));
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
log_format::scan_result_t
|
||||
external_log_format::scan(logfile& lf,
|
||||
std::vector<logline>& dst,
|
||||
const line_info& li,
|
||||
shared_buffer_ref& sbr)
|
||||
{
|
||||
if (this->elf_type == ELF_TYPE_JSON) {
|
||||
if (this->elf_type == elf_type_t::ELF_TYPE_JSON) {
|
||||
yajlpp_parse_context& ypc = *(this->jlf_parse_context);
|
||||
logline ll(li.li_file_range.fr_offset, 0, 0, LEVEL_INFO);
|
||||
yajl_handle handle = this->jlf_yajl_handle.get();
|
||||
|
@ -852,7 +865,7 @@ external_log_format::scan(logfile& lf,
|
|||
= *mod_elf->elf_pattern_order[mod_pat_index];
|
||||
|
||||
if (mod_pat.p_pcre->match(mod_pc, mod_pi)) {
|
||||
auto mod_level_cap
|
||||
auto* mod_level_cap
|
||||
= mod_pc[mod_pat.p_level_field_index];
|
||||
|
||||
level = mod_elf->convert_level(mod_pi, mod_level_cap);
|
||||
|
@ -991,7 +1004,7 @@ external_log_format::annotate(uint64_t line_number,
|
|||
struct line_range lr;
|
||||
pcre_context::capture_t *cap, *body_cap, *module_cap = nullptr;
|
||||
|
||||
if (this->elf_type != ELF_TYPE_TEXT) {
|
||||
if (this->elf_type != elf_type_t::ELF_TYPE_TEXT) {
|
||||
values = this->jlf_line_values;
|
||||
sa = this->jlf_line_attrs;
|
||||
return;
|
||||
|
@ -1152,7 +1165,9 @@ external_log_format::rewrite(exec_context& ec,
|
|||
}
|
||||
|
||||
auto _sg = ec.enter_source(
|
||||
this->elf_name.to_string() + ":" + vd_iter->first.to_string(), 1);
|
||||
this->elf_name.to_string() + ":" + vd_iter->first.to_string(),
|
||||
1,
|
||||
vd.vd_rewriter);
|
||||
auto field_value
|
||||
= execute_any(ec, vd.vd_rewriter).orElse(err_to_ok).unwrap();
|
||||
struct line_range adj_origin
|
||||
|
@ -1297,7 +1312,7 @@ external_log_format::get_subline(const logline& ll,
|
|||
shared_buffer_ref& sbr,
|
||||
bool full_message)
|
||||
{
|
||||
if (this->elf_type == ELF_TYPE_TEXT) {
|
||||
if (this->elf_type == elf_type_t::ELF_TYPE_TEXT) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1382,9 +1397,10 @@ external_log_format::get_subline(const logline& ll,
|
|||
jfe.jfe_default_value.size());
|
||||
break;
|
||||
case JLF_VARIABLE:
|
||||
lv_iter = find_if(this->jlf_line_values.begin(),
|
||||
this->jlf_line_values.end(),
|
||||
logline_value_cmp(&jfe.jfe_value));
|
||||
lv_iter = find_if(
|
||||
this->jlf_line_values.begin(),
|
||||
this->jlf_line_values.end(),
|
||||
logline_value_cmp(&jfe.jfe_value.pp_value));
|
||||
if (lv_iter != this->jlf_line_values.end()) {
|
||||
auto str = lv_iter->to_string();
|
||||
size_t nl_pos = str.find('\n');
|
||||
|
@ -1458,7 +1474,7 @@ external_log_format::get_subline(const logline& ll,
|
|||
used_values[distance(this->jlf_line_values.begin(),
|
||||
lv_iter)]
|
||||
= true;
|
||||
} else if (jfe.jfe_value == ts_field) {
|
||||
} else if (jfe.jfe_value.pp_value == ts_field) {
|
||||
struct line_range lr;
|
||||
ssize_t ts_len;
|
||||
char ts[64];
|
||||
|
@ -1490,7 +1506,10 @@ external_log_format::get_subline(const logline& ll,
|
|||
this->jlf_line_values.begin(), lv_iter)]
|
||||
= true;
|
||||
}
|
||||
} else if (jfe.jfe_value == level_field) {
|
||||
} else if (jfe.jfe_value.pp_value == level_field
|
||||
|| jfe.jfe_value.pp_value
|
||||
== this->elf_level_field)
|
||||
{
|
||||
this->json_append(jfe, ll.get_level_name(), -1);
|
||||
} else {
|
||||
this->json_append(jfe,
|
||||
|
@ -1623,7 +1642,7 @@ external_log_format::get_subline(const logline& ll,
|
|||
}
|
||||
|
||||
void
|
||||
external_log_format::build(std::vector<std::string>& errors)
|
||||
external_log_format::build(std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
if (!this->lf_timestamp_field.empty()) {
|
||||
auto& vd = this->elf_value_defs[this->lf_timestamp_field];
|
||||
|
@ -1635,6 +1654,10 @@ external_log_format::build(std::vector<std::string>& errors)
|
|||
vd->vd_meta.lvm_kind = value_kind_t::VALUE_TEXT;
|
||||
vd->vd_internal = true;
|
||||
}
|
||||
if (startswith(this->elf_level_field.get(), "/")) {
|
||||
this->elf_level_field
|
||||
= intern_string::lookup(this->elf_level_field.get() + 1);
|
||||
}
|
||||
if (!this->elf_level_field.empty()
|
||||
&& this->elf_value_defs.find(this->elf_level_field)
|
||||
== this->elf_value_defs.end())
|
||||
|
@ -1662,35 +1685,20 @@ external_log_format::build(std::vector<std::string>& errors)
|
|||
if (!this->lf_timestamp_format.empty()) {
|
||||
this->lf_timestamp_format.push_back(nullptr);
|
||||
}
|
||||
try {
|
||||
this->elf_filename_pcre
|
||||
= std::make_shared<pcrepp>(this->elf_file_pattern);
|
||||
} catch (const pcrepp::error& e) {
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ".file-pattern:" + e.what());
|
||||
}
|
||||
for (auto iter = this->elf_patterns.begin();
|
||||
iter != this->elf_patterns.end();
|
||||
++iter)
|
||||
{
|
||||
pattern& pat = *iter->second;
|
||||
|
||||
if (pat.p_pcre == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pat.p_module_format) {
|
||||
this->elf_has_module_format = true;
|
||||
}
|
||||
|
||||
try {
|
||||
pat.p_pcre = std::make_unique<pcrepp>(pat.p_string, PCRE_DOTALL);
|
||||
} catch (const pcrepp::error& e) {
|
||||
errors.push_back("error:" + this->elf_name.to_string() + ".regex["
|
||||
+ iter->first + "]" + ":" + e.what());
|
||||
errors.push_back("error:" + this->elf_name.to_string() + ".regex["
|
||||
+ iter->first + "]" + ":" + pat.p_string);
|
||||
errors.push_back("error:" + this->elf_name.to_string() + ".regex["
|
||||
+ iter->first + "]" + ":"
|
||||
+ std::string(e.e_offset, ' ') + "^");
|
||||
continue;
|
||||
}
|
||||
for (pcre_named_capture::iterator name_iter = pat.p_pcre->named_begin();
|
||||
name_iter != pat.p_pcre->named_end();
|
||||
++name_iter)
|
||||
|
@ -1772,12 +1780,18 @@ external_log_format::build(std::vector<std::string>& errors)
|
|||
this->elf_pattern_order.push_back(iter->second);
|
||||
}
|
||||
|
||||
if (this->elf_type != ELF_TYPE_TEXT) {
|
||||
if (this->elf_type != elf_type_t::ELF_TYPE_TEXT) {
|
||||
if (!this->elf_patterns.empty()) {
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ": structured logs cannot have regexes");
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t()
|
||||
.append_quoted(
|
||||
lnav::roles::symbol(this->elf_name.to_string()))
|
||||
.append(" is not a valid log format"))
|
||||
.with_reason("structured logs cannot have regexes")
|
||||
.with_snippets(this->get_snippets()));
|
||||
}
|
||||
if (this->elf_type == ELF_TYPE_JSON) {
|
||||
if (this->elf_type == elf_type_t::ELF_TYPE_JSON) {
|
||||
this->jlf_parse_context = std::make_shared<yajlpp_parse_context>(
|
||||
this->elf_name.to_string());
|
||||
this->jlf_yajl_handle.reset(
|
||||
|
@ -1791,18 +1805,13 @@ external_log_format::build(std::vector<std::string>& errors)
|
|||
|
||||
} else {
|
||||
if (this->elf_patterns.empty()) {
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ": no regexes specified for format");
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& elf_level_pattern : this->elf_level_patterns) {
|
||||
try {
|
||||
elf_level_pattern.second.lp_pcre = std::make_shared<pcrepp>(
|
||||
elf_level_pattern.second.lp_regex.c_str());
|
||||
} catch (const pcrepp::error& e) {
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ".level:" + e.what());
|
||||
errors.emplace_back(lnav::console::user_message::error(
|
||||
attr_line_t()
|
||||
.append_quoted(lnav::roles::symbol(
|
||||
this->elf_name.to_string()))
|
||||
.append(" is not a valid log format"))
|
||||
.with_reason("no regexes specified")
|
||||
.with_snippets(this->get_snippets()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1825,22 +1834,31 @@ external_log_format::build(std::vector<std::string>& errors)
|
|||
{
|
||||
if (this->lf_action_defs.find(*act_iter)
|
||||
== this->lf_action_defs.end()) {
|
||||
#if 0
|
||||
errors.push_back("error:" + this->elf_name.to_string() + ":"
|
||||
+ vd->vd_meta.lvm_name.get()
|
||||
+ ": cannot find action -- " + (*act_iter));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this->elf_type == ELF_TYPE_TEXT && this->elf_samples.empty()) {
|
||||
errors.push_back(
|
||||
"error:" + this->elf_name.to_string()
|
||||
+ ":no sample logs provided, all formats must have samples");
|
||||
if (this->elf_type == elf_type_t::ELF_TYPE_TEXT
|
||||
&& this->elf_samples.empty()) {
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t()
|
||||
.append_quoted(
|
||||
lnav::roles::symbol(this->elf_name.to_string()))
|
||||
.append(" is not a valid log format"))
|
||||
.with_reason("log message samples must be included in a format "
|
||||
"definition")
|
||||
.with_snippets(this->get_snippets()));
|
||||
}
|
||||
|
||||
for (auto& elf_sample : this->elf_samples) {
|
||||
pcre_context_static<128> pc;
|
||||
pcre_input pi(elf_sample.s_line);
|
||||
pcre_input pi(elf_sample.s_line.pp_value);
|
||||
bool found = false;
|
||||
|
||||
for (auto pat_iter = this->elf_pattern_order.begin();
|
||||
|
@ -1853,100 +1871,136 @@ external_log_format::build(std::vector<std::string>& errors)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!pat.p_module_format
|
||||
&& pat.p_pcre->name_index(this->lf_timestamp_field.to_string())
|
||||
< 0)
|
||||
{
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ":timestamp field '"
|
||||
+ this->lf_timestamp_field.get()
|
||||
+ "' not found in pattern -- " + pat.p_string);
|
||||
if (!pat.p_pcre->match(pc, pi)) {
|
||||
continue;
|
||||
}
|
||||
found = true;
|
||||
|
||||
if (pat.p_module_format) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pat.p_pcre->match(pc, pi)) {
|
||||
if (pat.p_module_format) {
|
||||
found = true;
|
||||
continue;
|
||||
}
|
||||
pcre_context::capture_t* ts_cap
|
||||
= pc[this->lf_timestamp_field.get()];
|
||||
pcre_context::capture_t* level_cap
|
||||
= pc[pat.p_level_field_index];
|
||||
const char* ts = pi.get_substr_start(ts_cap);
|
||||
ssize_t ts_len = pc[this->lf_timestamp_field.get()]->length();
|
||||
const char* const* custom_formats
|
||||
= this->get_timestamp_formats();
|
||||
date_time_scanner dts;
|
||||
struct timeval tv;
|
||||
struct exttm tm;
|
||||
if (pat.p_pcre->name_index(this->lf_timestamp_field.to_string())
|
||||
< 0) {
|
||||
attr_line_t notes;
|
||||
bool first_note = true;
|
||||
|
||||
if (ts_cap->c_begin == 0) {
|
||||
pat.p_timestamp_end = ts_cap->c_end;
|
||||
if (pat.p_pcre->p_named_count > 0) {
|
||||
notes.append("the following captures are available:\n ");
|
||||
}
|
||||
found = true;
|
||||
if (ts_len == -1
|
||||
|| dts.scan(ts, ts_len, custom_formats, &tm, tv) == nullptr)
|
||||
for (auto name_iter = pat.p_pcre->named_begin();
|
||||
name_iter != pat.p_pcre->named_end();
|
||||
++name_iter)
|
||||
{
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ":invalid sample -- "
|
||||
+ elf_sample.s_line);
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ":unrecognized timestamp format -- "
|
||||
+ ts);
|
||||
if (!first_note) {
|
||||
notes.append(", ");
|
||||
}
|
||||
notes.append(lnav::roles::symbol(name_iter->pnc_name));
|
||||
first_note = false;
|
||||
}
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("invalid value for property ")
|
||||
.append_quoted(lnav::roles::symbol(
|
||||
fmt::format(FMT_STRING("/{}/timestamp-field"),
|
||||
this->elf_name))))
|
||||
.with_reason(
|
||||
attr_line_t()
|
||||
.append_quoted(this->lf_timestamp_field)
|
||||
.append(" was not found in the pattern at ")
|
||||
.append(lnav::roles::symbol(pat.p_config_path)))
|
||||
.with_note(notes)
|
||||
.with_snippets(this->get_snippets()));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (custom_formats == nullptr) {
|
||||
for (int lpc = 0; PTIMEC_FORMATS[lpc].pf_fmt != nullptr;
|
||||
lpc++) {
|
||||
off_t off = 0;
|
||||
const auto* ts_cap = pc[this->lf_timestamp_field.get()];
|
||||
const auto* level_cap = pc[pat.p_level_field_index];
|
||||
const char* ts = pi.get_substr_start(ts_cap);
|
||||
ssize_t ts_len = pc[this->lf_timestamp_field.get()]->length();
|
||||
const char* const* custom_formats = this->get_timestamp_formats();
|
||||
date_time_scanner dts;
|
||||
struct timeval tv;
|
||||
struct exttm tm;
|
||||
|
||||
PTIMEC_FORMATS[lpc].pf_func(&tm, ts, off, ts_len);
|
||||
errors.push_back(
|
||||
" format: "
|
||||
+ std::string(PTIMEC_FORMATS[lpc].pf_fmt)
|
||||
+ "; matched: " + std::string(ts, off));
|
||||
}
|
||||
} else {
|
||||
for (int lpc = 0; custom_formats[lpc] != nullptr; lpc++)
|
||||
{
|
||||
off_t off = 0;
|
||||
if (ts_cap->c_begin == 0) {
|
||||
pat.p_timestamp_end = ts_cap->c_end;
|
||||
}
|
||||
if (ts_len == -1
|
||||
|| dts.scan(ts, ts_len, custom_formats, &tm, tv) == nullptr) {
|
||||
attr_line_t notes;
|
||||
|
||||
ptime_fmt(
|
||||
custom_formats[lpc], &tm, ts, off, ts_len);
|
||||
errors.push_back(
|
||||
" format: " + std::string(custom_formats[lpc])
|
||||
+ "; matched: " + std::string(ts, off));
|
||||
}
|
||||
notes.append("the following formats were tried:");
|
||||
if (custom_formats == nullptr) {
|
||||
for (int lpc = 0; PTIMEC_FORMATS[lpc].pf_fmt != nullptr;
|
||||
lpc++) {
|
||||
off_t off = 0;
|
||||
|
||||
PTIMEC_FORMATS[lpc].pf_func(&tm, ts, off, ts_len);
|
||||
notes.append("\n ")
|
||||
.append(ts, (size_t) ts_len)
|
||||
.append("\n")
|
||||
.append(2 + off, ' ')
|
||||
.append(lnav::roles::comment("^ "))
|
||||
.append_quoted(
|
||||
lnav::roles::symbol(PTIMEC_FORMATS[lpc].pf_fmt))
|
||||
.append(
|
||||
lnav::roles::comment(" matched up to here"));
|
||||
}
|
||||
} else {
|
||||
for (int lpc = 0; custom_formats[lpc] != nullptr; lpc++) {
|
||||
off_t off = 0;
|
||||
|
||||
ptime_fmt(custom_formats[lpc], &tm, ts, off, ts_len);
|
||||
notes.append("\n ")
|
||||
.append(ts, (size_t) ts_len)
|
||||
.append("\n")
|
||||
.append(2 + off, ' ')
|
||||
.append(lnav::roles::comment("^ "))
|
||||
.append_quoted(
|
||||
lnav::roles::symbol(custom_formats[lpc]))
|
||||
.append(
|
||||
lnav::roles::comment(" matched up to here"));
|
||||
}
|
||||
}
|
||||
|
||||
log_level_t level = this->convert_level(pi, level_cap);
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("invalid sample log message ")
|
||||
.append_quoted(elf_sample.s_line.pp_value))
|
||||
.with_reason(attr_line_t("unrecognized timestamp -- ")
|
||||
.append(ts, (size_t) ts_len))
|
||||
.with_snippet(elf_sample.s_line.to_snippet())
|
||||
.with_note(notes));
|
||||
}
|
||||
|
||||
if (elf_sample.s_level != LEVEL_UNKNOWN) {
|
||||
if (elf_sample.s_level != level) {
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ":invalid sample -- "
|
||||
+ elf_sample.s_line);
|
||||
errors.push_back(
|
||||
"error:" + this->elf_name.to_string()
|
||||
+ ":parsed level '" + level_names[level]
|
||||
+ "' does not match expected level of '"
|
||||
+ level_names[elf_sample.s_level] + "'");
|
||||
}
|
||||
}
|
||||
log_level_t level = this->convert_level(pi, level_cap);
|
||||
|
||||
if (elf_sample.s_level != LEVEL_UNKNOWN
|
||||
&& elf_sample.s_level != level) {
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("invalid sample log message ")
|
||||
.append_quoted(elf_sample.s_line.pp_value))
|
||||
.with_reason(attr_line_t()
|
||||
.append_quoted(lnav::roles::symbol(
|
||||
level_names[level]))
|
||||
.append(" does not match the expected "
|
||||
"level of ")
|
||||
.append_quoted(lnav::roles::symbol(
|
||||
level_names[elf_sample.s_level])))
|
||||
.with_snippet(elf_sample.s_line.to_snippet()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ":invalid sample -- "
|
||||
+ elf_sample.s_line);
|
||||
if (!found && !this->elf_pattern_order.empty()) {
|
||||
attr_line_t notes(
|
||||
"the following shows how each pattern matched this sample:\n");
|
||||
size_t max_name_width = 0;
|
||||
|
||||
for (auto pat_iter = this->elf_pattern_order.begin();
|
||||
pat_iter != this->elf_pattern_order.end();
|
||||
++pat_iter)
|
||||
{
|
||||
pattern& pat = *(*pat_iter);
|
||||
notes.append(" ").append_quoted(elf_sample.s_line.pp_value);
|
||||
for (const auto& pat_iter : this->elf_pattern_order) {
|
||||
pattern& pat = *pat_iter;
|
||||
|
||||
if (!pat.p_pcre) {
|
||||
continue;
|
||||
|
@ -1954,19 +2008,42 @@ external_log_format::build(std::vector<std::string>& errors)
|
|||
|
||||
size_t partial_len = pat.p_pcre->match_partial(pi);
|
||||
|
||||
if (partial_len > 0) {
|
||||
errors.push_back(
|
||||
"error:" + this->elf_name.to_string()
|
||||
+ ":partial sample matched -- "
|
||||
+ elf_sample.s_line.substr(0, partial_len));
|
||||
errors.push_back("error: against pattern "
|
||||
+ (*pat_iter)->p_config_path + " -- "
|
||||
+ (*pat_iter)->p_string);
|
||||
} else {
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ":no partial match found");
|
||||
}
|
||||
notes.append("\n ")
|
||||
.append(partial_len, ' ')
|
||||
.append(lnav::roles::comment("^ "))
|
||||
.append(lnav::roles::symbol(pat.p_name))
|
||||
.append(lnav::roles::comment(" matched up to here"));
|
||||
|
||||
max_name_width = std::max(max_name_width, pat.p_name.size());
|
||||
}
|
||||
|
||||
attr_line_t help;
|
||||
for (const auto& pat_iter : this->elf_pattern_order) {
|
||||
if (!pat_iter->p_pcre) {
|
||||
help.append(
|
||||
lnav::roles::symbol(fmt::format(FMT_STRING("{:{}}"),
|
||||
pat_iter->p_name,
|
||||
max_name_width)))
|
||||
.append(" is invalid");
|
||||
continue;
|
||||
}
|
||||
|
||||
help
|
||||
.append(lnav::roles::symbol(fmt::format(
|
||||
FMT_STRING("{:{}}"), pat_iter->p_name, max_name_width)))
|
||||
.append(" = ")
|
||||
.append(pat_iter->p_pcre->get_pattern())
|
||||
.append("\n");
|
||||
}
|
||||
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("invalid sample log message ")
|
||||
.append_quoted(elf_sample.s_line.pp_value))
|
||||
.with_reason("sample does not match any patterns")
|
||||
.with_snippet(elf_sample.s_line.to_snippet())
|
||||
.with_note(notes)
|
||||
.with_help(help));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2002,41 +2079,48 @@ external_log_format::build(std::vector<std::string>& errors)
|
|||
= intern_string::lookup("__level__");
|
||||
json_format_element& jfe = *iter;
|
||||
|
||||
if (startswith(jfe.jfe_value.get(), "/")) {
|
||||
jfe.jfe_value = intern_string::lookup(jfe.jfe_value.get() + 1);
|
||||
if (startswith(jfe.jfe_value.pp_value.get(), "/")) {
|
||||
jfe.jfe_value.pp_value
|
||||
= intern_string::lookup(jfe.jfe_value.pp_value.get() + 1);
|
||||
}
|
||||
if (!jfe.jfe_ts_format.empty()) {
|
||||
if (!jfe.jfe_value.empty() && jfe.jfe_value != ts) {
|
||||
if (!jfe.jfe_value.pp_value.empty() && jfe.jfe_value.pp_value != ts)
|
||||
{
|
||||
log_warning(
|
||||
"%s:line-format[%d]:ignoring field '%s' since "
|
||||
"timestamp-format was used",
|
||||
this->elf_name.get(),
|
||||
format_index,
|
||||
jfe.jfe_value.get());
|
||||
jfe.jfe_value.pp_value.get());
|
||||
}
|
||||
jfe.jfe_value = ts;
|
||||
jfe.jfe_value.pp_value = ts;
|
||||
}
|
||||
|
||||
switch (jfe.jfe_type) {
|
||||
case JLF_VARIABLE: {
|
||||
auto vd_iter = this->elf_value_defs.find(jfe.jfe_value);
|
||||
if (jfe.jfe_value == ts) {
|
||||
auto vd_iter
|
||||
= this->elf_value_defs.find(jfe.jfe_value.pp_value);
|
||||
if (jfe.jfe_value.pp_value == ts) {
|
||||
this->elf_value_defs[this->lf_timestamp_field]
|
||||
->vd_meta.lvm_hidden
|
||||
= true;
|
||||
} else if (jfe.jfe_value == level_field) {
|
||||
} else if (jfe.jfe_value.pp_value == level_field) {
|
||||
this->elf_value_defs[this->elf_level_field]
|
||||
->vd_meta.lvm_hidden
|
||||
= true;
|
||||
} else if (vd_iter == this->elf_value_defs.end()) {
|
||||
char index_str[32];
|
||||
|
||||
snprintf(index_str, sizeof(index_str), "%d", format_index);
|
||||
errors.push_back(
|
||||
"error:" + this->elf_name.to_string() + ":line-format["
|
||||
+ index_str
|
||||
+ "]:line format variable is not defined -- "
|
||||
+ jfe.jfe_value.to_string());
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("invalid line format element ")
|
||||
.append_quoted(lnav::roles::symbol(fmt::format(
|
||||
FMT_STRING("/{}/line-format/{}/field"),
|
||||
this->elf_name,
|
||||
format_index))))
|
||||
.with_reason(
|
||||
attr_line_t()
|
||||
.append_quoted(jfe.jfe_value.pp_value)
|
||||
.append(" is not a defined value"))
|
||||
.with_snippet(jfe.jfe_value.to_snippet()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2053,30 +2137,44 @@ external_log_format::build(std::vector<std::string>& errors)
|
|||
|
||||
for (auto& hd_pair : this->elf_highlighter_patterns) {
|
||||
external_log_format::highlighter_def& hd = hd_pair.second;
|
||||
const std::string& pattern = hd.hd_pattern;
|
||||
const char* errptr;
|
||||
auto fg = styling::color_unit::make_empty();
|
||||
auto bg = styling::color_unit::make_empty();
|
||||
int eoff, attrs = 0;
|
||||
|
||||
if (!hd.hd_color.empty()) {
|
||||
fg = styling::color_unit::from_str(hd.hd_color)
|
||||
if (!hd.hd_color.pp_value.empty()) {
|
||||
fg = styling::color_unit::from_str(hd.hd_color.pp_value)
|
||||
.unwrapOrElse([&](const auto& msg) {
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ":highlighters/"
|
||||
+ hd_pair.first.to_string()
|
||||
+ "/color:" + msg);
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t()
|
||||
.append_quoted(hd.hd_color.pp_value)
|
||||
.append(" is not a valid color value for "
|
||||
"property ")
|
||||
.append_quoted(lnav::roles::symbol(
|
||||
hd.hd_color.pp_path.to_string())))
|
||||
.with_reason(msg)
|
||||
.with_snippet(hd.hd_color.to_snippet()));
|
||||
return styling::color_unit::make_empty();
|
||||
});
|
||||
}
|
||||
|
||||
if (!hd.hd_background_color.empty()) {
|
||||
bg = styling::color_unit::from_str(hd.hd_background_color)
|
||||
if (!hd.hd_background_color.pp_value.empty()) {
|
||||
bg = styling::color_unit::from_str(hd.hd_background_color.pp_value)
|
||||
.unwrapOrElse([&](const auto& msg) {
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ":highlighters/"
|
||||
+ hd_pair.first.to_string()
|
||||
+ "/color:" + msg);
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t()
|
||||
.append_quoted(
|
||||
hd.hd_background_color.pp_value)
|
||||
.append(" is not a valid color value for "
|
||||
"property ")
|
||||
.append_quoted(lnav::roles::symbol(
|
||||
hd.hd_background_color.pp_path
|
||||
.to_string())))
|
||||
.with_reason(msg)
|
||||
.with_snippet(
|
||||
hd.hd_background_color.to_snippet()));
|
||||
return styling::color_unit::make_empty();
|
||||
});
|
||||
}
|
||||
|
@ -2088,58 +2186,46 @@ external_log_format::build(std::vector<std::string>& errors)
|
|||
attrs |= A_BLINK;
|
||||
}
|
||||
|
||||
pcre* code = pcre_compile(
|
||||
pattern.c_str(), PCRE_CASELESS, &errptr, &eoff, nullptr);
|
||||
if (hd.hd_pattern != nullptr) {
|
||||
pcre* code = pcre_compile(hd.hd_pattern->get_pattern().c_str(),
|
||||
PCRE_CASELESS,
|
||||
&errptr,
|
||||
&eoff,
|
||||
nullptr);
|
||||
|
||||
if (code == nullptr) {
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ":highlighters/" + hd_pair.first.to_string()
|
||||
+ ":" + std::string(errptr));
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ":highlighters/" + hd_pair.first.to_string()
|
||||
+ ":" + pattern);
|
||||
errors.push_back("error:" + this->elf_name.to_string()
|
||||
+ ":highlighters/" + hd_pair.first.to_string()
|
||||
+ ":" + std::string(eoff, ' ') + "^");
|
||||
} else {
|
||||
this->lf_highlighters.emplace_back(code);
|
||||
this->lf_highlighters.back()
|
||||
.with_pattern(pattern)
|
||||
.with_format_name(this->elf_name)
|
||||
.with_color(fg, bg)
|
||||
.with_attrs(attrs);
|
||||
if (code == nullptr) {
|
||||
log_error("unable to recompile highlighter pattern");
|
||||
} else {
|
||||
this->lf_highlighters.emplace_back(code);
|
||||
this->lf_highlighters.back()
|
||||
.with_pattern(hd.hd_pattern->get_pattern())
|
||||
.with_format_name(this->elf_name)
|
||||
.with_color(fg, bg)
|
||||
.with_attrs(attrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
external_log_format::register_vtabs(log_vtab_manager* vtab_manager,
|
||||
std::vector<std::string>& errors)
|
||||
external_log_format::register_vtabs(
|
||||
log_vtab_manager* vtab_manager,
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
for (auto search_iter = this->elf_search_tables.begin();
|
||||
search_iter != this->elf_search_tables.end();
|
||||
++search_iter)
|
||||
{
|
||||
auto re_res = pcrepp::from_str(search_iter->second,
|
||||
log_search_table::pattern_options());
|
||||
|
||||
if (re_res.isErr()) {
|
||||
errors.emplace_back(fmt::format(
|
||||
FMT_STRING("error:{}:{}:unable to compile regex '{}': {}"),
|
||||
this->elf_name.get(),
|
||||
search_iter->first.get(),
|
||||
search_iter->second,
|
||||
re_res.unwrapErr().ce_msg));
|
||||
for (auto& elf_search_table : this->elf_search_tables) {
|
||||
if (elf_search_table.second.std_pattern == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto lst = std::make_shared<log_search_table>(re_res.unwrap(),
|
||||
search_iter->first);
|
||||
auto lst = std::make_shared<log_search_table>(
|
||||
*elf_search_table.second.std_pattern, elf_search_table.first);
|
||||
auto errmsg = vtab_manager->register_vtab(lst);
|
||||
if (!errmsg.empty()) {
|
||||
#if 0
|
||||
errors.push_back("error:" + this->elf_name.to_string() + ":"
|
||||
+ search_iter->first.to_string()
|
||||
+ ":unable to register table -- " + errmsg);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2156,7 +2242,7 @@ external_log_format::match_samples(const std::vector<sample>& samples) const
|
|||
}
|
||||
|
||||
pcre_context_static<128> pc;
|
||||
pcre_input pi(sample_iter.s_line);
|
||||
pcre_input pi(sample_iter.s_line.pp_value);
|
||||
|
||||
if (pat.p_pcre->match(pc, pi)) {
|
||||
return true;
|
||||
|
@ -2317,7 +2403,7 @@ external_log_format::specialized(int fmt_lock)
|
|||
retval->lf_pattern_locks.emplace_back(0, fmt_lock);
|
||||
}
|
||||
|
||||
if (this->elf_type == ELF_TYPE_JSON) {
|
||||
if (this->elf_type == elf_type_t::ELF_TYPE_JSON) {
|
||||
this->jlf_parse_context = std::make_shared<yajlpp_parse_context>(
|
||||
this->elf_name.to_string());
|
||||
this->jlf_yajl_handle.reset(
|
||||
|
|
|
@ -42,9 +42,9 @@ class module_format;
|
|||
class external_log_format : public log_format {
|
||||
public:
|
||||
struct sample {
|
||||
sample() : s_level(LEVEL_UNKNOWN){};
|
||||
sample() : s_level(LEVEL_UNKNOWN) {}
|
||||
|
||||
std::string s_line;
|
||||
positioned_property<std::string> s_line;
|
||||
log_level_t s_level;
|
||||
};
|
||||
|
||||
|
@ -87,9 +87,9 @@ public:
|
|||
};
|
||||
|
||||
struct pattern {
|
||||
std::string p_name;
|
||||
std::string p_config_path;
|
||||
std::string p_string;
|
||||
std::unique_ptr<pcrepp> p_pcre;
|
||||
std::shared_ptr<pcrepp> p_pcre;
|
||||
std::vector<indexed_value_def> p_value_by_index;
|
||||
std::vector<int> p_numeric_value_indexes;
|
||||
int p_timestamp_field_index{-1};
|
||||
|
@ -116,12 +116,8 @@ public:
|
|||
};
|
||||
|
||||
external_log_format(const intern_string_t name)
|
||||
: elf_column_count(0), elf_timestamp_divisor(1.0),
|
||||
elf_level_field(intern_string::lookup("level", -1)),
|
||||
: elf_level_field(intern_string::lookup("level", -1)),
|
||||
elf_body_field(intern_string::lookup("body", -1)),
|
||||
elf_container(false), elf_has_module_format(false),
|
||||
elf_builtin_format(false), elf_type(ELF_TYPE_TEXT),
|
||||
jlf_hide_extra(false), jlf_cached_offset(-1),
|
||||
jlf_yajl_handle(nullptr, yajl_handle_deleter()), elf_name(name)
|
||||
{
|
||||
this->jlf_line_offsets.reserve(128);
|
||||
|
@ -154,10 +150,10 @@ public:
|
|||
string_attrs_t& sa,
|
||||
std::string& value_out);
|
||||
|
||||
void build(std::vector<std::string>& errors);
|
||||
void build(std::vector<lnav::console::user_message>& errors);
|
||||
|
||||
void register_vtabs(log_vtab_manager* vtab_manager,
|
||||
std::vector<std::string>& errors);
|
||||
std::vector<lnav::console::user_message>& errors);
|
||||
|
||||
bool match_samples(const std::vector<sample>& samples) const;
|
||||
|
||||
|
@ -246,7 +242,7 @@ public:
|
|||
jfe_text_transform(transform_t::NONE){};
|
||||
|
||||
json_log_field jfe_type;
|
||||
intern_string_t jfe_value;
|
||||
positioned_property<intern_string_t> jfe_value;
|
||||
std::string jfe_default_value;
|
||||
long long jfe_min_width;
|
||||
long long jfe_max_width;
|
||||
|
@ -263,7 +259,7 @@ public:
|
|||
bool operator()(const json_format_element& jfe) const
|
||||
{
|
||||
return (this->jfc_type == jfe.jfe_type
|
||||
&& this->jfc_field_name == jfe.jfe_value);
|
||||
&& this->jfc_field_name == jfe.jfe_value.pp_value);
|
||||
};
|
||||
|
||||
json_log_field jfc_type;
|
||||
|
@ -273,9 +269,9 @@ public:
|
|||
struct highlighter_def {
|
||||
highlighter_def() : hd_underline(false), hd_blink(false) {}
|
||||
|
||||
std::string hd_pattern;
|
||||
std::string hd_color;
|
||||
std::string hd_background_color;
|
||||
std::shared_ptr<pcrepp> hd_pattern;
|
||||
positioned_property<std::string> hd_color;
|
||||
positioned_property<std::string> hd_background_color;
|
||||
bool hd_underline;
|
||||
bool hd_blink;
|
||||
};
|
||||
|
@ -317,7 +313,7 @@ public:
|
|||
|
||||
std::string get_pattern_name(uint64_t line_number) const
|
||||
{
|
||||
if (this->elf_type != ELF_TYPE_TEXT) {
|
||||
if (this->elf_type != elf_type_t::ELF_TYPE_TEXT) {
|
||||
return "structured";
|
||||
}
|
||||
int pat_index = this->pattern_index_for_line(line_number);
|
||||
|
@ -326,15 +322,15 @@ public:
|
|||
|
||||
std::string get_pattern_regex(uint64_t line_number) const
|
||||
{
|
||||
if (this->elf_type != ELF_TYPE_TEXT) {
|
||||
if (this->elf_type != elf_type_t::ELF_TYPE_TEXT) {
|
||||
return "";
|
||||
}
|
||||
int pat_index = this->pattern_index_for_line(line_number);
|
||||
return this->elf_pattern_order[pat_index]->p_string;
|
||||
return this->elf_pattern_order[pat_index]->p_pcre->get_pattern();
|
||||
}
|
||||
|
||||
log_level_t convert_level(const pcre_input& pi,
|
||||
pcre_context::capture_t* level_cap) const
|
||||
const pcre_context::capture_t* level_cap) const
|
||||
{
|
||||
log_level_t retval = LEVEL_INFO;
|
||||
|
||||
|
@ -360,12 +356,13 @@ public:
|
|||
return retval;
|
||||
}
|
||||
|
||||
typedef std::map<intern_string_t, module_format> mod_map_t;
|
||||
using mod_map_t = std::map<intern_string_t, module_format>;
|
||||
static mod_map_t MODULE_FORMATS;
|
||||
static std::vector<std::shared_ptr<external_log_format>>
|
||||
GRAPH_ORDERED_FORMATS;
|
||||
|
||||
std::set<std::string> elf_source_path;
|
||||
std::unordered_map<std::string, int> elf_format_sources;
|
||||
std::list<intern_string_t> elf_collision;
|
||||
std::string elf_file_pattern;
|
||||
std::set<file_format_t> elf_mime_types;
|
||||
|
@ -377,8 +374,8 @@ public:
|
|||
elf_value_defs;
|
||||
std::vector<std::shared_ptr<value_def>> elf_value_def_order;
|
||||
std::vector<std::shared_ptr<value_def>> elf_numeric_value_defs;
|
||||
int elf_column_count;
|
||||
double elf_timestamp_divisor;
|
||||
int elf_column_count{0};
|
||||
double elf_timestamp_divisor{1.0};
|
||||
intern_string_t elf_level_field;
|
||||
pcrepp elf_level_pointer;
|
||||
intern_string_t elf_body_field;
|
||||
|
@ -386,19 +383,24 @@ public:
|
|||
intern_string_t elf_opid_field;
|
||||
std::map<log_level_t, level_pattern> elf_level_patterns;
|
||||
std::vector<std::pair<int64_t, log_level_t>> elf_level_pairs;
|
||||
bool elf_container;
|
||||
bool elf_has_module_format;
|
||||
bool elf_builtin_format;
|
||||
std::vector<std::pair<intern_string_t, std::string>> elf_search_tables;
|
||||
bool elf_container{false};
|
||||
bool elf_has_module_format{false};
|
||||
bool elf_builtin_format{false};
|
||||
|
||||
struct search_table_def {
|
||||
std::shared_ptr<pcrepp> std_pattern;
|
||||
};
|
||||
|
||||
std::map<intern_string_t, search_table_def> elf_search_tables;
|
||||
std::map<const intern_string_t, highlighter_def> elf_highlighter_patterns;
|
||||
|
||||
enum elf_type_t {
|
||||
enum class elf_type_t {
|
||||
ELF_TYPE_TEXT,
|
||||
ELF_TYPE_JSON,
|
||||
ELF_TYPE_CSV,
|
||||
};
|
||||
|
||||
elf_type_t elf_type;
|
||||
elf_type_t elf_type{elf_type_t::ELF_TYPE_TEXT};
|
||||
|
||||
void json_append_to_cache(const char* value, ssize_t len)
|
||||
{
|
||||
|
@ -455,12 +457,14 @@ public:
|
|||
return lvm;
|
||||
}
|
||||
|
||||
bool jlf_hide_extra;
|
||||
std::vector<lnav::console::snippet> get_snippets() const;
|
||||
|
||||
bool jlf_hide_extra{false};
|
||||
std::vector<json_format_element> jlf_line_format;
|
||||
int jlf_line_format_init_count{0};
|
||||
std::vector<logline_value> jlf_line_values;
|
||||
|
||||
off_t jlf_cached_offset;
|
||||
off_t jlf_cached_offset{-1};
|
||||
bool jlf_cached_full{false};
|
||||
std::vector<off_t> jlf_line_offsets;
|
||||
shared_buffer jlf_share_manager;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "attr_line.hh"
|
||||
#include "base/string_attr_type.hh"
|
||||
#include "byte_array.hh"
|
||||
#include "log_level.hh"
|
||||
#include "ptimec.hh"
|
||||
|
|
|
@ -61,16 +61,17 @@ static void extract_metadata(const char* contents,
|
|||
size_t len,
|
||||
struct script_metadata& meta_out);
|
||||
|
||||
typedef std::map<intern_string_t, std::shared_ptr<external_log_format>>
|
||||
log_formats_map_t;
|
||||
using log_formats_map_t
|
||||
= std::map<intern_string_t, std::shared_ptr<external_log_format>>;
|
||||
|
||||
static auto intern_lifetime = intern_string::get_table_lifetime();
|
||||
static log_formats_map_t LOG_FORMATS;
|
||||
|
||||
struct userdata {
|
||||
yajlpp_parse_context* ud_parse_context{nullptr};
|
||||
ghc::filesystem::path ud_format_path;
|
||||
std::vector<intern_string_t>* ud_format_names{nullptr};
|
||||
std::vector<std::string>* ud_errors{nullptr};
|
||||
std::vector<lnav::console::user_message>* ud_errors{nullptr};
|
||||
};
|
||||
|
||||
static external_log_format*
|
||||
|
@ -86,12 +87,19 @@ ensure_format(const yajlpp_provider_context& ypc, userdata* ud)
|
|||
retval = LOG_FORMATS[name].get();
|
||||
log_debug("Loading format -- %s", name.get());
|
||||
}
|
||||
retval->elf_source_path.insert(ud->ud_format_path.filename().string());
|
||||
retval->elf_source_path.insert(ud->ud_format_path.parent_path().string());
|
||||
|
||||
if (find(formats->begin(), formats->end(), name) == formats->end()) {
|
||||
formats->push_back(name);
|
||||
}
|
||||
|
||||
auto srcs_iter
|
||||
= retval->elf_format_sources.find(ud->ud_format_path.string());
|
||||
if (srcs_iter == retval->elf_format_sources.end()) {
|
||||
retval->elf_format_sources[ud->ud_format_path.string()]
|
||||
= ud->ud_parse_context->get_line_number();
|
||||
}
|
||||
|
||||
if (ud->ud_format_path.empty()) {
|
||||
retval->elf_builtin_format = true;
|
||||
}
|
||||
|
@ -110,8 +118,9 @@ pattern_provider(const yajlpp_provider_context& ypc, external_log_format* elf)
|
|||
}
|
||||
|
||||
if (pat->p_config_path.empty()) {
|
||||
pat->p_config_path
|
||||
= elf->get_name().to_string() + "/regex/" + regex_name;
|
||||
pat->p_name = regex_name;
|
||||
pat->p_config_path = fmt::format(
|
||||
FMT_STRING("/{}/regex/{}"), elf->get_name(), regex_name);
|
||||
}
|
||||
|
||||
return pat.get();
|
||||
|
@ -172,16 +181,13 @@ read_format_bool(yajlpp_parse_context* ypc, int val)
|
|||
auto elf = (external_log_format*) ypc->ypc_obj_stack.top();
|
||||
auto field_name = ypc->get_path_fragment(1);
|
||||
|
||||
if (field_name == "convert-to-local-time")
|
||||
if (field_name == "convert-to-local-time") {
|
||||
elf->lf_date_time.dts_local_time = val;
|
||||
else if (field_name == "json") {
|
||||
} else if (field_name == "json") {
|
||||
if (val) {
|
||||
elf->elf_type = external_log_format::ELF_TYPE_JSON;
|
||||
elf->elf_type = external_log_format::elf_type_t::ELF_TYPE_JSON;
|
||||
}
|
||||
} else if (field_name == "hide-extra")
|
||||
elf->jlf_hide_extra = val;
|
||||
else if (field_name == "multiline")
|
||||
elf->lf_multiline = val;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -194,11 +200,16 @@ read_format_double(yajlpp_parse_context* ypc, double val)
|
|||
|
||||
if (field_name == "timestamp-divisor") {
|
||||
if (val <= 0) {
|
||||
fprintf(stderr,
|
||||
"error:%s: timestamp-divisor cannot be less "
|
||||
"than or equal to zero\n",
|
||||
ypc->get_path_fragment(0).c_str());
|
||||
return 0;
|
||||
ypc->report_error(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t()
|
||||
.append_quoted(fmt::to_string(val))
|
||||
.append(" is not a valid value for ")
|
||||
.append_quoted(lnav::roles::symbol(
|
||||
ypc->get_full_path().to_string())))
|
||||
.with_reason("value cannot be less than or equal to zero")
|
||||
.with_snippet(ypc->get_snippet())
|
||||
.with_help(ypc->ypc_current_handler->get_help_text(ypc)));
|
||||
}
|
||||
elf->elf_timestamp_divisor = val;
|
||||
}
|
||||
|
@ -214,11 +225,16 @@ read_format_int(yajlpp_parse_context* ypc, long long val)
|
|||
|
||||
if (field_name == "timestamp-divisor") {
|
||||
if (val <= 0) {
|
||||
fprintf(stderr,
|
||||
"error:%s: timestamp-divisor cannot be less "
|
||||
"than or equal to zero\n",
|
||||
ypc->get_path_fragment(0).c_str());
|
||||
return 0;
|
||||
ypc->report_error(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t()
|
||||
.append_quoted(fmt::to_string(val))
|
||||
.append(" is not a valid value for ")
|
||||
.append_quoted(lnav::roles::symbol(
|
||||
ypc->get_full_path().to_string())))
|
||||
.with_reason("value cannot be less than or equal to zero")
|
||||
.with_snippet(ypc->get_snippet())
|
||||
.with_help(ypc->ypc_current_handler->get_help_text(ypc)));
|
||||
}
|
||||
elf->elf_timestamp_divisor = val;
|
||||
}
|
||||
|
@ -238,37 +254,33 @@ read_format_field(yajlpp_parse_context* ypc,
|
|||
auto field_name = ypc->get_path_fragment(1);
|
||||
|
||||
if (field_name == "file-pattern") {
|
||||
elf->elf_file_pattern = value;
|
||||
} else if (field_name == "level-field") {
|
||||
elf->elf_level_field = intern_string::lookup(value);
|
||||
try {
|
||||
elf->elf_file_pattern = value;
|
||||
elf->elf_filename_pcre
|
||||
= std::make_shared<pcrepp>(elf->elf_file_pattern);
|
||||
} catch (const pcrepp::error& e) {
|
||||
pcrepp::compile_error ce;
|
||||
|
||||
ce.ce_msg = e.what();
|
||||
ce.ce_offset = e.e_offset;
|
||||
ypc->ypc_current_handler->report_regex_value_error(ypc, value, ce);
|
||||
}
|
||||
} else if (field_name == "level-pointer") {
|
||||
auto pcre_res = pcrepp::from_str(value);
|
||||
|
||||
if (pcre_res.isErr()) {
|
||||
ypc->ypc_error_reporter(
|
||||
*ypc,
|
||||
lnav_log_level_t::ERROR,
|
||||
fmt::format(
|
||||
FMT_STRING("error:{}:{}:invalid regular expression for "
|
||||
"level-pointer -- {}"),
|
||||
ypc->ypc_source,
|
||||
ypc->get_line_number(),
|
||||
pcre_res.unwrapErr().ce_msg)
|
||||
.c_str());
|
||||
auto pcre_error = pcre_res.unwrapErr();
|
||||
|
||||
ypc->ypc_current_handler->report_regex_value_error(
|
||||
ypc, value, pcre_error);
|
||||
} else {
|
||||
elf->elf_level_pointer = pcre_res.unwrap();
|
||||
}
|
||||
} else if (field_name == "timestamp-field") {
|
||||
elf->lf_timestamp_field = intern_string::lookup(value);
|
||||
} else if (field_name == "body-field") {
|
||||
elf->elf_body_field = intern_string::lookup(value);
|
||||
} else if (field_name == "timestamp-format") {
|
||||
elf->lf_timestamp_format.push_back(intern_string::lookup(value)->get());
|
||||
} else if (field_name == "module-field") {
|
||||
elf->elf_module_id_field = intern_string::lookup(value);
|
||||
elf->elf_container = true;
|
||||
} else if (field_name == "opid-field") {
|
||||
elf->elf_opid_field = intern_string::lookup(value);
|
||||
} else if (field_name == "mime-types") {
|
||||
auto value_opt = ypc->ypc_current_handler->to_enum_value(value);
|
||||
if (value_opt) {
|
||||
|
@ -288,6 +300,17 @@ read_levels(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
|
|||
log_level_t level = string2level(level_name_or_number.c_str());
|
||||
elf->elf_level_patterns[level].lp_regex = regex;
|
||||
|
||||
try {
|
||||
elf->elf_level_patterns[level].lp_pcre
|
||||
= std::make_shared<pcrepp>(regex);
|
||||
} catch (const pcrepp::error& e) {
|
||||
pcrepp::compile_error ce;
|
||||
|
||||
ce.ce_msg = e.what();
|
||||
ce.ce_offset = e.e_offset;
|
||||
ypc->ypc_current_handler->report_regex_value_error(ypc, regex, ce);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -312,8 +335,9 @@ read_action_def(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
|
|||
auto val = std::string((const char*) str, len);
|
||||
|
||||
elf->lf_action_defs[action_name].ad_name = action_name;
|
||||
if (field_name == "label")
|
||||
if (field_name == "label") {
|
||||
elf->lf_action_defs[action_name].ad_label = val;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -376,39 +400,27 @@ read_json_constant(yajlpp_parse_context* ypc,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
create_search_table(yajlpp_parse_context* ypc,
|
||||
const unsigned char* str,
|
||||
size_t len)
|
||||
{
|
||||
auto elf = (external_log_format*) ypc->ypc_obj_stack.top();
|
||||
const intern_string_t table_name = ypc->get_path_fragment_i(2);
|
||||
auto regex = std::string((const char*) str, len);
|
||||
|
||||
elf->elf_search_tables.emplace_back(table_name, regex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct json_path_container pattern_handlers = {
|
||||
yajlpp::property_handler("pattern")
|
||||
.with_synopsis("<message-regex>")
|
||||
.with_description(
|
||||
"The regular expression to match a log message and capture fields.")
|
||||
.with_min_length(1)
|
||||
.FOR_FIELD(external_log_format::pattern, p_string),
|
||||
.for_field(&external_log_format::pattern::p_pcre),
|
||||
yajlpp::property_handler("module-format")
|
||||
.with_synopsis("<bool>")
|
||||
.with_description(
|
||||
"If true, this pattern will only be used to parse message bodies "
|
||||
"of container formats, like syslog")
|
||||
.for_field(&external_log_format::pattern::p_module_format)};
|
||||
.for_field(&external_log_format::pattern::p_module_format),
|
||||
};
|
||||
|
||||
static const json_path_handler_base::enum_value_t ALIGN_ENUM[]
|
||||
= {{"left", external_log_format::json_format_element::align_t::LEFT},
|
||||
{"right", external_log_format::json_format_element::align_t::RIGHT},
|
||||
static const json_path_handler_base::enum_value_t ALIGN_ENUM[] = {
|
||||
{"left", external_log_format::json_format_element::align_t::LEFT},
|
||||
{"right", external_log_format::json_format_element::align_t::RIGHT},
|
||||
|
||||
json_path_handler_base::ENUM_TERMINATOR};
|
||||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
static const json_path_handler_base::enum_value_t OVERFLOW_ENUM[] = {
|
||||
{"abbrev", external_log_format::json_format_element::overflow_t::ABBREV},
|
||||
|
@ -416,18 +428,20 @@ static const json_path_handler_base::enum_value_t OVERFLOW_ENUM[] = {
|
|||
external_log_format::json_format_element::overflow_t::TRUNCATE},
|
||||
{"dot-dot", external_log_format::json_format_element::overflow_t::DOTDOT},
|
||||
|
||||
json_path_handler_base::ENUM_TERMINATOR};
|
||||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
static const json_path_handler_base::enum_value_t TRANSFORM_ENUM[]
|
||||
= {{"none", external_log_format::json_format_element::transform_t::NONE},
|
||||
{"uppercase",
|
||||
external_log_format::json_format_element::transform_t::UPPERCASE},
|
||||
{"lowercase",
|
||||
external_log_format::json_format_element::transform_t::LOWERCASE},
|
||||
{"capitalize",
|
||||
external_log_format::json_format_element::transform_t::CAPITALIZE},
|
||||
static const json_path_handler_base::enum_value_t TRANSFORM_ENUM[] = {
|
||||
{"none", external_log_format::json_format_element::transform_t::NONE},
|
||||
{"uppercase",
|
||||
external_log_format::json_format_element::transform_t::UPPERCASE},
|
||||
{"lowercase",
|
||||
external_log_format::json_format_element::transform_t::LOWERCASE},
|
||||
{"capitalize",
|
||||
external_log_format::json_format_element::transform_t::CAPITALIZE},
|
||||
|
||||
json_path_handler_base::ENUM_TERMINATOR};
|
||||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
static struct json_path_container line_format_handlers = {
|
||||
yajlpp::property_handler("field")
|
||||
|
@ -435,78 +449,83 @@ static struct json_path_container line_format_handlers = {
|
|||
.with_description(
|
||||
"The name of the field to substitute at this position")
|
||||
.with_min_length(1)
|
||||
.FOR_FIELD(external_log_format::json_format_element, jfe_value),
|
||||
.for_field(&external_log_format::json_format_element::jfe_value),
|
||||
|
||||
yajlpp::property_handler("default-value")
|
||||
.with_synopsis("<string>")
|
||||
.with_description(
|
||||
"The default value for this position if the field is null")
|
||||
.FOR_FIELD(external_log_format::json_format_element, jfe_default_value),
|
||||
.for_field(
|
||||
&external_log_format::json_format_element::jfe_default_value),
|
||||
|
||||
yajlpp::property_handler("timestamp-format")
|
||||
.with_synopsis("<string>")
|
||||
.with_min_length(1)
|
||||
.with_description("The strftime(3) format for this field")
|
||||
.FOR_FIELD(external_log_format::json_format_element, jfe_ts_format),
|
||||
.for_field(&external_log_format::json_format_element::jfe_ts_format),
|
||||
|
||||
yajlpp::property_handler("min-width")
|
||||
.with_min_value(0)
|
||||
.with_synopsis("<size>")
|
||||
.with_description("The minimum width of the field")
|
||||
.FOR_FIELD(external_log_format::json_format_element, jfe_min_width),
|
||||
.for_field(&external_log_format::json_format_element::jfe_min_width),
|
||||
|
||||
yajlpp::property_handler("max-width")
|
||||
.with_min_value(0)
|
||||
.with_synopsis("<size>")
|
||||
.with_description("The maximum width of the field")
|
||||
.FOR_FIELD(external_log_format::json_format_element, jfe_max_width),
|
||||
.for_field(&external_log_format::json_format_element::jfe_max_width),
|
||||
|
||||
yajlpp::property_handler("align")
|
||||
.with_synopsis("left|right")
|
||||
.with_description(
|
||||
"Align the text in the column to the left or right side")
|
||||
.with_enum_values(ALIGN_ENUM)
|
||||
.FOR_FIELD(external_log_format::json_format_element, jfe_align),
|
||||
.for_field(&external_log_format::json_format_element::jfe_align),
|
||||
|
||||
yajlpp::property_handler("overflow")
|
||||
.with_synopsis("abbrev|truncate|dot-dot")
|
||||
.with_description("Overflow style")
|
||||
.with_enum_values(OVERFLOW_ENUM)
|
||||
.FOR_FIELD(external_log_format::json_format_element, jfe_overflow),
|
||||
.for_field(&external_log_format::json_format_element::jfe_overflow),
|
||||
|
||||
yajlpp::property_handler("text-transform")
|
||||
.with_synopsis("none|uppercase|lowercase|capitalize")
|
||||
.with_description("Text transformation")
|
||||
.with_enum_values(TRANSFORM_ENUM)
|
||||
.FOR_FIELD(external_log_format::json_format_element,
|
||||
jfe_text_transform)};
|
||||
.for_field(
|
||||
&external_log_format::json_format_element::jfe_text_transform),
|
||||
};
|
||||
|
||||
static const json_path_handler_base::enum_value_t KIND_ENUM[]
|
||||
= {{"string", value_kind_t::VALUE_TEXT},
|
||||
{"integer", value_kind_t::VALUE_INTEGER},
|
||||
{"float", value_kind_t::VALUE_FLOAT},
|
||||
{"boolean", value_kind_t::VALUE_BOOLEAN},
|
||||
{"json", value_kind_t::VALUE_JSON},
|
||||
{"struct", value_kind_t::VALUE_STRUCT},
|
||||
{"quoted", value_kind_t::VALUE_QUOTED},
|
||||
{"xml", value_kind_t::VALUE_XML},
|
||||
static const json_path_handler_base::enum_value_t KIND_ENUM[] = {
|
||||
{"string", value_kind_t::VALUE_TEXT},
|
||||
{"integer", value_kind_t::VALUE_INTEGER},
|
||||
{"float", value_kind_t::VALUE_FLOAT},
|
||||
{"boolean", value_kind_t::VALUE_BOOLEAN},
|
||||
{"json", value_kind_t::VALUE_JSON},
|
||||
{"struct", value_kind_t::VALUE_STRUCT},
|
||||
{"quoted", value_kind_t::VALUE_QUOTED},
|
||||
{"xml", value_kind_t::VALUE_XML},
|
||||
|
||||
json_path_handler_base::ENUM_TERMINATOR};
|
||||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
static const json_path_handler_base::enum_value_t SCALE_OP_ENUM[]
|
||||
= {{"identity", scale_op_t::SO_IDENTITY},
|
||||
{"multiply", scale_op_t::SO_MULTIPLY},
|
||||
{"divide", scale_op_t::SO_DIVIDE},
|
||||
static const json_path_handler_base::enum_value_t SCALE_OP_ENUM[] = {
|
||||
{"identity", scale_op_t::SO_IDENTITY},
|
||||
{"multiply", scale_op_t::SO_MULTIPLY},
|
||||
{"divide", scale_op_t::SO_DIVIDE},
|
||||
|
||||
json_path_handler_base::ENUM_TERMINATOR};
|
||||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
static struct json_path_container scaling_factor_handlers
|
||||
= {yajlpp::pattern_property_handler("op")
|
||||
.with_enum_values(SCALE_OP_ENUM)
|
||||
.FOR_FIELD(scaling_factor, sf_op),
|
||||
static struct json_path_container scaling_factor_handlers = {
|
||||
yajlpp::pattern_property_handler("op")
|
||||
.with_enum_values(SCALE_OP_ENUM)
|
||||
.for_field(&scaling_factor::sf_op),
|
||||
|
||||
yajlpp::pattern_property_handler("value").FOR_FIELD(scaling_factor,
|
||||
sf_value)};
|
||||
yajlpp::pattern_property_handler("value").FOR_FIELD(scaling_factor,
|
||||
sf_value),
|
||||
};
|
||||
|
||||
static struct json_path_container scale_handlers = {
|
||||
yajlpp::pattern_property_handler("(?<scale>[^/]+)")
|
||||
|
@ -519,7 +538,7 @@ static struct json_path_container unit_handlers = {
|
|||
.with_synopsis("<field-name>")
|
||||
.with_description(
|
||||
"The name of the field that contains the units for this field")
|
||||
.FOR_FIELD(external_log_format::value_def, vd_unit_field),
|
||||
.for_field(&external_log_format::value_def::vd_unit_field),
|
||||
|
||||
yajlpp::property_handler("scaling-factor")
|
||||
.with_description("Transforms the numeric value by the given factor")
|
||||
|
@ -528,7 +547,7 @@ static struct json_path_container unit_handlers = {
|
|||
|
||||
static struct json_path_container value_def_handlers = {
|
||||
yajlpp::property_handler("kind")
|
||||
.with_synopsis("string|integer|float|boolean|json|quoted")
|
||||
.with_synopsis("<data-type>")
|
||||
.with_description("The type of data in the field")
|
||||
.with_enum_values(KIND_ENUM)
|
||||
.for_field(&external_log_format::value_def::vd_meta,
|
||||
|
@ -537,7 +556,7 @@ static struct json_path_container value_def_handlers = {
|
|||
yajlpp::property_handler("collate")
|
||||
.with_synopsis("<function>")
|
||||
.with_description("The collating function to use for this column")
|
||||
.FOR_FIELD(external_log_format::value_def, vd_collate),
|
||||
.for_field(&external_log_format::value_def::vd_collate),
|
||||
|
||||
yajlpp::property_handler("unit")
|
||||
.with_description("Unit definitions for this field")
|
||||
|
@ -572,30 +591,31 @@ static struct json_path_container value_def_handlers = {
|
|||
.with_synopsis("<command>")
|
||||
.with_description(
|
||||
"A command that will rewrite this field when pretty-printing")
|
||||
.FOR_FIELD(external_log_format::value_def, vd_rewriter),
|
||||
.for_field(&external_log_format::value_def::vd_rewriter),
|
||||
|
||||
yajlpp::property_handler("description")
|
||||
.with_synopsis("<string>")
|
||||
.with_description("A description of the field")
|
||||
.FOR_FIELD(external_log_format::value_def, vd_description)};
|
||||
.for_field(&external_log_format::value_def::vd_description),
|
||||
};
|
||||
|
||||
static struct json_path_container highlighter_def_handlers = {
|
||||
yajlpp::property_handler("pattern")
|
||||
.with_synopsis("<regex>")
|
||||
.with_description(
|
||||
"A regular expression to highlight in logs of this format.")
|
||||
.FOR_FIELD(external_log_format::highlighter_def, hd_pattern),
|
||||
.for_field(&external_log_format::highlighter_def::hd_pattern),
|
||||
|
||||
yajlpp::property_handler("color")
|
||||
.with_synopsis("#<hex>|<name>")
|
||||
.with_description("The color to use when highlighting this pattern.")
|
||||
.FOR_FIELD(external_log_format::highlighter_def, hd_color),
|
||||
.for_field(&external_log_format::highlighter_def::hd_color),
|
||||
|
||||
yajlpp::property_handler("background-color")
|
||||
.with_synopsis("#<hex>|<name>")
|
||||
.with_description(
|
||||
"The background color to use when highlighting this pattern.")
|
||||
.FOR_FIELD(external_log_format::highlighter_def, hd_background_color),
|
||||
.for_field(&external_log_format::highlighter_def::hd_background_color),
|
||||
|
||||
yajlpp::property_handler("underline")
|
||||
.with_synopsis("<enabled>")
|
||||
|
@ -605,43 +625,47 @@ static struct json_path_container highlighter_def_handlers = {
|
|||
yajlpp::property_handler("blink")
|
||||
.with_synopsis("<enabled>")
|
||||
.with_description("Highlight this pattern by blinking.")
|
||||
.for_field(&external_log_format::highlighter_def::hd_blink)};
|
||||
.for_field(&external_log_format::highlighter_def::hd_blink),
|
||||
};
|
||||
|
||||
static const json_path_handler_base::enum_value_t LEVEL_ENUM[]
|
||||
= {{level_names[LEVEL_TRACE], LEVEL_TRACE},
|
||||
{level_names[LEVEL_DEBUG5], LEVEL_DEBUG5},
|
||||
{level_names[LEVEL_DEBUG4], LEVEL_DEBUG4},
|
||||
{level_names[LEVEL_DEBUG3], LEVEL_DEBUG3},
|
||||
{level_names[LEVEL_DEBUG2], LEVEL_DEBUG2},
|
||||
{level_names[LEVEL_DEBUG], LEVEL_DEBUG},
|
||||
{level_names[LEVEL_INFO], LEVEL_INFO},
|
||||
{level_names[LEVEL_STATS], LEVEL_STATS},
|
||||
{level_names[LEVEL_NOTICE], LEVEL_NOTICE},
|
||||
{level_names[LEVEL_WARNING], LEVEL_WARNING},
|
||||
{level_names[LEVEL_ERROR], LEVEL_ERROR},
|
||||
{level_names[LEVEL_CRITICAL], LEVEL_CRITICAL},
|
||||
{level_names[LEVEL_FATAL], LEVEL_FATAL},
|
||||
static const json_path_handler_base::enum_value_t LEVEL_ENUM[] = {
|
||||
{level_names[LEVEL_TRACE], LEVEL_TRACE},
|
||||
{level_names[LEVEL_DEBUG5], LEVEL_DEBUG5},
|
||||
{level_names[LEVEL_DEBUG4], LEVEL_DEBUG4},
|
||||
{level_names[LEVEL_DEBUG3], LEVEL_DEBUG3},
|
||||
{level_names[LEVEL_DEBUG2], LEVEL_DEBUG2},
|
||||
{level_names[LEVEL_DEBUG], LEVEL_DEBUG},
|
||||
{level_names[LEVEL_INFO], LEVEL_INFO},
|
||||
{level_names[LEVEL_STATS], LEVEL_STATS},
|
||||
{level_names[LEVEL_NOTICE], LEVEL_NOTICE},
|
||||
{level_names[LEVEL_WARNING], LEVEL_WARNING},
|
||||
{level_names[LEVEL_ERROR], LEVEL_ERROR},
|
||||
{level_names[LEVEL_CRITICAL], LEVEL_CRITICAL},
|
||||
{level_names[LEVEL_FATAL], LEVEL_FATAL},
|
||||
|
||||
json_path_handler_base::ENUM_TERMINATOR};
|
||||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
static struct json_path_container sample_handlers
|
||||
= {yajlpp::property_handler("line")
|
||||
.with_synopsis("<log-line>")
|
||||
.with_description(
|
||||
"A sample log line that should match a pattern in this format.")
|
||||
.FOR_FIELD(external_log_format::sample, s_line),
|
||||
static struct json_path_container sample_handlers = {
|
||||
yajlpp::property_handler("line")
|
||||
.with_synopsis("<log-line>")
|
||||
.with_description(
|
||||
"A sample log line that should match a pattern in this format.")
|
||||
.for_field(&external_log_format::sample::s_line),
|
||||
|
||||
yajlpp::property_handler("level")
|
||||
.with_enum_values(LEVEL_ENUM)
|
||||
.with_description("The expected level for this sample log line.")
|
||||
.FOR_FIELD(external_log_format::sample, s_level)};
|
||||
yajlpp::property_handler("level")
|
||||
.with_enum_values(LEVEL_ENUM)
|
||||
.with_description("The expected level for this sample log line.")
|
||||
.for_field(&external_log_format::sample::s_level),
|
||||
};
|
||||
|
||||
static const json_path_handler_base::enum_value_t TYPE_ENUM[]
|
||||
= {{"text", external_log_format::elf_type_t::ELF_TYPE_TEXT},
|
||||
{"json", external_log_format::elf_type_t::ELF_TYPE_JSON},
|
||||
{"csv", external_log_format::elf_type_t::ELF_TYPE_CSV},
|
||||
static const json_path_handler_base::enum_value_t TYPE_ENUM[] = {
|
||||
{"text", external_log_format::elf_type_t::ELF_TYPE_TEXT},
|
||||
{"json", external_log_format::elf_type_t::ELF_TYPE_JSON},
|
||||
{"csv", external_log_format::elf_type_t::ELF_TYPE_CSV},
|
||||
|
||||
json_path_handler_base::ENUM_TERMINATOR};
|
||||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
static struct json_path_container regex_handlers = {
|
||||
yajlpp::pattern_property_handler(R"((?<pattern_name>[^/]+))")
|
||||
|
@ -659,14 +683,16 @@ static struct json_path_container level_handlers = {
|
|||
.with_description("The regular expression used to match the log text "
|
||||
"for this level. "
|
||||
"For JSON logs with numeric levels, this should be "
|
||||
"the number for the corresponding level.")};
|
||||
"the number for the corresponding level."),
|
||||
};
|
||||
|
||||
static struct json_path_container value_handlers
|
||||
= {yajlpp::pattern_property_handler("(?<value_name>[^/]+)")
|
||||
.with_description(
|
||||
"The set of values captured by the log message patterns")
|
||||
.with_obj_provider(value_def_provider)
|
||||
.with_children(value_def_handlers)};
|
||||
static struct json_path_container value_handlers = {
|
||||
yajlpp::pattern_property_handler("(?<value_name>[^/]+)")
|
||||
.with_description(
|
||||
"The set of values captured by the log message patterns")
|
||||
.with_obj_provider(value_def_provider)
|
||||
.with_children(value_def_handlers),
|
||||
};
|
||||
|
||||
static struct json_path_container highlight_handlers = {
|
||||
yajlpp::pattern_property_handler(R"((?<highlight_name>[^/]+))")
|
||||
|
@ -674,38 +700,54 @@ static struct json_path_container highlight_handlers = {
|
|||
.with_obj_provider<external_log_format::highlighter_def,
|
||||
external_log_format>(
|
||||
[](const yajlpp_provider_context& ypc, external_log_format* root) {
|
||||
return &(root->elf_highlighter_patterns[ypc.get_substr_i(0)]);
|
||||
auto* retval
|
||||
= &(root->elf_highlighter_patterns[ypc.get_substr_i(0)]);
|
||||
|
||||
return retval;
|
||||
})
|
||||
.with_children(highlighter_def_handlers)};
|
||||
|
||||
static struct json_path_container action_def_handlers
|
||||
= {json_path_handler("label", read_action_def),
|
||||
json_path_handler("capture-output", read_action_bool),
|
||||
json_path_handler("cmd#", read_action_cmd)};
|
||||
|
||||
static struct json_path_container action_handlers
|
||||
= {json_path_handler(pcrepp("(?<action_name>\\w+)"), read_action_def)
|
||||
.with_children(action_def_handlers)};
|
||||
|
||||
static struct json_path_container search_table_def_handlers = {
|
||||
json_path_handler("pattern", create_search_table)
|
||||
.with_synopsis("<regex>")
|
||||
.with_description("The regular expression for this search table."),
|
||||
.with_children(highlighter_def_handlers),
|
||||
};
|
||||
|
||||
static struct json_path_container search_table_handlers
|
||||
= {yajlpp::pattern_property_handler("\\w+")
|
||||
.with_description(
|
||||
"The set of search tables to be automatically defined")
|
||||
.with_children(search_table_def_handlers)};
|
||||
static struct json_path_container action_def_handlers = {
|
||||
json_path_handler("label", read_action_def),
|
||||
json_path_handler("capture-output", read_action_bool),
|
||||
json_path_handler("cmd#", read_action_cmd),
|
||||
};
|
||||
|
||||
static const json_path_handler_base::enum_value_t MIME_TYPE_ENUM[]
|
||||
= {{
|
||||
"application/vnd.tcpdump.pcap",
|
||||
file_format_t::PCAP,
|
||||
},
|
||||
static struct json_path_container action_handlers = {
|
||||
json_path_handler(pcrepp("(?<action_name>\\w+)"), read_action_def)
|
||||
.with_children(action_def_handlers),
|
||||
};
|
||||
|
||||
json_path_handler_base::ENUM_TERMINATOR};
|
||||
static struct json_path_container search_table_def_handlers = {
|
||||
json_path_handler("pattern")
|
||||
.with_synopsis("<regex>")
|
||||
.with_description("The regular expression for this search table.")
|
||||
.for_field(&external_log_format::search_table_def::std_pattern),
|
||||
};
|
||||
|
||||
static struct json_path_container search_table_handlers = {
|
||||
yajlpp::pattern_property_handler("(?<table_name>\\w+)")
|
||||
.with_description(
|
||||
"The set of search tables to be automatically defined")
|
||||
.with_obj_provider<external_log_format::search_table_def,
|
||||
external_log_format>(
|
||||
[](const yajlpp_provider_context& ypc, external_log_format* root) {
|
||||
auto* retval = &(root->elf_search_tables[ypc.get_substr_i(0)]);
|
||||
|
||||
return retval;
|
||||
})
|
||||
.with_children(search_table_def_handlers),
|
||||
};
|
||||
|
||||
static const json_path_handler_base::enum_value_t MIME_TYPE_ENUM[] = {
|
||||
{
|
||||
"application/vnd.tcpdump.pcap",
|
||||
file_format_t::PCAP,
|
||||
},
|
||||
|
||||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
struct json_path_container format_handlers = {
|
||||
yajlpp::property_handler("regex")
|
||||
|
@ -721,10 +763,11 @@ struct json_path_container format_handlers = {
|
|||
"automatically be converted to local time"),
|
||||
json_path_handler("hide-extra", read_format_bool)
|
||||
.with_description(
|
||||
"Specifies whether extra values in JSON logs should be displayed"),
|
||||
"Specifies whether extra values in JSON logs should be displayed")
|
||||
.for_field(&external_log_format::jlf_hide_extra),
|
||||
json_path_handler("multiline", read_format_bool)
|
||||
.with_description(
|
||||
"Indicates that log messages can span multiple lines"),
|
||||
.with_description("Indicates that log messages can span multiple lines")
|
||||
.for_field(&log_format::lf_multiline),
|
||||
json_path_handler("timestamp-divisor", read_format_double)
|
||||
.add_cb(read_format_int)
|
||||
.with_synopsis("<number>")
|
||||
|
@ -738,16 +781,19 @@ struct json_path_container format_handlers = {
|
|||
.with_enum_values(MIME_TYPE_ENUM),
|
||||
json_path_handler("level-field", read_format_field)
|
||||
.with_description(
|
||||
"The name of the level field in the log message pattern"),
|
||||
"The name of the level field in the log message pattern")
|
||||
.for_field(&external_log_format::elf_level_field),
|
||||
json_path_handler("level-pointer", read_format_field)
|
||||
.with_description("A regular-expression that matches the JSON-pointer "
|
||||
"of the level property"),
|
||||
json_path_handler("timestamp-field", read_format_field)
|
||||
.with_description(
|
||||
"The name of the timestamp field in the log message pattern"),
|
||||
"The name of the timestamp field in the log message pattern")
|
||||
.for_field(&log_format::lf_timestamp_field),
|
||||
json_path_handler("body-field", read_format_field)
|
||||
.with_description(
|
||||
"The name of the body field in the log message pattern"),
|
||||
"The name of the body field in the log message pattern")
|
||||
.for_field(&external_log_format::elf_body_field),
|
||||
json_path_handler("url", pcrepp("url#?"))
|
||||
.add_cb(read_format_field)
|
||||
.with_description("A URL with more information about this log format"),
|
||||
|
@ -762,7 +808,8 @@ struct json_path_container format_handlers = {
|
|||
"The name of the module field in the log message pattern"),
|
||||
json_path_handler("opid-field", read_format_field)
|
||||
.with_description(
|
||||
"The name of the operation-id field in the log message pattern"),
|
||||
"The name of the operation-id field in the log message pattern")
|
||||
.for_field(&external_log_format::elf_opid_field),
|
||||
yajlpp::property_handler("ordered-by-time")
|
||||
.with_synopsis("<bool>")
|
||||
.with_description(
|
||||
|
@ -789,7 +836,7 @@ struct json_path_container format_handlers = {
|
|||
.with_obj_provider(line_format_provider)
|
||||
.add_cb(read_json_constant)
|
||||
.with_children(line_format_handlers),
|
||||
json_path_handler("search-table", create_search_table)
|
||||
json_path_handler("search-table")
|
||||
.with_description(
|
||||
"Search tables to automatically define for this log format")
|
||||
.with_children(search_table_handlers),
|
||||
|
@ -802,7 +849,8 @@ struct json_path_container format_handlers = {
|
|||
.with_synopsis("text|json|csv")
|
||||
.with_description("The type of file that contains the log messages")
|
||||
.with_enum_values(TYPE_ENUM)
|
||||
.FOR_FIELD(external_log_format, elf_type)};
|
||||
.for_field(&external_log_format::elf_type),
|
||||
};
|
||||
|
||||
static int
|
||||
read_id(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
|
||||
|
@ -814,12 +862,21 @@ read_id(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
|
|||
file_id)
|
||||
== SUPPORTED_FORMAT_SCHEMAS.end())
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s:%d: error: unsupported format $schema -- %s\n",
|
||||
ypc->ypc_source.c_str(),
|
||||
ypc->get_line_number(),
|
||||
file_id.c_str());
|
||||
return 0;
|
||||
const auto* handler = ypc->ypc_current_handler;
|
||||
attr_line_t notes{"expecting one of the following $schema values:"};
|
||||
|
||||
for (const auto& schema : SUPPORTED_FORMAT_SCHEMAS) {
|
||||
notes.append("\n").append(
|
||||
lnav::roles::symbol(fmt::format(FMT_STRING(" {}"), schema)));
|
||||
}
|
||||
ypc->report_error(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("'")
|
||||
.append(lnav::roles::symbol(file_id))
|
||||
.append("' is not a supported log format $schema version"))
|
||||
.with_snippet(ypc->get_snippet())
|
||||
.with_note(notes)
|
||||
.with_help(handler->get_help_text(ypc)));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -910,38 +967,35 @@ write_sample_file()
|
|||
|
||||
static void
|
||||
format_error_reporter(const yajlpp_parse_context& ypc,
|
||||
lnav_log_level_t level,
|
||||
const char* msg)
|
||||
const lnav::console::user_message& msg)
|
||||
{
|
||||
if (level >= lnav_log_level_t::ERROR) {
|
||||
struct userdata* ud = (userdata*) ypc.ypc_userdata;
|
||||
struct userdata* ud = (userdata*) ypc.ypc_userdata;
|
||||
|
||||
ud->ud_errors->push_back(msg);
|
||||
} else {
|
||||
fprintf(stderr, "warning:%s\n", msg);
|
||||
}
|
||||
ud->ud_errors->emplace_back(msg);
|
||||
}
|
||||
|
||||
std::vector<intern_string_t>
|
||||
load_format_file(const ghc::filesystem::path& filename,
|
||||
std::vector<std::string>& errors)
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
std::vector<intern_string_t> retval;
|
||||
struct userdata ud;
|
||||
auto_fd fd;
|
||||
|
||||
log_info("loading formats from file: %s", filename.c_str());
|
||||
yajlpp_parse_context ypc(filename, &root_format_handler);
|
||||
ud.ud_parse_context = &ypc;
|
||||
ud.ud_format_path = filename;
|
||||
ud.ud_format_names = &retval;
|
||||
ud.ud_errors = &errors;
|
||||
yajlpp_parse_context ypc(filename, &root_format_handler);
|
||||
ypc.ypc_userdata = &ud;
|
||||
ypc.with_obj(ud);
|
||||
if ((fd = lnav::filesystem::openp(filename, O_RDONLY)) == -1) {
|
||||
errors.emplace_back(fmt::format(
|
||||
FMT_STRING("error: unable to open format file '{}' -- {}"),
|
||||
filename.string(),
|
||||
strerror(errno)));
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("unable to open format file: ")
|
||||
.append(lnav::roles::file(filename.string())))
|
||||
.with_errno_reason());
|
||||
} else {
|
||||
auto_mem<yajl_handle_t> handle(yajl_free);
|
||||
char buffer[2048];
|
||||
|
@ -955,11 +1009,13 @@ load_format_file(const ghc::filesystem::path& filename,
|
|||
rc = read(fd, buffer, sizeof(buffer));
|
||||
if (rc == 0) {
|
||||
break;
|
||||
} else if (rc == -1) {
|
||||
errors.emplace_back(fmt::format(
|
||||
FMT_STRING("error:{}:unable to read file -- {}"),
|
||||
filename.string(),
|
||||
strerror(errno)));
|
||||
}
|
||||
if (rc == -1) {
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("unable to read format file: ")
|
||||
.append(lnav::roles::file(filename.string())))
|
||||
.with_errno_reason());
|
||||
break;
|
||||
}
|
||||
if (offset == 0 && (rc > 2) && (buffer[0] == '#')
|
||||
|
@ -983,7 +1039,7 @@ load_format_file(const ghc::filesystem::path& filename,
|
|||
|
||||
static void
|
||||
load_from_path(const ghc::filesystem::path& path,
|
||||
std::vector<std::string>& errors)
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
auto format_path = path / "formats/*/*.json";
|
||||
static_root_mem<glob_t, globfree> gl;
|
||||
|
@ -1015,11 +1071,9 @@ load_from_path(const ghc::filesystem::path& path,
|
|||
|
||||
void
|
||||
load_formats(const std::vector<ghc::filesystem::path>& extra_paths,
|
||||
std::vector<std::string>& errors)
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
auto default_source = lnav::paths::dotlnav() / "default";
|
||||
yajlpp_parse_context ypc_builtin(default_source.string(),
|
||||
&root_format_handler);
|
||||
std::vector<intern_string_t> retval;
|
||||
struct userdata ud;
|
||||
yajl_handle handle;
|
||||
|
@ -1028,7 +1082,9 @@ load_formats(const std::vector<ghc::filesystem::path>& extra_paths,
|
|||
|
||||
log_debug("Loading default formats");
|
||||
for (const auto& bsf : lnav_format_json) {
|
||||
yajlpp_parse_context ypc_builtin(bsf.get_name(), &root_format_handler);
|
||||
handle = yajl_alloc(&ypc_builtin.ypc_callbacks, nullptr, &ypc_builtin);
|
||||
ud.ud_parse_context = &ypc_builtin;
|
||||
ud.ud_format_names = &retval;
|
||||
ud.ud_errors = &errors;
|
||||
ypc_builtin.with_obj(ud)
|
||||
|
@ -1043,8 +1099,10 @@ load_formats(const std::vector<ghc::filesystem::path>& extra_paths,
|
|||
handle, 1, (const unsigned char*) sf.data(), sf.length());
|
||||
|
||||
errors.emplace_back(
|
||||
fmt::format(FMT_STRING("builtin: invalid json -- {}"),
|
||||
reinterpret_cast<char*>(msg)));
|
||||
lnav::console::user_message::error("invalid json")
|
||||
.with_snippet(lnav::console::snippet::from(
|
||||
ypc_builtin.ypc_source, attr_line_t((const char*) msg)))
|
||||
.with_errno_reason());
|
||||
yajl_free_error(handle, msg);
|
||||
}
|
||||
ypc_builtin.complete_parse();
|
||||
|
@ -1154,7 +1212,7 @@ load_formats(const std::vector<ghc::filesystem::path>& extra_paths,
|
|||
static void
|
||||
exec_sql_in_path(sqlite3* db,
|
||||
const ghc::filesystem::path& path,
|
||||
std::vector<std::string>& errors)
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
auto format_path = path / "formats/*/*.sql";
|
||||
static_root_mem<glob_t, globfree> gl;
|
||||
|
@ -1172,10 +1230,11 @@ exec_sql_in_path(sqlite3* db,
|
|||
sql_execute_script(
|
||||
db, filename.c_str(), content.c_str(), errors);
|
||||
} else {
|
||||
errors.emplace_back(fmt::format(
|
||||
FMT_STRING("error:unable to read file '{}' -- {}"),
|
||||
filename.string(),
|
||||
read_res.unwrapErr()));
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("unable to read format file: ")
|
||||
.append(lnav::roles::file(filename.string())))
|
||||
.with_reason(read_res.unwrapErr()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1184,7 +1243,7 @@ exec_sql_in_path(sqlite3* db,
|
|||
void
|
||||
load_format_extra(sqlite3* db,
|
||||
const std::vector<ghc::filesystem::path>& extra_paths,
|
||||
std::vector<std::string>& errors)
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
for (const auto& extra_path : extra_paths) {
|
||||
exec_sql_in_path(db, extra_path, errors);
|
||||
|
@ -1275,7 +1334,7 @@ find_format_scripts(const std::vector<ghc::filesystem::path>& extra_paths,
|
|||
|
||||
void
|
||||
load_format_vtabs(log_vtab_manager* vtab_manager,
|
||||
std::vector<std::string>& errors)
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
auto& root_formats = LOG_FORMATS;
|
||||
|
||||
|
|
|
@ -38,22 +38,24 @@
|
|||
#include <sqlite3.h>
|
||||
|
||||
#include "base/intern_string.hh"
|
||||
#include "base/lnav.console.hh"
|
||||
#include "ghc/filesystem.hpp"
|
||||
|
||||
class log_vtab_manager;
|
||||
|
||||
std::vector<intern_string_t> load_format_file(
|
||||
const ghc::filesystem::path& filename, std::vector<std::string>& errors);
|
||||
const ghc::filesystem::path& filename,
|
||||
std::vector<lnav::console::user_message>& errors);
|
||||
|
||||
void load_formats(const std::vector<ghc::filesystem::path>& extra_paths,
|
||||
std::vector<std::string>& errors);
|
||||
std::vector<lnav::console::user_message>& errors);
|
||||
|
||||
void load_format_vtabs(log_vtab_manager* vtab_manager,
|
||||
std::vector<std::string>& errors);
|
||||
std::vector<lnav::console::user_message>& errors);
|
||||
|
||||
void load_format_extra(sqlite3* db,
|
||||
const std::vector<ghc::filesystem::path>& extra_paths,
|
||||
std::vector<std::string>& errors);
|
||||
std::vector<lnav::console::user_message>& errors);
|
||||
|
||||
struct script_metadata {
|
||||
ghc::filesystem::path sm_path;
|
||||
|
|
|
@ -39,8 +39,8 @@ public:
|
|||
int start,
|
||||
int end,
|
||||
chtype& ch,
|
||||
view_colors::role_t& role_out,
|
||||
view_colors::role_t& bar_role_out)
|
||||
role_t& role_out,
|
||||
role_t& bar_role_out)
|
||||
{
|
||||
textview_curses* tc = (textview_curses*) &lv;
|
||||
vis_bookmarks& bm = tc->get_bookmarks();
|
||||
|
@ -63,13 +63,13 @@ public:
|
|||
}
|
||||
next = bm[&logfile_sub_source::BM_ERRORS].next(vis_line_t(start));
|
||||
if (next != -1 && next <= end) {
|
||||
role_out = view_colors::VCR_ERROR;
|
||||
bar_role_out = view_colors::VCR_SCROLLBAR_ERROR;
|
||||
role_out = role_t::VCR_ERROR;
|
||||
bar_role_out = role_t::VCR_SCROLLBAR_ERROR;
|
||||
} else {
|
||||
next = bm[&logfile_sub_source::BM_WARNINGS].next(vis_line_t(start));
|
||||
if (next != -1 && next <= end) {
|
||||
role_out = view_colors::VCR_WARNING;
|
||||
bar_role_out = view_colors::VCR_SCROLLBAR_WARNING;
|
||||
role_out = role_t::VCR_WARNING;
|
||||
bar_role_out = role_t::VCR_SCROLLBAR_WARNING;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -32,17 +32,20 @@
|
|||
#include "base/lnav_log.hh"
|
||||
#include "base/string_util.hh"
|
||||
#include "config.h"
|
||||
#include "lnav_util.hh"
|
||||
#include "logfile_sub_source.hh"
|
||||
#include "sql_util.hh"
|
||||
#include "vtab_module.hh"
|
||||
#include "yajlpp/json_op.hh"
|
||||
#include "yajlpp/yajlpp_def.hh"
|
||||
|
||||
using namespace lnav::roles::literals;
|
||||
|
||||
static auto intern_lifetime = intern_string::get_table_lifetime();
|
||||
|
||||
static struct log_cursor log_cursor_latest;
|
||||
|
||||
struct _log_vtab_data log_vtab_data;
|
||||
thread_local _log_vtab_data log_vtab_data;
|
||||
|
||||
static const char* LOG_COLUMNS = R"( (
|
||||
log_line INTEGER PRIMARY KEY, -- The line number for the log message
|
||||
|
@ -947,12 +950,13 @@ vt_best_index(sqlite3_vtab* tab, sqlite3_index_info* p_info)
|
|||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static struct json_path_container tags_handler
|
||||
= {json_path_handler("#")
|
||||
.with_synopsis("<tag>")
|
||||
.with_description("A tag for the log line")
|
||||
.with_pattern(R"(^#[^\s]+$)")
|
||||
.FOR_FIELD(bookmark_metadata, bm_tags)};
|
||||
static struct json_path_container tags_handler = {
|
||||
json_path_handler("#")
|
||||
.with_synopsis("tag")
|
||||
.with_description("A tag for the log line")
|
||||
.with_pattern(R"(^#[^\s]+$)")
|
||||
.FOR_FIELD(bookmark_metadata, bm_tags),
|
||||
};
|
||||
|
||||
static int
|
||||
vt_update(sqlite3_vtab* tab,
|
||||
|
@ -972,17 +976,17 @@ vt_update(sqlite3_vtab* tab,
|
|||
|
||||
std::map<content_line_t, bookmark_metadata>& bm
|
||||
= vt->lss->get_user_bookmark_metadata();
|
||||
const unsigned char* part_name
|
||||
= sqlite3_value_text(argv[2 + VT_COL_PARTITION]);
|
||||
const unsigned char* log_comment
|
||||
const auto* part_name = sqlite3_value_text(argv[2 + VT_COL_PARTITION]);
|
||||
const auto* log_comment
|
||||
= sqlite3_value_text(argv[2 + VT_COL_LOG_COMMENT]);
|
||||
const unsigned char* log_tags
|
||||
= sqlite3_value_text(argv[2 + VT_COL_LOG_TAGS]);
|
||||
const auto* log_tags = sqlite3_value_text(argv[2 + VT_COL_LOG_TAGS]);
|
||||
bookmark_metadata tmp_bm;
|
||||
|
||||
if (log_tags) {
|
||||
std::vector<std::string> errors;
|
||||
yajlpp_parse_context ypc(log_vtab_data.lvd_source, &tags_handler);
|
||||
std::vector<lnav::console::user_message> errors;
|
||||
yajlpp_parse_context ypc(
|
||||
fmt::format(FMT_STRING("{}.log_tags"), vt->vi->get_name()),
|
||||
&tags_handler);
|
||||
auto_mem<yajl_handle_t> handle(yajl_free);
|
||||
|
||||
handle = yajl_alloc(&ypc.ypc_callbacks, nullptr, &ypc);
|
||||
|
@ -990,19 +994,31 @@ vt_update(sqlite3_vtab* tab,
|
|||
ypc.ypc_line_number = log_vtab_data.lvd_line_number;
|
||||
ypc.with_handle(handle)
|
||||
.with_error_reporter([](const yajlpp_parse_context& ypc,
|
||||
lnav_log_level_t level,
|
||||
const char* msg) {
|
||||
auto& errors
|
||||
= *((std::vector<std::string>*) ypc.ypc_userdata);
|
||||
auto msg) {
|
||||
auto& errors = *((std::vector<lnav::console::user_message>*)
|
||||
ypc.ypc_userdata);
|
||||
errors.emplace_back(msg);
|
||||
})
|
||||
.with_obj(tmp_bm);
|
||||
ypc.parse(log_tags, strlen((const char*) log_tags));
|
||||
ypc.complete_parse();
|
||||
ypc.parse_doc(string_fragment{log_tags});
|
||||
if (!errors.empty()) {
|
||||
auto all_errors
|
||||
= fmt::format(FMT_STRING("{}"), fmt::join(errors, "\n"));
|
||||
tab->zErrMsg = sqlite3_mprintf("%s", all_errors.c_str());
|
||||
auto top_error
|
||||
= lnav::console::user_message::error(
|
||||
attr_line_t("invalid value for ")
|
||||
.append_quoted("log_tags"_symbol)
|
||||
.append(" column of table ")
|
||||
.append_quoted(lnav::roles::symbol(
|
||||
vt->vi->get_name().to_string())))
|
||||
.with_reason(errors[0].to_attr_line({}))
|
||||
.with_snippet(
|
||||
lnav::console::snippet::from(
|
||||
log_vtab_data.lvd_source,
|
||||
log_vtab_data.lvd_content)
|
||||
.with_line(log_vtab_data.lvd_line_number));
|
||||
auto json_error = lnav::to_json(top_error);
|
||||
tab->zErrMsg
|
||||
= sqlite3_mprintf("lnav-error:%s", json_error.c_str());
|
||||
log_debug("dump %s", json_error.c_str());
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -207,25 +207,30 @@ protected:
|
|||
typedef int (*sql_progress_callback_t)(const log_cursor& lc);
|
||||
typedef void (*sql_progress_finished_callback_t)();
|
||||
|
||||
extern struct _log_vtab_data {
|
||||
struct _log_vtab_data {
|
||||
sql_progress_callback_t lvd_progress;
|
||||
sql_progress_finished_callback_t lvd_finished;
|
||||
std::string lvd_source;
|
||||
int lvd_line_number{0};
|
||||
} log_vtab_data;
|
||||
attr_line_t lvd_content;
|
||||
};
|
||||
|
||||
extern thread_local _log_vtab_data log_vtab_data;
|
||||
|
||||
class sql_progress_guard {
|
||||
public:
|
||||
sql_progress_guard(sql_progress_callback_t cb,
|
||||
sql_progress_finished_callback_t fcb,
|
||||
const std::string& source,
|
||||
int line_number)
|
||||
int line_number,
|
||||
const attr_line_t& content)
|
||||
{
|
||||
log_vtab_data.lvd_progress = cb;
|
||||
log_vtab_data.lvd_finished = fcb;
|
||||
log_vtab_data.lvd_source = source;
|
||||
log_vtab_data.lvd_line_number = line_number;
|
||||
};
|
||||
log_vtab_data.lvd_content = content;
|
||||
}
|
||||
|
||||
~sql_progress_guard()
|
||||
{
|
||||
|
@ -236,7 +241,8 @@ public:
|
|||
log_vtab_data.lvd_finished = nullptr;
|
||||
log_vtab_data.lvd_source.clear();
|
||||
log_vtab_data.lvd_line_number = 0;
|
||||
};
|
||||
log_vtab_data.lvd_content.clear();
|
||||
}
|
||||
};
|
||||
|
||||
class log_vtab_manager {
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "ansi_scrubber.hh"
|
||||
#include "base/ansi_scrubber.hh"
|
||||
#include "base/humanize.time.hh"
|
||||
#include "base/string_util.hh"
|
||||
#include "command_executor.hh"
|
||||
|
@ -371,7 +371,7 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
|
|||
lr.lr_start = time_offset_end;
|
||||
lr.lr_end = -1;
|
||||
|
||||
value_out.emplace_back(lr, view_curses::VC_STYLE.value(attrs));
|
||||
value_out.emplace_back(lr, VC_STYLE.value(attrs));
|
||||
|
||||
if (this->lss_token_line->get_msg_level() == log_level_t::LEVEL_INVALID) {
|
||||
for (auto& token_attr : this->lss_token_attrs) {
|
||||
|
@ -381,7 +381,7 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
|
|||
|
||||
value_out.emplace_back(
|
||||
token_attr.sa_range,
|
||||
view_curses::VC_ROLE.value(view_colors::VCR_INVALID_MSG));
|
||||
VC_ROLE.value(role_t::VCR_INVALID_MSG));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,7 +411,7 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
|
|||
|
||||
value_out.emplace_back(
|
||||
ident_range,
|
||||
view_curses::VC_ROLE.value(view_colors::VCR_IDENTIFIER));
|
||||
VC_ROLE.value(role_t::VCR_IDENTIFIER));
|
||||
}
|
||||
|
||||
if (this->lss_token_shift_size) {
|
||||
|
@ -441,7 +441,7 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
|
|||
} else if (is_last_for_file) {
|
||||
graph = ACS_LLCORNER;
|
||||
}
|
||||
value_out.emplace_back(lr, view_curses::VC_GRAPHIC.value(graph));
|
||||
value_out.emplace_back(lr, VC_GRAPHIC.value(graph));
|
||||
|
||||
if (!(this->lss_token_flags & RF_FULL)) {
|
||||
bookmark_vector<vis_line_t>& bv_search
|
||||
|
@ -453,13 +453,13 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
|
|||
lr.lr_start = 0;
|
||||
lr.lr_end = 1;
|
||||
value_out.emplace_back(lr,
|
||||
view_curses::VC_STYLE.value(A_REVERSE));
|
||||
VC_STYLE.value(A_REVERSE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
value_out.emplace_back(lr,
|
||||
view_curses::VC_STYLE.value(vc.attrs_for_ident(
|
||||
VC_STYLE.value(vc.attrs_for_ident(
|
||||
this->lss_token_file->get_filename())));
|
||||
|
||||
if (this->lss_flags & F_FILENAME || this->lss_flags & F_BASENAME) {
|
||||
|
@ -472,7 +472,7 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
|
|||
lr.lr_start = 0;
|
||||
lr.lr_end = file_offset_end + 1;
|
||||
value_out.emplace_back(lr,
|
||||
view_curses::VC_STYLE.value(vc.attrs_for_ident(
|
||||
VC_STYLE.value(vc.attrs_for_ident(
|
||||
this->lss_token_file->get_filename())));
|
||||
}
|
||||
|
||||
|
@ -484,25 +484,25 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
|
|||
shift_string_attrs(value_out, 0, time_offset_end);
|
||||
|
||||
value_out.emplace_back(
|
||||
lr, view_curses::VC_ROLE.value(view_colors::VCR_OFFSET_TIME));
|
||||
lr, VC_ROLE.value(role_t::VCR_OFFSET_TIME));
|
||||
value_out.emplace_back(line_range(12, 13),
|
||||
view_curses::VC_GRAPHIC.value(ACS_VLINE));
|
||||
VC_GRAPHIC.value(ACS_VLINE));
|
||||
|
||||
view_colors::role_t bar_role = view_colors::VCR_NONE;
|
||||
role_t bar_role = role_t::VCR_NONE;
|
||||
|
||||
switch (this->get_line_accel_direction(vis_line_t(row))) {
|
||||
case log_accel::A_STEADY:
|
||||
break;
|
||||
case log_accel::A_DECEL:
|
||||
bar_role = view_colors::VCR_DIFF_DELETE;
|
||||
bar_role = role_t::VCR_DIFF_DELETE;
|
||||
break;
|
||||
case log_accel::A_ACCEL:
|
||||
bar_role = view_colors::VCR_DIFF_ADD;
|
||||
bar_role = role_t::VCR_DIFF_ADD;
|
||||
break;
|
||||
}
|
||||
if (bar_role != view_colors::VCR_NONE) {
|
||||
if (bar_role != role_t::VCR_NONE) {
|
||||
value_out.emplace_back(line_range(12, 13),
|
||||
view_curses::VC_ROLE.value(bar_role));
|
||||
VC_ROLE.value(bar_role));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -550,7 +550,7 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
|
|||
if (time_range.lr_end != -1) {
|
||||
value_out.emplace_back(
|
||||
time_range,
|
||||
view_curses::VC_ROLE.value(view_colors::VCR_ADJUSTED_TIME));
|
||||
VC_ROLE.value(role_t::VCR_ADJUSTED_TIME));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -561,7 +561,7 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
|
|||
if (time_range.lr_end != -1) {
|
||||
value_out.emplace_back(
|
||||
time_range,
|
||||
view_curses::VC_ROLE.value(view_colors::VCR_SKEWED_TIME));
|
||||
VC_ROLE.value(role_t::VCR_SKEWED_TIME));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -584,11 +584,11 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
|
|||
} else {
|
||||
color = COLOR_RED;
|
||||
value_out.emplace_back(
|
||||
line_range{0, 1}, view_curses::VC_STYLE.value(A_BLINK));
|
||||
line_range{0, 1}, VC_STYLE.value(A_BLINK));
|
||||
}
|
||||
}
|
||||
value_out.emplace_back(line_range{0, 1},
|
||||
view_curses::VC_BACKGROUND.value(color));
|
||||
VC_BACKGROUND.value(color));
|
||||
}
|
||||
|
||||
auto sql_filter_opt = this->get_sql_filter();
|
||||
|
@ -605,7 +605,7 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
|
|||
auto color = COLOR_YELLOW;
|
||||
value_out.emplace_back(line_range{0, -1}, SA_ERROR.value(msg));
|
||||
value_out.emplace_back(line_range{0, 1},
|
||||
view_curses::VC_BACKGROUND.value(color));
|
||||
VC_BACKGROUND.value(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "auto_mem.hh"
|
||||
#include "base/auto_mem.hh"
|
||||
#include "config.h"
|
||||
#include "sqlite-extension-func.hh"
|
||||
#include "sqlite3.h"
|
||||
|
|
|
@ -45,8 +45,8 @@
|
|||
# include <sys/wait.h>
|
||||
# include <unistd.h>
|
||||
|
||||
# include "auto_mem.hh"
|
||||
# include "base/auto_fd.hh"
|
||||
# include "base/auto_mem.hh"
|
||||
# include "curl_looper.hh"
|
||||
# include "line_buffer.hh"
|
||||
# include "yajlpp/yajlpp.hh"
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "auto_mem.hh"
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/intern_string.hh"
|
||||
#include "base/result.h"
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "attr_line.hh"
|
||||
#include "base/attr_line.hh"
|
||||
#include "textview_curses.hh"
|
||||
|
||||
class plain_text_source
|
||||
|
@ -55,18 +55,18 @@ public:
|
|||
this->tds_lines.emplace_back(text.substr(start));
|
||||
}
|
||||
this->tds_longest_line = this->compute_longest_line();
|
||||
};
|
||||
}
|
||||
|
||||
plain_text_source(const std::vector<std::string>& text_lines)
|
||||
{
|
||||
this->replace_with(text_lines);
|
||||
};
|
||||
}
|
||||
|
||||
plain_text_source(const std::vector<attr_line_t>& text_lines)
|
||||
{
|
||||
this->tds_lines = text_lines;
|
||||
this->tds_longest_line = this->compute_longest_line();
|
||||
};
|
||||
}
|
||||
|
||||
plain_text_source& replace_with(const attr_line_t& text_lines)
|
||||
{
|
||||
|
@ -74,23 +74,23 @@ public:
|
|||
text_lines.split_lines(this->tds_lines);
|
||||
this->tds_longest_line = this->compute_longest_line();
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
plain_text_source& replace_with(const std::vector<std::string>& text_lines)
|
||||
{
|
||||
for (auto& str : text_lines) {
|
||||
for (const auto& str : text_lines) {
|
||||
this->tds_lines.emplace_back(str);
|
||||
}
|
||||
this->tds_longest_line = this->compute_longest_line();
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
this->tds_lines.clear();
|
||||
this->tds_longest_line = 0;
|
||||
this->tds_text_format = text_format_t::TF_UNKNOWN;
|
||||
};
|
||||
}
|
||||
|
||||
plain_text_source& truncate_to(size_t max_lines)
|
||||
{
|
||||
|
@ -98,22 +98,22 @@ public:
|
|||
this->tds_lines.pop_back();
|
||||
}
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
size_t text_line_count()
|
||||
{
|
||||
return this->tds_lines.size();
|
||||
};
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return this->tds_lines.empty();
|
||||
};
|
||||
}
|
||||
|
||||
size_t text_line_width(textview_curses& curses)
|
||||
{
|
||||
return this->tds_longest_line;
|
||||
};
|
||||
}
|
||||
|
||||
void text_value_for_line(textview_curses& tc,
|
||||
int row,
|
||||
|
@ -121,30 +121,35 @@ public:
|
|||
line_flags_t flags)
|
||||
{
|
||||
value_out = this->tds_lines[row].get_string();
|
||||
};
|
||||
}
|
||||
|
||||
void text_attrs_for_line(textview_curses& tc,
|
||||
int line,
|
||||
string_attrs_t& value_out)
|
||||
{
|
||||
value_out = this->tds_lines[line].get_attrs();
|
||||
};
|
||||
}
|
||||
|
||||
size_t text_size_for_line(textview_curses& tc, int row, line_flags_t flags)
|
||||
{
|
||||
return this->tds_lines[row].length();
|
||||
};
|
||||
}
|
||||
|
||||
text_format_t get_text_format() const
|
||||
{
|
||||
return this->tds_text_format;
|
||||
};
|
||||
}
|
||||
|
||||
const std::vector<attr_line_t>& get_lines() const
|
||||
{
|
||||
return this->tds_lines;
|
||||
}
|
||||
|
||||
plain_text_source& set_text_format(text_format_t format)
|
||||
{
|
||||
this->tds_text_format = format;
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
nonstd::optional<location_history*> get_location_history()
|
||||
{
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "attr_line.hh"
|
||||
#include "base/attr_line.hh"
|
||||
#include "data_scanner.hh"
|
||||
|
||||
class pretty_printer {
|
||||
|
|
|
@ -50,12 +50,12 @@ public:
|
|||
static const char TOGGLE_MSG[] = "Press CTRL+P to show/hide";
|
||||
|
||||
this->tss_fields[TSF_TITLE].set_width(14);
|
||||
this->tss_fields[TSF_TITLE].set_role(view_colors::VCR_STATUS_TITLE);
|
||||
this->tss_fields[TSF_TITLE].set_role(role_t::VCR_STATUS_TITLE);
|
||||
this->tss_fields[TSF_TITLE].set_value(" Preview Data ");
|
||||
this->tss_fields[TSF_STITCH_TITLE].set_width(2);
|
||||
this->tss_fields[TSF_STITCH_TITLE].set_stitch_value(
|
||||
view_colors::VCR_STATUS_STITCH_TITLE_TO_NORMAL,
|
||||
view_colors::VCR_STATUS_STITCH_NORMAL_TO_TITLE);
|
||||
role_t::VCR_STATUS_STITCH_TITLE_TO_NORMAL,
|
||||
role_t::VCR_STATUS_STITCH_NORMAL_TO_TITLE);
|
||||
this->tss_fields[TSF_DESCRIPTION].set_share(1);
|
||||
this->tss_fields[TSF_TOGGLE].set_width(strlen(TOGGLE_MSG) + 1);
|
||||
this->tss_fields[TSF_TOGGLE].set_value(TOGGLE_MSG);
|
||||
|
|
|
@ -49,6 +49,8 @@
|
|||
#include "vtab_module.hh"
|
||||
#include "yajlpp/yajlpp.hh"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
#define ABORT_MSG "(Press " ANSI_BOLD("CTRL+]") " to abort)"
|
||||
|
||||
#define STR_HELPER(x) #x
|
||||
|
@ -126,7 +128,7 @@ rl_set_help()
|
|||
}
|
||||
case LNM_SQL: {
|
||||
textview_curses& log_view = lnav_data.ld_views[LNV_LOG];
|
||||
auto lss = (logfile_sub_source*) log_view.get_sub_source();
|
||||
auto* lss = (logfile_sub_source*) log_view.get_sub_source();
|
||||
attr_line_t example_al;
|
||||
|
||||
if (log_view.get_inner_height() > 0) {
|
||||
|
@ -241,6 +243,7 @@ rl_change(readline_curses* rc)
|
|||
tc->get_highlights().erase({highlight_source_t::PREVIEW, "preview"});
|
||||
tc->get_highlights().erase({highlight_source_t::PREVIEW, "bodypreview"});
|
||||
lnav_data.ld_log_source.set_preview_sql_filter(nullptr);
|
||||
lnav_data.ld_user_message_source.clear();
|
||||
lnav_data.ld_preview_source.clear();
|
||||
lnav_data.ld_preview_status_source.get_description()
|
||||
.set_cylon(false)
|
||||
|
@ -266,9 +269,9 @@ rl_change(readline_curses* rc)
|
|||
generation += 1;
|
||||
}
|
||||
|
||||
auto os = tc->get_overlay_source();
|
||||
auto* os = tc->get_overlay_source();
|
||||
if (!args.empty() && os != nullptr) {
|
||||
auto fos = dynamic_cast<field_overlay_source*>(os);
|
||||
auto* fos = dynamic_cast<field_overlay_source*>(os);
|
||||
|
||||
if (fos != nullptr) {
|
||||
if (generation == 0) {
|
||||
|
@ -400,6 +403,7 @@ rl_search_internal(readline_curses* rc, ln_mode_t mode, bool complete = false)
|
|||
tc->get_highlights().erase({highlight_source_t::PREVIEW, "bodypreview"});
|
||||
lnav_data.ld_log_source.set_preview_sql_filter(nullptr);
|
||||
tc->reload_data();
|
||||
lnav_data.ld_user_message_source.clear();
|
||||
|
||||
switch (mode) {
|
||||
case LNM_SEARCH:
|
||||
|
@ -436,7 +440,8 @@ rl_search_internal(readline_curses* rc, ln_mode_t mode, bool complete = false)
|
|||
}
|
||||
} else {
|
||||
lnav_data.ld_bottom_source.set_prompt("");
|
||||
lnav_data.ld_bottom_source.grep_error(result.unwrapErr());
|
||||
lnav_data.ld_bottom_source.grep_error(
|
||||
result.unwrapErr().um_message.get_string());
|
||||
}
|
||||
|
||||
lnav_data.ld_preview_view.reload_data();
|
||||
|
@ -518,7 +523,7 @@ lnav_rl_abort(readline_curses* rc)
|
|||
tc->get_highlights().erase({highlight_source_t::PREVIEW, "bodypreview"});
|
||||
lnav_data.ld_log_source.set_preview_sql_filter(nullptr);
|
||||
|
||||
std::vector<std::string> errors;
|
||||
std::vector<lnav::console::user_message> errors;
|
||||
lnav_config = rollback_lnav_config;
|
||||
reload_config(errors);
|
||||
|
||||
|
@ -577,13 +582,30 @@ rl_callback_int(readline_curses* rc, bool is_alt)
|
|||
require(0);
|
||||
break;
|
||||
|
||||
case LNM_COMMAND:
|
||||
case LNM_COMMAND: {
|
||||
rc->set_alt_value("");
|
||||
rc->set_value(execute_command(ec, rc->get_value())
|
||||
.map(ok_prefix)
|
||||
.orElse(err_to_ok)
|
||||
.unwrap());
|
||||
ec.ec_source.top().s_content
|
||||
= fmt::format(FMT_STRING(":{}"), rc->get_value());
|
||||
auto exec_res = execute_command(ec, rc->get_value());
|
||||
if (exec_res.isOk()) {
|
||||
rc->set_value(exec_res.unwrap());
|
||||
} else {
|
||||
auto um = exec_res.unwrapErr();
|
||||
|
||||
lnav_data.ld_user_message_source.replace_with(
|
||||
um.to_attr_line().rtrim());
|
||||
for (const auto& line :
|
||||
lnav_data.ld_user_message_source.get_lines()) {
|
||||
log_debug("line -- %s", lnav::to_json(line).c_str());
|
||||
}
|
||||
lnav_data.ld_user_message_view.reload_data();
|
||||
lnav_data.ld_user_message_expiration
|
||||
= std::chrono::steady_clock::now() + 20s;
|
||||
rc->set_value("");
|
||||
}
|
||||
ec.ec_source.top().s_content.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
case LNM_USER:
|
||||
rc->set_alt_value("");
|
||||
|
@ -645,6 +667,7 @@ rl_callback_int(readline_curses* rc, bool is_alt)
|
|||
break;
|
||||
|
||||
case LNM_SQL: {
|
||||
ec.ec_source.top().s_content = rc->get_value();
|
||||
auto result = execute_sql(ec, rc->get_value(), alt_msg);
|
||||
db_label_source& dls = lnav_data.ld_db_row_source;
|
||||
std::string prompt;
|
||||
|
@ -659,8 +682,14 @@ rl_callback_int(readline_curses* rc, bool is_alt)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
prompt = result.orElse(err_to_ok).unwrap();
|
||||
auto um = result.unwrapErr();
|
||||
lnav_data.ld_user_message_source.replace_with(
|
||||
um.to_attr_line().rtrim());
|
||||
lnav_data.ld_user_message_view.reload_data();
|
||||
lnav_data.ld_user_message_expiration
|
||||
= std::chrono::steady_clock::now() + 20s;
|
||||
}
|
||||
ec.ec_source.top().s_content.clear();
|
||||
|
||||
rc->set_value(prompt);
|
||||
rc->set_alt_value(alt_msg);
|
||||
|
@ -766,7 +795,7 @@ rl_display_matches(readline_curses* rc)
|
|||
add_nl = false;
|
||||
}
|
||||
if (match == current_match) {
|
||||
al.append(match, view_curses::VC_STYLE.value(A_REVERSE));
|
||||
al.append(match, VC_STYLE.value(A_REVERSE));
|
||||
} else {
|
||||
al.append(match);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include <readline/history.h>
|
||||
|
||||
#include "base/lnav.console.hh"
|
||||
#include "base/result.h"
|
||||
#include "help_text.hh"
|
||||
|
||||
|
@ -52,7 +53,7 @@ typedef void (*readline_highlighter_t)(attr_line_t& line, int x);
|
|||
*/
|
||||
class readline_context {
|
||||
public:
|
||||
typedef Result<std::string, std::string> (*command_func_t)(
|
||||
typedef Result<std::string, lnav::console::user_message> (*command_func_t)(
|
||||
exec_context& ec, std::string cmdline, std::vector<std::string>& args);
|
||||
typedef std::string (*prompt_func_t)(exec_context& ec,
|
||||
const std::string& cmdline);
|
||||
|
|
|
@ -54,8 +54,8 @@
|
|||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "ansi_scrubber.hh"
|
||||
#include "auto_mem.hh"
|
||||
#include "base/ansi_scrubber.hh"
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/lnav_log.hh"
|
||||
#include "base/paths.hh"
|
||||
#include "base/string_util.hh"
|
||||
|
@ -1381,7 +1381,7 @@ 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(view_colors::VCR_TEXT));
|
||||
wattron(this->vc_window, vc.attrs_for_role(role_t::VCR_TEXT));
|
||||
whline(this->vc_window, ' ', this->vc_width);
|
||||
|
||||
if (time(nullptr) > this->rc_value_expiration) {
|
||||
|
|
|
@ -90,44 +90,53 @@ public:
|
|||
void add_context(int id, readline_context& rc)
|
||||
{
|
||||
this->rc_contexts[id] = &rc;
|
||||
};
|
||||
}
|
||||
|
||||
void set_focus_action(const action& va)
|
||||
{
|
||||
this->rc_focus = va;
|
||||
};
|
||||
}
|
||||
|
||||
void set_change_action(const action& va)
|
||||
{
|
||||
this->rc_change = va;
|
||||
};
|
||||
}
|
||||
|
||||
void set_perform_action(const action& va)
|
||||
{
|
||||
this->rc_perform = va;
|
||||
};
|
||||
}
|
||||
|
||||
void set_alt_perform_action(const action& va)
|
||||
{
|
||||
this->rc_alt_perform = va;
|
||||
};
|
||||
}
|
||||
|
||||
void set_timeout_action(const action& va)
|
||||
{
|
||||
this->rc_timeout = va;
|
||||
};
|
||||
}
|
||||
|
||||
void set_abort_action(const action& va)
|
||||
{
|
||||
this->rc_abort = va;
|
||||
};
|
||||
}
|
||||
|
||||
void set_display_match_action(const action& va)
|
||||
{
|
||||
this->rc_display_match = va;
|
||||
};
|
||||
}
|
||||
|
||||
void set_display_next_action(const action& va)
|
||||
{
|
||||
this->rc_display_next = va;
|
||||
};
|
||||
}
|
||||
|
||||
void set_blur_action(const action& va)
|
||||
{
|
||||
this->rc_blur = va;
|
||||
};
|
||||
}
|
||||
|
||||
void set_completion_request_action(const action& va)
|
||||
{
|
||||
this->rc_completion_request = va;
|
||||
|
@ -141,32 +150,34 @@ public:
|
|||
}
|
||||
this->rc_value_expiration = time(nullptr) + VALUE_EXPIRATION;
|
||||
this->set_needs_update();
|
||||
};
|
||||
}
|
||||
|
||||
std::string get_value() const
|
||||
{
|
||||
return this->rc_value;
|
||||
};
|
||||
}
|
||||
|
||||
std::string get_line_buffer() const
|
||||
{
|
||||
return this->rc_line_buffer;
|
||||
};
|
||||
}
|
||||
|
||||
void set_alt_value(const std::string& value)
|
||||
{
|
||||
this->rc_alt_value = value;
|
||||
};
|
||||
}
|
||||
|
||||
std::string get_alt_value() const
|
||||
{
|
||||
return this->rc_alt_value;
|
||||
};
|
||||
}
|
||||
|
||||
void update_poll_set(std::vector<struct pollfd>& pollfds)
|
||||
{
|
||||
pollfds.push_back((struct pollfd){this->rc_pty[RCF_MASTER], POLLIN, 0});
|
||||
pollfds.push_back(
|
||||
(struct pollfd){this->rc_command_pipe[RCF_MASTER], POLLIN, 0});
|
||||
};
|
||||
}
|
||||
|
||||
void handle_key(int ch);
|
||||
|
||||
|
@ -190,7 +201,7 @@ public:
|
|||
std::map<int, readline_context*>::const_iterator iter;
|
||||
iter = this->rc_contexts.find(this->rc_active_context);
|
||||
return iter->second;
|
||||
};
|
||||
}
|
||||
|
||||
void abort();
|
||||
|
||||
|
@ -208,7 +219,7 @@ public:
|
|||
if (ioctl(this->rc_pty[RCF_MASTER], TIOCSWINSZ, &ws) == -1) {
|
||||
throw error(errno);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void line_ready(const char* line);
|
||||
|
||||
|
@ -229,7 +240,7 @@ public:
|
|||
for (int lpc = 0; values[lpc]; lpc++) {
|
||||
this->add_possibility(context, type, values[lpc]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void add_possibility(int context,
|
||||
const std::string& type,
|
||||
|
@ -239,7 +250,7 @@ public:
|
|||
for (; first < last; first++) {
|
||||
this->add_possibility(context, type, *first);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<template<typename...> class Container>
|
||||
void add_possibility(int context,
|
||||
|
@ -249,7 +260,7 @@ public:
|
|||
for (const auto& str : values) {
|
||||
this->add_possibility(context, type, str);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void rem_possibility(int context,
|
||||
const std::string& type,
|
||||
|
@ -259,7 +270,7 @@ public:
|
|||
const std::vector<std::string>& get_matches() const
|
||||
{
|
||||
return this->rc_matches;
|
||||
};
|
||||
}
|
||||
|
||||
int get_match_start() const
|
||||
{
|
||||
|
@ -271,7 +282,7 @@ public:
|
|||
int get_max_match_length() const
|
||||
{
|
||||
return this->rc_max_match_length;
|
||||
};
|
||||
}
|
||||
|
||||
bool consume_ready_for_input()
|
||||
{
|
||||
|
@ -327,4 +338,5 @@ private:
|
|||
action rc_blur;
|
||||
action rc_completion_request;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "shlex.hh"
|
||||
#include "sql_help.hh"
|
||||
#include "sql_util.hh"
|
||||
#include "view_curses.hh"
|
||||
|
||||
static void readline_sqlite_highlighter_int(attr_line_t& al, int x, int skip);
|
||||
|
||||
|
@ -72,9 +73,9 @@ find_matching_bracket(attr_line_t& al, int x, char left, char right)
|
|||
{
|
||||
view_colors& vc = view_colors::singleton();
|
||||
int matching_bracket_attrs
|
||||
= A_BOLD | A_REVERSE | vc.attrs_for_role(view_colors::VCR_OK);
|
||||
= A_BOLD | A_REVERSE | vc.attrs_for_role(role_t::VCR_OK);
|
||||
int missing_bracket_attrs
|
||||
= A_BOLD | A_REVERSE | vc.attrs_for_role(view_colors::VCR_ERROR);
|
||||
= A_BOLD | A_REVERSE | vc.attrs_for_role(role_t::VCR_ERROR);
|
||||
bool is_lit = (left == 'Q');
|
||||
const std::string& line = al.get_string();
|
||||
int depth = 0;
|
||||
|
@ -91,7 +92,7 @@ find_matching_bracket(attr_line_t& al, int x, char left, char right)
|
|||
if (depth == 0) {
|
||||
al.get_attrs().emplace_back(
|
||||
line_range(lpc, lpc + 1),
|
||||
view_curses::VC_STYLE.value(matching_bracket_attrs));
|
||||
VC_STYLE.value(matching_bracket_attrs));
|
||||
break;
|
||||
} else {
|
||||
depth -= 1;
|
||||
|
@ -108,7 +109,7 @@ find_matching_bracket(attr_line_t& al, int x, char left, char right)
|
|||
if (depth == 0) {
|
||||
al.get_attrs().emplace_back(
|
||||
line_range(lpc, lpc + 1),
|
||||
view_curses::VC_STYLE.value(matching_bracket_attrs));
|
||||
VC_STYLE.value(matching_bracket_attrs));
|
||||
break;
|
||||
} else {
|
||||
depth -= 1;
|
||||
|
@ -133,7 +134,7 @@ find_matching_bracket(attr_line_t& al, int x, char left, char right)
|
|||
} else {
|
||||
al.get_attrs().emplace_back(
|
||||
line_range(is_lit ? lpc - 1 : lpc, lpc + 1),
|
||||
view_curses::VC_STYLE.value(missing_bracket_attrs));
|
||||
VC_STYLE.value(missing_bracket_attrs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +142,7 @@ find_matching_bracket(attr_line_t& al, int x, char left, char right)
|
|||
if (depth > 0) {
|
||||
al.get_attrs().emplace_back(
|
||||
line_range(is_lit ? first_left - 1 : first_left, first_left + 1),
|
||||
view_curses::VC_STYLE.value(missing_bracket_attrs));
|
||||
VC_STYLE.value(missing_bracket_attrs));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,20 +160,21 @@ static void
|
|||
readline_regex_highlighter_int(attr_line_t& al, int x, int skip)
|
||||
{
|
||||
view_colors& vc = view_colors::singleton();
|
||||
int special_char
|
||||
= (A_BOLD | vc.attrs_for_role(view_colors::VCR_RE_SPECIAL));
|
||||
int class_attrs = (A_BOLD | vc.attrs_for_role(view_colors::VCR_SYMBOL));
|
||||
int repeated_char_attrs = vc.attrs_for_role(view_colors::VCR_RE_REPEAT);
|
||||
int bracket_attrs = vc.attrs_for_role(view_colors::VCR_OK);
|
||||
int special_char = (A_BOLD | vc.attrs_for_role(role_t::VCR_RE_SPECIAL));
|
||||
int class_attrs = (A_BOLD | vc.attrs_for_role(role_t::VCR_SYMBOL));
|
||||
int repeated_char_attrs = vc.attrs_for_role(role_t::VCR_RE_REPEAT);
|
||||
int bracket_attrs = vc.attrs_for_role(role_t::VCR_OK);
|
||||
int error_attrs
|
||||
= (A_BOLD | A_REVERSE | vc.attrs_for_role(view_colors::VCR_ERROR));
|
||||
= (A_BOLD | A_REVERSE | vc.attrs_for_role(role_t::VCR_ERROR));
|
||||
|
||||
static const char* brackets[] = {"[]",
|
||||
"{}",
|
||||
"()",
|
||||
"QE",
|
||||
static const char* brackets[] = {
|
||||
"[]",
|
||||
"{}",
|
||||
"()",
|
||||
"QE",
|
||||
|
||||
nullptr};
|
||||
nullptr,
|
||||
};
|
||||
|
||||
auto& line = al.get_string();
|
||||
bool backslash_is_quoted = false;
|
||||
|
@ -186,15 +188,14 @@ readline_regex_highlighter_int(attr_line_t& al, int x, int skip)
|
|||
case '+':
|
||||
case '|':
|
||||
case '.':
|
||||
al.get_attrs().emplace_back(
|
||||
line_range(lpc, lpc + 1),
|
||||
view_curses::VC_STYLE.value(special_char));
|
||||
al.get_attrs().emplace_back(line_range(lpc, lpc + 1),
|
||||
VC_STYLE.value(special_char));
|
||||
|
||||
if ((line[lpc] == '*' || line[lpc] == '+')
|
||||
&& check_re_prev(line, lpc)) {
|
||||
al.get_attrs().emplace_back(
|
||||
line_range(lpc - 1, lpc),
|
||||
view_curses::VC_STYLE.value(repeated_char_attrs));
|
||||
VC_STYLE.value(repeated_char_attrs));
|
||||
}
|
||||
break;
|
||||
case '?': {
|
||||
|
@ -211,16 +212,15 @@ readline_regex_highlighter_int(attr_line_t& al, int x, int skip)
|
|||
break;
|
||||
}
|
||||
al.get_attrs().emplace_back(
|
||||
lr, view_curses::VC_STYLE.value(bracket_attrs));
|
||||
lr, VC_STYLE.value(bracket_attrs));
|
||||
} else {
|
||||
al.get_attrs().emplace_back(
|
||||
lr, view_curses::VC_STYLE.value(special_char));
|
||||
lr, VC_STYLE.value(special_char));
|
||||
|
||||
if (check_re_prev(line, lpc)) {
|
||||
al.get_attrs().emplace_back(
|
||||
line_range(lpc - 1, lpc),
|
||||
view_curses::VC_STYLE.value(
|
||||
repeated_char_attrs));
|
||||
VC_STYLE.value(repeated_char_attrs));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -232,9 +232,8 @@ readline_regex_highlighter_int(attr_line_t& al, int x, int skip)
|
|||
case '}':
|
||||
case '[':
|
||||
case ']':
|
||||
al.get_attrs().emplace_back(
|
||||
line_range(lpc, lpc + 1),
|
||||
view_curses::VC_STYLE.value(bracket_attrs));
|
||||
al.get_attrs().emplace_back(line_range(lpc, lpc + 1),
|
||||
VC_STYLE.value(bracket_attrs));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -246,9 +245,8 @@ readline_regex_highlighter_int(attr_line_t& al, int x, int skip)
|
|||
switch (line[lpc]) {
|
||||
case '\\':
|
||||
backslash_is_quoted = true;
|
||||
al.with_attr(
|
||||
string_attr(line_range(lpc - 1, lpc + 1),
|
||||
view_curses::VC_STYLE.value(special_char)));
|
||||
al.with_attr(string_attr(line_range(lpc - 1, lpc + 1),
|
||||
VC_STYLE.value(special_char)));
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
|
@ -270,44 +268,38 @@ readline_regex_highlighter_int(attr_line_t& al, int x, int skip)
|
|||
case 'G':
|
||||
case 'Z':
|
||||
case 'z':
|
||||
al.get_attrs().emplace_back(
|
||||
line_range(lpc - 1, lpc + 1),
|
||||
view_curses::VC_STYLE.value(class_attrs));
|
||||
al.get_attrs().emplace_back(line_range(lpc - 1, lpc + 1),
|
||||
VC_STYLE.value(class_attrs));
|
||||
break;
|
||||
case ' ':
|
||||
al.get_attrs().emplace_back(
|
||||
line_range(lpc - 1, lpc + 1),
|
||||
view_curses::VC_STYLE.value(error_attrs));
|
||||
al.get_attrs().emplace_back(line_range(lpc - 1, lpc + 1),
|
||||
VC_STYLE.value(error_attrs));
|
||||
break;
|
||||
case '0':
|
||||
case 'x':
|
||||
if (safe_read(line, lpc + 1) == '{') {
|
||||
al.with_attr(string_attr(
|
||||
line_range(lpc - 1, lpc + 1),
|
||||
view_curses::VC_STYLE.value(special_char)));
|
||||
al.with_attr(string_attr(line_range(lpc - 1, lpc + 1),
|
||||
VC_STYLE.value(special_char)));
|
||||
} else if (isdigit(safe_read(line, lpc + 1))
|
||||
&& isdigit(safe_read(line, lpc + 2)))
|
||||
{
|
||||
al.with_attr(string_attr(
|
||||
line_range(lpc - 1, lpc + 3),
|
||||
view_curses::VC_STYLE.value(special_char)));
|
||||
al.with_attr(string_attr(line_range(lpc - 1, lpc + 3),
|
||||
VC_STYLE.value(special_char)));
|
||||
} else {
|
||||
al.with_attr(string_attr(
|
||||
line_range(lpc - 1, lpc + 1),
|
||||
view_curses::VC_STYLE.value(error_attrs)));
|
||||
al.with_attr(string_attr(line_range(lpc - 1, lpc + 1),
|
||||
VC_STYLE.value(error_attrs)));
|
||||
}
|
||||
break;
|
||||
case 'Q':
|
||||
case 'E':
|
||||
al.with_attr(string_attr(
|
||||
line_range(lpc - 1, lpc + 1),
|
||||
view_curses::VC_STYLE.value(bracket_attrs)));
|
||||
al.with_attr(string_attr(line_range(lpc - 1, lpc + 1),
|
||||
VC_STYLE.value(bracket_attrs)));
|
||||
break;
|
||||
default:
|
||||
if (isdigit(line[lpc])) {
|
||||
al.get_attrs().emplace_back(
|
||||
line_range(lpc - 1, lpc + 1),
|
||||
view_curses::VC_STYLE.value(special_char));
|
||||
VC_STYLE.value(special_char));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -338,7 +330,7 @@ readline_command_highlighter(attr_line_t& al, int x)
|
|||
static const pcrepp COLOR_RE("(#(?:[a-fA-F0-9]{6}|[a-fA-F0-9]{3}))");
|
||||
|
||||
view_colors& vc = view_colors::singleton();
|
||||
int keyword_attrs = (A_BOLD | vc.attrs_for_role(view_colors::VCR_KEYWORD));
|
||||
int keyword_attrs = (A_BOLD | vc.attrs_for_role(role_t::VCR_KEYWORD));
|
||||
|
||||
const auto& line = al.get_string();
|
||||
pcre_context_static<30> pc;
|
||||
|
@ -349,7 +341,7 @@ readline_command_highlighter(attr_line_t& al, int x)
|
|||
auto command = line.substr(0, ws_index);
|
||||
if (ws_index != std::string::npos) {
|
||||
al.get_attrs().emplace_back(line_range(1, ws_index),
|
||||
view_curses::VC_STYLE.value(keyword_attrs));
|
||||
VC_STYLE.value(keyword_attrs));
|
||||
}
|
||||
if (RE_PREFIXES.match(pc, pi)) {
|
||||
readline_regex_highlighter_int(al, x, 1 + pc[0]->length());
|
||||
|
@ -373,8 +365,7 @@ readline_command_highlighter(attr_line_t& al, int x)
|
|||
.then([&](const auto& rgb_fg) {
|
||||
al.get_attrs().emplace_back(
|
||||
line_range{cap->c_begin, cap->c_begin + 1},
|
||||
view_curses::VC_ROLE.value(
|
||||
view_colors::VCR_COLOR_HINT));
|
||||
VC_ROLE.value(role_t::VCR_COLOR_HINT));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -402,7 +393,7 @@ readline_command_highlighter(attr_line_t& al, int x)
|
|||
value = "#" + value;
|
||||
}
|
||||
al.get_attrs().emplace_back(
|
||||
lr, view_curses::VC_STYLE.value(vc.attrs_for_ident(value)));
|
||||
lr, VC_STYLE.value(vc.attrs_for_ident(value)));
|
||||
}
|
||||
|
||||
start = last;
|
||||
|
@ -426,10 +417,10 @@ readline_sqlite_highlighter_int(attr_line_t& al, int x, int skip)
|
|||
|
||||
auto& vc = view_colors::singleton();
|
||||
|
||||
int keyword_attrs = vc.attrs_for_role(view_colors::VCR_KEYWORD);
|
||||
int symbol_attrs = vc.attrs_for_role(view_colors::VCR_SYMBOL);
|
||||
int string_attrs = vc.attrs_for_role(view_colors::VCR_STRING);
|
||||
int error_attrs = vc.attrs_for_role(view_colors::VCR_ERROR) | A_REVERSE;
|
||||
int keyword_attrs = vc.attrs_for_role(role_t::VCR_KEYWORD);
|
||||
int symbol_attrs = vc.attrs_for_role(role_t::VCR_SYMBOL);
|
||||
int string_attrs = vc.attrs_for_role(role_t::VCR_STRING);
|
||||
int error_attrs = vc.attrs_for_role(role_t::VCR_ERROR) | A_REVERSE;
|
||||
|
||||
pcre_context_static<30> pc;
|
||||
pcre_input pi(al.get_string(), skip);
|
||||
|
@ -444,8 +435,7 @@ readline_sqlite_highlighter_int(attr_line_t& al, int x, int skip)
|
|||
if (space != std::string::npos) {
|
||||
lr.lr_end = space;
|
||||
}
|
||||
al.get_attrs().emplace_back(lr,
|
||||
view_curses::VC_STYLE.value(keyword_attrs));
|
||||
al.get_attrs().emplace_back(lr, VC_STYLE.value(keyword_attrs));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -456,7 +446,7 @@ readline_sqlite_highlighter_int(attr_line_t& al, int x, int skip)
|
|||
|
||||
if (line[cap->c_end] == '(') {
|
||||
} else if (!lr.contains(x) && !lr.contains(x - 1)) {
|
||||
al.get_attrs().emplace_back(lr, view_curses::VC_STYLE.value(attrs));
|
||||
al.get_attrs().emplace_back(lr, VC_STYLE.value(attrs));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,7 +456,7 @@ readline_sqlite_highlighter_int(attr_line_t& al, int x, int skip)
|
|||
pcre_context::capture_t* cap = pc.all();
|
||||
|
||||
al.get_attrs().emplace_back(line_range(cap->c_begin, cap->c_end),
|
||||
view_curses::VC_STYLE.value(keyword_attrs));
|
||||
VC_STYLE.value(keyword_attrs));
|
||||
}
|
||||
|
||||
for (size_t lpc = skip; lpc < line.length(); lpc++) {
|
||||
|
@ -478,9 +468,8 @@ readline_sqlite_highlighter_int(attr_line_t& al, int x, int skip)
|
|||
case '!':
|
||||
case '-':
|
||||
case '+':
|
||||
al.get_attrs().emplace_back(
|
||||
line_range(lpc, lpc + 1),
|
||||
view_curses::VC_STYLE.value(symbol_attrs));
|
||||
al.get_attrs().emplace_back(line_range(lpc, lpc + 1),
|
||||
VC_STYLE.value(symbol_attrs));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -496,10 +485,10 @@ readline_sqlite_highlighter_int(attr_line_t& al, int x, int skip)
|
|||
|
||||
if (line[cap->c_end - 1] != '\'') {
|
||||
sa.emplace_back(line_range(cap->c_begin, cap->c_begin + 1),
|
||||
view_curses::VC_STYLE.value(error_attrs));
|
||||
VC_STYLE.value(error_attrs));
|
||||
lr.lr_start += 1;
|
||||
}
|
||||
sa.emplace_back(lr, view_curses::VC_STYLE.value(string_attrs));
|
||||
sa.emplace_back(lr, VC_STYLE.value(string_attrs));
|
||||
}
|
||||
|
||||
for (int lpc = 0; brackets[lpc]; lpc++) {
|
||||
|
@ -517,9 +506,9 @@ void
|
|||
readline_shlex_highlighter(attr_line_t& al, int x)
|
||||
{
|
||||
view_colors& vc = view_colors::singleton();
|
||||
int special_char = (A_BOLD | vc.attrs_for_role(view_colors::VCR_SYMBOL));
|
||||
int error_attrs = vc.attrs_for_role(view_colors::VCR_ERROR) | A_REVERSE;
|
||||
int string_attrs = vc.attrs_for_role(view_colors::VCR_STRING);
|
||||
int special_char = (A_BOLD | vc.attrs_for_role(role_t::VCR_SYMBOL));
|
||||
int error_attrs = vc.attrs_for_role(role_t::VCR_ERROR) | A_REVERSE;
|
||||
int string_attrs = vc.attrs_for_role(role_t::VCR_STRING);
|
||||
const auto& str = al.get_string();
|
||||
pcre_context::capture_t cap;
|
||||
shlex_token_t token;
|
||||
|
@ -529,15 +518,13 @@ readline_shlex_highlighter(attr_line_t& al, int x)
|
|||
while (lexer.tokenize(cap, token)) {
|
||||
switch (token) {
|
||||
case shlex_token_t::ST_ERROR:
|
||||
al.with_attr(
|
||||
string_attr(line_range(cap.c_begin, cap.c_end),
|
||||
view_curses::VC_STYLE.value(error_attrs)));
|
||||
al.with_attr(string_attr(line_range(cap.c_begin, cap.c_end),
|
||||
VC_STYLE.value(error_attrs)));
|
||||
break;
|
||||
case shlex_token_t::ST_TILDE:
|
||||
case shlex_token_t::ST_ESCAPE:
|
||||
al.with_attr(
|
||||
string_attr(line_range(cap.c_begin, cap.c_end),
|
||||
view_curses::VC_STYLE.value(special_char)));
|
||||
al.with_attr(string_attr(line_range(cap.c_begin, cap.c_end),
|
||||
VC_STYLE.value(special_char)));
|
||||
break;
|
||||
case shlex_token_t::ST_DOUBLE_QUOTE_START:
|
||||
case shlex_token_t::ST_SINGLE_QUOTE_START:
|
||||
|
@ -545,9 +532,8 @@ readline_shlex_highlighter(attr_line_t& al, int x)
|
|||
break;
|
||||
case shlex_token_t::ST_DOUBLE_QUOTE_END:
|
||||
case shlex_token_t::ST_SINGLE_QUOTE_END:
|
||||
al.with_attr(
|
||||
string_attr(line_range(quote_start, cap.c_end),
|
||||
view_curses::VC_STYLE.value(string_attrs)));
|
||||
al.with_attr(string_attr(line_range(quote_start, cap.c_end),
|
||||
VC_STYLE.value(string_attrs)));
|
||||
quote_start = -1;
|
||||
break;
|
||||
case shlex_token_t::ST_VARIABLE_REF:
|
||||
|
@ -559,16 +545,16 @@ readline_shlex_highlighter(attr_line_t& al, int x)
|
|||
|
||||
al.with_attr(string_attr(
|
||||
line_range(cap.c_begin, cap.c_begin + 1 + extra),
|
||||
view_curses::VC_STYLE.value(special_char)));
|
||||
VC_STYLE.value(special_char)));
|
||||
al.with_attr(string_attr(
|
||||
line_range(cap.c_begin + 1 + extra, cap.c_end - extra),
|
||||
view_curses::VC_STYLE.value(
|
||||
x == cap.c_end || cap.contains(x) ? special_char
|
||||
: attrs)));
|
||||
VC_STYLE.value(x == cap.c_end || cap.contains(x)
|
||||
? special_char
|
||||
: attrs)));
|
||||
if (extra) {
|
||||
al.with_attr(
|
||||
string_attr(line_range(cap.c_end - 1, cap.c_end),
|
||||
view_curses::VC_STYLE.value(special_char)));
|
||||
VC_STYLE.value(special_char)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -579,6 +565,6 @@ readline_shlex_highlighter(attr_line_t& al, int x)
|
|||
|
||||
if (quote_start != -1) {
|
||||
al.with_attr(string_attr(line_range(quote_start, quote_start + 1),
|
||||
view_curses::VC_STYLE.value(error_attrs)));
|
||||
VC_STYLE.value(error_attrs)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#ifndef readline_highlighters_hh
|
||||
#define readline_highlighters_hh
|
||||
|
||||
#include "view_curses.hh"
|
||||
#include "base/attr_line.hh"
|
||||
|
||||
void readline_regex_highlighter(attr_line_t& line, int x);
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ relative_time::from_str(const char* str, size_t len)
|
|||
parse_error pe_out;
|
||||
std::unordered_set<int> seen_tokens;
|
||||
|
||||
pe_out.pe_column = -1;
|
||||
pe_out.pe_column = 0;
|
||||
pe_out.pe_msg.clear();
|
||||
|
||||
while (true) {
|
||||
|
|
|
@ -913,7 +913,7 @@ static struct json_path_container view_handlers
|
|||
static struct json_path_container file_state_handlers = {
|
||||
yajlpp::property_handler("visible")
|
||||
.with_description("Indicates whether the file is visible or not")
|
||||
.FOR_FIELD(file_state, fs_is_visible),
|
||||
.for_field(&file_state::fs_is_visible),
|
||||
};
|
||||
|
||||
static struct json_path_container file_states_handlers = {
|
||||
|
@ -928,9 +928,9 @@ static struct json_path_container file_states_handlers = {
|
|||
|
||||
static struct json_path_container view_info_handlers = {
|
||||
yajlpp::property_handler("save-time")
|
||||
.FOR_FIELD(session_data_t, sd_save_time),
|
||||
.for_field(&session_data_t::sd_save_time),
|
||||
yajlpp::property_handler("time-offset")
|
||||
.FOR_FIELD(session_data_t, sd_time_offset),
|
||||
.for_field(&session_data_t::sd_time_offset),
|
||||
json_path_handler("files#", read_files),
|
||||
yajlpp::property_handler("file-states").with_children(file_states_handlers),
|
||||
yajlpp::property_handler("views").with_children(view_handlers),
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#define lnav_session_data_hh
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "view_helpers.hh"
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "auto_mem.hh"
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/lnav_log.hh"
|
||||
|
||||
class shared_buffer;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "spectro_source.hh"
|
||||
|
||||
#include "base/ansi_scrubber.hh"
|
||||
#include "base/math_util.hh"
|
||||
#include "config.h"
|
||||
|
||||
|
@ -155,7 +156,7 @@ spectrogram_source::list_value_for_overlay(const listview_curses& lv,
|
|||
|
||||
if (this->ss_cached_line_count == 0) {
|
||||
value_out.with_ansi_string(ANSI_ROLE("error: no log data"),
|
||||
view_colors::VCR_ERROR);
|
||||
role_t::VCR_ERROR);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -169,12 +170,12 @@ spectrogram_source::list_value_for_overlay(const listview_curses& lv,
|
|||
sizeof(buf),
|
||||
ANSI_ROLE(" ") " 1-%'d " ANSI_ROLE(" ") " %'d-%'d " ANSI_ROLE(
|
||||
" ") " %'d+",
|
||||
view_colors::VCR_LOW_THRESHOLD,
|
||||
role_t::VCR_LOW_THRESHOLD,
|
||||
st.st_green_threshold - 1,
|
||||
view_colors::VCR_MED_THRESHOLD,
|
||||
role_t::VCR_MED_THRESHOLD,
|
||||
st.st_green_threshold,
|
||||
st.st_yellow_threshold - 1,
|
||||
view_colors::VCR_HIGH_THRESHOLD,
|
||||
role_t::VCR_HIGH_THRESHOLD,
|
||||
st.st_yellow_threshold);
|
||||
line.append(width / 2 - strlen(buf) / 3 - line.length(), ' ');
|
||||
line.append(buf);
|
||||
|
@ -185,7 +186,7 @@ spectrogram_source::list_value_for_overlay(const listview_curses& lv,
|
|||
line.append(buf);
|
||||
|
||||
value_out.with_attr(string_attr(line_range(0, -1),
|
||||
view_curses::VC_STYLE.value(A_UNDERLINE)));
|
||||
VC_STYLE.value(A_UNDERLINE)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -321,7 +322,7 @@ spectrogram_source::text_attrs_for_line(textview_curses& tc,
|
|||
color = COLOR_RED;
|
||||
}
|
||||
value_out.emplace_back(line_range(lpc, lpc + 1),
|
||||
view_curses::VC_STYLE.value(
|
||||
VC_STYLE.value(
|
||||
vc.ansi_color_pair(COLOR_BLACK, color)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "ansi_scrubber.hh"
|
||||
#include "textview_curses.hh"
|
||||
|
||||
struct spectrogram_bounds {
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "auto_mem.hh"
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/fs_util.hh"
|
||||
#include "base/injector.bind.hh"
|
||||
#include "base/lnav_log.hh"
|
||||
|
@ -40,7 +40,7 @@
|
|||
#include "sqlitepp.hh"
|
||||
#include "view_helpers.hh"
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
sql_cmd_dump(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -80,7 +80,7 @@ sql_cmd_dump(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
sql_cmd_read(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -143,7 +143,7 @@ sql_cmd_read(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
sql_cmd_schema(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
@ -159,7 +159,7 @@ sql_cmd_schema(exec_context& ec,
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
static Result<std::string, std::string>
|
||||
static Result<std::string, lnav::console::user_message>
|
||||
sql_cmd_generic(exec_context& ec,
|
||||
std::string cmdline,
|
||||
std::vector<std::string>& args)
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
#include "attr_line.hh"
|
||||
#include "base/attr_line.hh"
|
||||
#include "help_text.hh"
|
||||
|
||||
extern string_attr_type<void> SQL_COMMAND_ATTR;
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "auto_mem.hh"
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/injector.hh"
|
||||
#include "base/lnav_log.hh"
|
||||
#include "base/string_util.hh"
|
||||
|
@ -655,11 +655,11 @@ sql_compile_script(sqlite3* db,
|
|||
const char* src_name,
|
||||
const char* script_orig,
|
||||
std::vector<sqlite3_stmt*>& stmts,
|
||||
std::vector<std::string>& errors)
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
const char* script = script_orig;
|
||||
|
||||
while (script != NULL && script[0]) {
|
||||
while (script != nullptr && script[0]) {
|
||||
auto_mem<sqlite3_stmt> stmt(sqlite3_finalize);
|
||||
int line_number = 1;
|
||||
const char* tail;
|
||||
|
@ -678,23 +678,23 @@ sql_compile_script(sqlite3* db,
|
|||
log_debug("retcode %d %p %p", retcode, script, tail);
|
||||
if (retcode != SQLITE_OK) {
|
||||
const char* errmsg = sqlite3_errmsg(db);
|
||||
auto_mem<char> full_msg;
|
||||
attr_line_t sql_content;
|
||||
|
||||
if (asprintf(full_msg.out(),
|
||||
"error:%s:%d:%s",
|
||||
src_name,
|
||||
line_number,
|
||||
errmsg)
|
||||
== -1)
|
||||
{
|
||||
log_error("unable to allocate error message");
|
||||
break;
|
||||
if (tail != nullptr) {
|
||||
sql_content.append(script, (size_t) (tail - script));
|
||||
} else {
|
||||
sql_content.append(script);
|
||||
}
|
||||
errors.emplace_back(full_msg.in());
|
||||
errors.emplace_back(lnav::console::user_message::error(
|
||||
"failed to compile SQL statement")
|
||||
.with_reason(errmsg)
|
||||
.with_snippet(lnav::console::snippet::from(
|
||||
src_name, sql_content)
|
||||
.with_line(line_number)));
|
||||
break;
|
||||
} else if (script == tail) {
|
||||
break;
|
||||
} else if (stmt == NULL) {
|
||||
} else if (stmt == nullptr) {
|
||||
} else {
|
||||
stmts.push_back(stmt.release());
|
||||
}
|
||||
|
@ -703,10 +703,11 @@ sql_compile_script(sqlite3* db,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
sql_execute_script(sqlite3* db,
|
||||
const char* src_name,
|
||||
const std::vector<sqlite3_stmt*>& stmts,
|
||||
std::vector<std::string>& errors)
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
std::map<std::string, std::string> lvars;
|
||||
|
||||
|
@ -766,7 +767,13 @@ sql_execute_script(sqlite3* db,
|
|||
const char* errmsg;
|
||||
|
||||
errmsg = sqlite3_errmsg(db);
|
||||
errors.emplace_back(errmsg);
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error(
|
||||
"failed to execute SQL statement")
|
||||
.with_reason(errmsg)
|
||||
.with_snippet(lnav::console::snippet::from(
|
||||
src_name, sqlite3_sql(stmt))));
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -780,13 +787,14 @@ void
|
|||
sql_execute_script(sqlite3* db,
|
||||
const char* src_name,
|
||||
const char* script,
|
||||
std::vector<std::string>& errors)
|
||||
std::vector<lnav::console::user_message>& errors)
|
||||
{
|
||||
std::vector<sqlite3_stmt*> stmts;
|
||||
auto init_error_count = errors.size();
|
||||
|
||||
sql_compile_script(db, src_name, script, stmts, errors);
|
||||
if (errors.empty()) {
|
||||
sql_execute_script(db, stmts, errors);
|
||||
if (errors.size() == init_error_count) {
|
||||
sql_execute_script(db, src_name, stmts, errors);
|
||||
}
|
||||
|
||||
for (sqlite3_stmt* stmt : stmts) {
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <time.h>
|
||||
|
||||
#include "base/intern_string.hh"
|
||||
#include "base/lnav.console.hh"
|
||||
#include "base/time_util.hh"
|
||||
#include "sqlitepp.hh"
|
||||
|
||||
|
@ -94,16 +95,12 @@ void sql_compile_script(sqlite3* db,
|
|||
const char* src_name,
|
||||
const char* script,
|
||||
std::vector<sqlite3_stmt*>& stmts,
|
||||
std::vector<std::string>& errors);
|
||||
|
||||
void sql_execute_script(sqlite3* db,
|
||||
const std::vector<sqlite3_stmt*>& stmts,
|
||||
std::vector<std::string>& errors);
|
||||
std::vector<lnav::console::user_message>& errors);
|
||||
|
||||
void sql_execute_script(sqlite3* db,
|
||||
const char* src_name,
|
||||
const char* script,
|
||||
std::vector<std::string>& errors);
|
||||
std::vector<lnav::console::user_message>& errors);
|
||||
|
||||
int guess_type_from_pcre(const std::string& pattern, std::string& collator);
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include "sqlite-extension-func.hh"
|
||||
|
||||
#include "auto_mem.hh"
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/lnav_log.hh"
|
||||
#include "base/string_util.hh"
|
||||
#include "config.h"
|
||||
|
@ -942,7 +942,11 @@ register_sqlite_funcs(sqlite3* db, sqlite_registration_func_t* reg_funcs)
|
|||
help_text("SELECT",
|
||||
"Query the database and return zero or more rows of data.")
|
||||
.sql_keyword()
|
||||
.with_parameter(help_text("result-column", "").one_or_more())
|
||||
.with_parameter(
|
||||
help_text(
|
||||
"result-column",
|
||||
"The expression used to generate a result for this column.")
|
||||
.one_or_more())
|
||||
.with_parameter(help_text("table", "The table(s) to query for data")
|
||||
.with_flag_name("FROM")
|
||||
.zero_or_more())
|
||||
|
@ -962,7 +966,7 @@ register_sqlite_funcs(sqlite3* db, sqlite_registration_func_t* reg_funcs)
|
|||
.with_flag_name("ORDER BY")
|
||||
.zero_or_more())
|
||||
.with_parameter(
|
||||
help_text("limit-expr", "The maximum number of rows to return")
|
||||
help_text("limit-expr", "The maximum number of rows to return.")
|
||||
.with_flag_name("LIMIT")
|
||||
.zero_or_more())
|
||||
.with_example(
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "statusview_curses.hh"
|
||||
|
||||
#include "base/ansi_scrubber.hh"
|
||||
#include "config.h"
|
||||
|
||||
void
|
||||
|
@ -56,15 +57,15 @@ status_field::do_cylon()
|
|||
{
|
||||
string_attrs_t& sa = this->sf_value.get_attrs();
|
||||
|
||||
remove_string_attr(sa, &view_curses::VC_STYLE);
|
||||
remove_string_attr(sa, &VC_STYLE);
|
||||
|
||||
struct line_range lr(this->sf_cylon_pos, this->sf_width);
|
||||
view_colors& vc = view_colors::singleton();
|
||||
|
||||
sa.emplace_back(
|
||||
lr,
|
||||
view_curses::VC_STYLE.value(
|
||||
vc.attrs_for_role(view_colors::VCR_ACTIVE_STATUS) | A_REVERSE));
|
||||
VC_STYLE.value(
|
||||
vc.attrs_for_role(role_t::VCR_ACTIVE_STATUS) | A_REVERSE));
|
||||
|
||||
this->sf_cylon_pos += 1;
|
||||
if (this->sf_cylon_pos > this->sf_width) {
|
||||
|
@ -73,18 +74,18 @@ status_field::do_cylon()
|
|||
}
|
||||
|
||||
void
|
||||
status_field::set_stitch_value(view_colors::role_t left,
|
||||
view_colors::role_t right)
|
||||
status_field::set_stitch_value(role_t left,
|
||||
role_t right)
|
||||
{
|
||||
string_attrs_t& sa = this->sf_value.get_attrs();
|
||||
struct line_range lr(0, 1);
|
||||
|
||||
this->sf_value.get_string() = "::";
|
||||
sa.clear();
|
||||
sa.emplace_back(lr, view_curses::VC_ROLE.value(left));
|
||||
sa.emplace_back(lr, VC_ROLE.value(left));
|
||||
lr.lr_start = 1;
|
||||
lr.lr_end = 2;
|
||||
sa.emplace_back(lr, view_curses::VC_ROLE.value(right));
|
||||
sa.emplace_back(lr, VC_ROLE.value(right));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -104,8 +105,8 @@ 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
|
||||
? view_colors::VCR_STATUS
|
||||
: view_colors::VCR_INACTIVE_STATUS);
|
||||
? role_t::VCR_STATUS
|
||||
: role_t::VCR_INACTIVE_STATUS);
|
||||
|
||||
wattron(this->sc_window, attrs);
|
||||
wmove(this->sc_window, top, 0);
|
||||
|
@ -125,16 +126,16 @@ statusview_curses::do_update()
|
|||
val = sf.get_value();
|
||||
if (!this->sc_enabled) {
|
||||
for (auto& sa : val.get_attrs()) {
|
||||
if (sa.sa_type == &view_curses::VC_STYLE) {
|
||||
if (sa.sa_type == &VC_STYLE) {
|
||||
sa.sa_value = sa.sa_value.get<int64_t>()
|
||||
& ~(A_REVERSE | A_COLOR);
|
||||
} else if (sa.sa_type == &view_curses::VC_ROLE) {
|
||||
if (sa.sa_value.get<int64_t>()
|
||||
== view_colors::VCR_ALERT_STATUS) {
|
||||
sa.sa_value.get<int64_t>()
|
||||
= view_colors::VCR_INACTIVE_ALERT_STATUS;
|
||||
} else if (sa.sa_type == &VC_ROLE) {
|
||||
if (sa.sa_value.get<role_t>()
|
||||
== role_t::VCR_ALERT_STATUS) {
|
||||
sa.sa_value.get<role_t>()
|
||||
= role_t::VCR_INACTIVE_ALERT_STATUS;
|
||||
} else {
|
||||
sa.sa_value = view_colors::VCR_NONE;
|
||||
sa.sa_value = role_t::VCR_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,10 +172,10 @@ statusview_curses::do_update()
|
|||
|
||||
auto default_role = sf.get_role();
|
||||
if (!this->sc_enabled) {
|
||||
if (default_role == view_colors::VCR_ALERT_STATUS) {
|
||||
default_role = view_colors::VCR_INACTIVE_ALERT_STATUS;
|
||||
if (default_role == role_t::VCR_ALERT_STATUS) {
|
||||
default_role = role_t::VCR_INACTIVE_ALERT_STATUS;
|
||||
} else {
|
||||
default_role = view_colors::VCR_INACTIVE_STATUS;
|
||||
default_role = role_t::VCR_INACTIVE_STATUS;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "ansi_scrubber.hh"
|
||||
#include "view_curses.hh"
|
||||
|
||||
/**
|
||||
|
@ -48,7 +47,7 @@ public:
|
|||
* @param role The color role for this field, defaults to VCR_STATUS.
|
||||
*/
|
||||
status_field(int width = 1,
|
||||
view_colors::role_t role = view_colors::VCR_STATUS)
|
||||
role_t role = role_t::VCR_STATUS)
|
||||
: sf_width(width), sf_role(role){};
|
||||
|
||||
virtual ~status_field() = default;
|
||||
|
@ -75,7 +74,7 @@ public:
|
|||
return *this;
|
||||
};
|
||||
|
||||
void set_stitch_value(view_colors::role_t left, view_colors::role_t right);
|
||||
void set_stitch_value(role_t left, role_t right);
|
||||
|
||||
void set_left_pad(size_t val)
|
||||
{
|
||||
|
@ -125,12 +124,12 @@ public:
|
|||
};
|
||||
|
||||
/** @param role The color role for this field. */
|
||||
void set_role(view_colors::role_t role)
|
||||
void set_role(role_t role)
|
||||
{
|
||||
this->sf_role = role;
|
||||
};
|
||||
/** @return The color role for this field. */
|
||||
view_colors::role_t get_role() const
|
||||
role_t get_role() const
|
||||
{
|
||||
return this->sf_role;
|
||||
};
|
||||
|
@ -173,7 +172,7 @@ protected:
|
|||
bool sf_cylon{false};
|
||||
ssize_t sf_cylon_pos{0};
|
||||
attr_line_t sf_value; /*< The value to display for this field. */
|
||||
view_colors::role_t sf_role; /*< The color role for this field. */
|
||||
role_t sf_role; /*< The color role for this field. */
|
||||
int sf_share{0};
|
||||
size_t sf_left_pad{0};
|
||||
};
|
||||
|
|
|
@ -443,6 +443,12 @@ sql_gzip(sqlite3_value* val)
|
|||
return nonstd::nullopt;
|
||||
}
|
||||
|
||||
std::string
|
||||
sql_humanize_file_size(file_ssize_t value)
|
||||
{
|
||||
return humanize::file_size(value, humanize::alignment::columnar);
|
||||
}
|
||||
|
||||
int
|
||||
string_extension_functions(struct FuncDef** basic_funcs,
|
||||
struct FuncDefAgg** agg_funcs)
|
||||
|
@ -511,8 +517,8 @@ string_extension_functions(struct FuncDef** basic_funcs,
|
|||
"SELECT regexp_replace('123 abc', '(\\w+)', '<\\1>')",
|
||||
})),
|
||||
|
||||
sqlite_func_adapter<decltype(&humanize::file_size),
|
||||
humanize::file_size>::
|
||||
sqlite_func_adapter<decltype(&sql_humanize_file_size),
|
||||
sql_humanize_file_size>::
|
||||
builder(help_text(
|
||||
"humanize_file_size",
|
||||
"Format the given file size as a human-friendly string")
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2020, Timothy Stack
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* * Neither the name of Timothy Stack nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* 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
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lnav_string_attr_type_hh
|
||||
#define lnav_string_attr_type_hh
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "base/intern_string.hh"
|
||||
#include "mapbox/variant.hpp"
|
||||
|
||||
class logfile;
|
||||
struct bookmark_metadata;
|
||||
|
||||
using string_attr_value = mapbox::util::variant<int64_t,
|
||||
const intern_string_t,
|
||||
std::string,
|
||||
std::shared_ptr<logfile>,
|
||||
bookmark_metadata*>;
|
||||
|
||||
class string_attr_type_base {
|
||||
public:
|
||||
explicit string_attr_type_base(const char* name) noexcept : sat_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
const char* const sat_name;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class string_attr_type : public string_attr_type_base {
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
explicit string_attr_type(const char* name) noexcept
|
||||
: string_attr_type_base(name)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename U = T>
|
||||
std::enable_if_t<!std::is_void<U>::value,
|
||||
std::pair<const string_attr_type_base*, string_attr_value>>
|
||||
value(const U& val) const
|
||||
{
|
||||
return std::make_pair(this, val);
|
||||
}
|
||||
|
||||
template<typename U = T>
|
||||
std::enable_if_t<std::is_void<U>::value,
|
||||
std::pair<const string_attr_type_base*, string_attr_value>>
|
||||
value() const
|
||||
{
|
||||
return std::make_pair(this, string_attr_value{});
|
||||
}
|
||||
};
|
||||
|
||||
extern string_attr_type<void> SA_ORIGINAL_LINE;
|
||||
extern string_attr_type<void> SA_BODY;
|
||||
extern string_attr_type<void> SA_HIDDEN;
|
||||
extern string_attr_type<const intern_string_t> SA_FORMAT;
|
||||
extern string_attr_type<void> SA_REMOVED;
|
||||
extern string_attr_type<std::string> SA_INVALID;
|
||||
extern string_attr_type<std::string> SA_ERROR;
|
||||
|
||||
#endif
|
|
@ -39,15 +39,15 @@
|
|||
#include "yajlpp/yajlpp_def.hh"
|
||||
|
||||
static const struct json_path_container term_color_rgb_handler = {
|
||||
yajlpp::property_handler("r").FOR_FIELD(rgb_color, rc_r),
|
||||
yajlpp::property_handler("g").FOR_FIELD(rgb_color, rc_g),
|
||||
yajlpp::property_handler("b").FOR_FIELD(rgb_color, rc_b),
|
||||
yajlpp::property_handler("r").for_field(&rgb_color::rc_r),
|
||||
yajlpp::property_handler("g").for_field(&rgb_color::rc_g),
|
||||
yajlpp::property_handler("b").for_field(&rgb_color::rc_b),
|
||||
};
|
||||
|
||||
static const struct json_path_container term_color_handler = {
|
||||
yajlpp::property_handler("colorId").FOR_FIELD(term_color, xc_id),
|
||||
yajlpp::property_handler("name").FOR_FIELD(term_color, xc_name),
|
||||
yajlpp::property_handler("hexString").FOR_FIELD(term_color, xc_hex),
|
||||
yajlpp::property_handler("colorId").for_field(&term_color::xc_id),
|
||||
yajlpp::property_handler("name").for_field(&term_color::xc_name),
|
||||
yajlpp::property_handler("hexString").for_field(&term_color::xc_hex),
|
||||
yajlpp::property_handler("rgb")
|
||||
.with_obj_provider<rgb_color, term_color>(
|
||||
[](const auto& pc, term_color* xc) { return &xc->xc_color; })
|
||||
|
|
|
@ -206,6 +206,7 @@ struct lnav_theme {
|
|||
style_config lt_style_inactive_status;
|
||||
style_config lt_style_inactive_alert_status;
|
||||
style_config lt_style_file;
|
||||
style_config lt_style_header[6];
|
||||
std::map<log_level_t, style_config> lt_level_styles;
|
||||
std::map<std::string, highlighter_config> lt_highlights;
|
||||
};
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "tailerpp.hh"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace tailer {
|
||||
|
||||
int
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue