[tidy] use factory_container for theme highlights

And... a bunch of other stuff
pull/1179/head
Tim Stack 10 months ago
parent d2d17ed7f0
commit b0589d14d9

@ -50,6 +50,8 @@ Bug Fixes:
as if it was in a file that was passed on the command-line.
* The `-I` option is now recognized in the management CLI
(i.e. when you run **lnav** with the `-m` flag).
* Fields in the bro and w3c log formats that were hidden are
now saved in the session and restored.
Interface changes:
* The DB view now uses the "alt-text" theme style to draw

@ -342,6 +342,14 @@ identifier(S str)
VC_ROLE.template value(role_t::VCR_IDENTIFIER));
}
template<typename S>
inline std::pair<S, string_attr_pair>
string(S str)
{
return std::make_pair(std::move(str),
VC_ROLE.template value(role_t::VCR_STRING));
}
template<typename S>
inline std::pair<S, string_attr_pair>
hr(S str)

@ -71,7 +71,7 @@ vt_create(sqlite3* db,
/* Allocate the sqlite3_vtab/vtab structure itself */
p_vt = (env_vtab*) sqlite3_malloc(sizeof(*p_vt));
if (p_vt == NULL) {
if (p_vt == nullptr) {
return SQLITE_NOMEM;
}
@ -126,11 +126,11 @@ vt_open(sqlite3_vtab* p_svt, sqlite3_vtab_cursor** pp_cursor)
{
env_vtab* p_vt = (env_vtab*) p_svt;
p_vt->base.zErrMsg = NULL;
p_vt->base.zErrMsg = nullptr;
env_vtab_cursor* p_cur = (env_vtab_cursor*) new env_vtab_cursor();
if (p_cur == NULL) {
if (p_cur == nullptr) {
return SQLITE_NOMEM;
} else {
*pp_cursor = (sqlite3_vtab_cursor*) p_cur;
@ -158,7 +158,7 @@ vt_eof(sqlite3_vtab_cursor* cur)
{
env_vtab_cursor* vc = (env_vtab_cursor*) cur;
return vc->env_cursor[0] == NULL;
return vc->env_cursor[0] == nullptr;
}
static int
@ -166,7 +166,7 @@ vt_next(sqlite3_vtab_cursor* cur)
{
env_vtab_cursor* vc = (env_vtab_cursor*) cur;
if (vc->env_cursor[0] != NULL) {
if (vc->env_cursor[0] != nullptr) {
vc->env_cursor += 1;
}
@ -309,11 +309,11 @@ static sqlite3_module vtab_module = {
vt_column, /* xColumn - read data */
vt_rowid, /* xRowid - read data */
vt_update, /* xUpdate - write data */
NULL, /* xBegin - begin transaction */
NULL, /* xSync - sync transaction */
NULL, /* xCommit - commit transaction */
NULL, /* xRollback - rollback transaction */
NULL, /* xFindFunction - function overloading */
nullptr, /* xBegin - begin transaction */
nullptr, /* xSync - sync transaction */
nullptr, /* xCommit - commit transaction */
nullptr, /* xRollback - rollback transaction */
nullptr, /* xFindFunction - function overloading */
};
int
@ -322,13 +322,13 @@ register_environ_vtab(sqlite3* db)
auto_mem<char, sqlite3_free> errmsg;
int rc;
rc = sqlite3_create_module(db, "environ_vtab_impl", &vtab_module, NULL);
rc = sqlite3_create_module(db, "environ_vtab_impl", &vtab_module, nullptr);
ensure(rc == SQLITE_OK);
if ((rc = sqlite3_exec(
db,
"CREATE VIRTUAL TABLE environ USING environ_vtab_impl()",
NULL,
NULL,
nullptr,
nullptr,
errmsg.out()))
!= SQLITE_OK)
{

@ -43,8 +43,6 @@
#include "yajlpp/json_op.hh"
#include "yajlpp/yajlpp.hh"
using namespace mapbox;
#define JSON_SUBTYPE 74 /* Ascii for "J" */
class sql_json_op : public json_op {
@ -68,7 +66,8 @@ null_or_default(sqlite3_context* context, int argc, sqlite3_value* argv[])
}
struct contains_userdata {
util::variant<string_fragment, sqlite3_int64, bool> cu_match_value{false};
mapbox::util::variant<string_fragment, sqlite3_int64, bool> cu_match_value{
false};
size_t cu_depth{0};
bool cu_result{false};
};
@ -119,12 +118,10 @@ json_contains(vtab_types::nullable<const char> nullable_json_in,
}
const auto* json_in = nullable_json_in.n_value;
auto_mem<yajl_handle_t> handle(yajl_free);
yajl_callbacks cb;
contains_userdata cu;
memset(&cb, 0, sizeof(cb));
handle = yajl_alloc(&cb, nullptr, &cu);
yajl_callbacks cb{};
contains_userdata cu;
auto handle = yajlpp::alloc_handle(&cb, &cu);
cb.yajl_start_array = +[](void* ctx) {
auto& cu = *((contains_userdata*) ctx);
@ -266,17 +263,16 @@ sql_jget(sqlite3_context* context, int argc, sqlite3_value** argv)
return;
}
const char* json_in = (const char*) sqlite3_value_text(argv[0]);
const auto json_in = from_sqlite<string_fragment>()(argc, argv, 0);
if (sqlite3_value_type(argv[1]) == SQLITE_NULL) {
sqlite3_result_text(context, json_in, -1, SQLITE_TRANSIENT);
sqlite3_result_text(context, json_in.data(), -1, SQLITE_TRANSIENT);
return;
}
const char* ptr_in = (const char*) sqlite3_value_text(argv[1]);
json_ptr jp(ptr_in);
sql_json_op jo(jp);
auto_mem<yajl_handle_t> handle(yajl_free);
unsigned char* err;
yajlpp_gen gen;
@ -289,16 +285,15 @@ sql_jget(sqlite3_context* context, int argc, sqlite3_value** argv)
jo.jo_ptr_callbacks.yajl_number = gen_handle_number;
jo.jo_ptr_data = gen.get_handle();
handle.reset(yajl_alloc(&json_op::ptr_callbacks, nullptr, &jo));
switch (yajl_parse(
handle.in(), (const unsigned char*) json_in, strlen(json_in)))
{
auto handle = yajlpp::alloc_handle(&json_op::ptr_callbacks, &jo);
switch (yajl_parse(handle.in(), json_in.udata(), json_in.length())) {
case yajl_status_error: {
err = yajl_get_error(handle.in(),
1,
(const unsigned char*) json_in,
strlen(json_in));
sqlite3_result_error(context, (const char*) err, -1);
err = yajl_get_error(
handle.in(), 1, json_in.udata(), json_in.length());
auto um = lnav::console::user_message::error("invalid JSON")
.with_reason((const char*) err);
to_sqlite(context, um);
yajl_free_error(handle.in(), err);
return;
}
@ -318,11 +313,12 @@ sql_jget(sqlite3_context* context, int argc, sqlite3_value** argv)
switch (yajl_complete_parse(handle.in())) {
case yajl_status_error: {
err = yajl_get_error(handle.in(),
1,
(const unsigned char*) json_in,
strlen(json_in));
sqlite3_result_error(context, (const char*) err, -1);
err = yajl_get_error(
handle.in(), 1, json_in.udata(), json_in.length());
auto um = lnav::console::user_message::error("invalid JSON")
.with_reason((const char*) err);
to_sqlite(context, um);
yajl_free_error(handle.in(), err);
return;
}
@ -342,10 +338,7 @@ sql_jget(sqlite3_context* context, int argc, sqlite3_value** argv)
switch (jo.sjo_type) {
case SQLITE3_TEXT:
sqlite3_result_text(context,
jo.sjo_str.c_str(),
jo.sjo_str.size(),
SQLITE_TRANSIENT);
to_sqlite(context, jo.sjo_str);
return;
case SQLITE_NULL:
sqlite3_result_null(context);
@ -358,7 +351,7 @@ sql_jget(sqlite3_context* context, int argc, sqlite3_value** argv)
return;
}
string_fragment result = gen.to_string_fragment();
const auto result = gen.to_string_fragment();
if (result.empty()) {
null_or_default(context, argc, argv);
@ -468,7 +461,6 @@ concat_gen_end_array(void* ctx)
static void
concat_gen_elements(yajl_gen gen, const unsigned char* text, size_t len)
{
auto_mem<yajl_handle_t> handle(yajl_free);
yajl_callbacks callbacks = {nullptr};
concat_context cc{gen};
@ -482,7 +474,7 @@ concat_gen_elements(yajl_gen gen, const unsigned char* text, size_t len)
callbacks.yajl_start_array = concat_gen_start_array;
callbacks.yajl_end_array = concat_gen_end_array;
handle = yajl_alloc(&callbacks, nullptr, &cc);
auto handle = yajlpp::alloc_handle(&callbacks, &cc);
yajl_config(handle, yajl_allow_comments, 1);
if (yajl_parse(handle, (const unsigned char*) text, len) != yajl_status_ok
|| yajl_complete_parse(handle) != yajl_status_ok)
@ -600,7 +592,7 @@ sql_json_group_object_step(sqlite3_context* context,
return;
}
json_agg_context* jac = (json_agg_context*) sqlite3_aggregate_context(
auto* jac = (json_agg_context*) sqlite3_aggregate_context(
context, sizeof(json_agg_context));
if (jac->jac_yajl_gen == nullptr) {
@ -662,8 +654,7 @@ sql_json_group_object_step(sqlite3_context* context,
static void
sql_json_group_object_final(sqlite3_context* context)
{
json_agg_context* jac
= (json_agg_context*) sqlite3_aggregate_context(context, 0);
auto* jac = (json_agg_context*) sqlite3_aggregate_context(context, 0);
if (jac == nullptr) {
sqlite3_result_text(context, "{}", -1, SQLITE_STATIC);
@ -686,7 +677,7 @@ sql_json_group_array_step(sqlite3_context* context,
int argc,
sqlite3_value** argv)
{
json_agg_context* jac = (json_agg_context*) sqlite3_aggregate_context(
auto* jac = (json_agg_context*) sqlite3_aggregate_context(
context, sizeof(json_agg_context));
if (jac->jac_yajl_gen == nullptr) {

@ -1924,29 +1924,7 @@ looper()
|| lnav_data.ld_text_source.text_line_count() > 0
|| !lnav_data.ld_active_files.fc_other_files.empty()))
{
log_debug("restoring view states");
for (size_t view_index = 0; view_index < LNV__MAX;
view_index++)
{
const auto& vs
= session_data.sd_view_states[view_index];
auto& tview = lnav_data.ld_views[view_index];
if (vs.vs_top >= 0
&& (view_index == LNV_LOG
|| tview.get_top() == 0_vl))
{
log_info("restoring %s view top: %d",
lnav_view_strings[view_index],
vs.vs_top);
lnav_data.ld_views[view_index].set_top(
vis_line_t(vs.vs_top));
if (vs.vs_selection) {
lnav_data.ld_views[view_index].set_selection(
vis_line_t(vs.vs_selection.value()));
}
}
}
lnav::session::restore_view_states();
if (lnav_data.ld_mode == ln_mode_t::FILES) {
if (lnav_data.ld_active_files.fc_name_to_errors.empty())
{

@ -918,15 +918,14 @@ json_write_row(yajl_gen handle,
case SQLITE_TEXT:
switch (hm.hm_sub_type) {
case 74: {
auto_mem<yajl_handle_t> parse_handle(yajl_free);
unsigned char* err;
json_ptr jp("");
json_op jo(jp);
jo.jo_ptr_callbacks = json_op::gen_callbacks;
jo.jo_ptr_data = handle;
parse_handle.reset(
yajl_alloc(&json_op::ptr_callbacks, nullptr, &jo));
auto parse_handle = yajlpp::alloc_handle(
&json_op::ptr_callbacks, &jo);
const unsigned char* json_in
= (const unsigned char*) dls.dls_rows[row][col];
@ -3770,6 +3769,7 @@ com_load_session(exec_context& ec,
if (args.empty()) {
} else if (!ec.ec_dry_run) {
load_session();
lnav::session::restore_view_states();
lnav_data.ld_views[LNV_LOG].reload_data();
}

@ -1348,10 +1348,10 @@ read_id(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
}
ypc->report_error(
lnav::console::user_message::error(
attr_line_t("'")
.append(lnav::roles::symbol(file_id))
attr_line_t()
.append_quoted(lnav::roles::symbol(file_id))
.append(
"' is not a supported configuration $schema version"))
" is not a supported configuration $schema version"))
.with_snippet(ypc->get_snippet())
.with_note(notes)
.with_help(handler->get_help_text(ypc)));
@ -1458,11 +1458,10 @@ load_config_from(_lnav_config& lconfig,
.with_errno_reason());
}
} else {
auto_mem<yajl_handle_t> handle(yajl_free);
char buffer[2048];
ssize_t rc = -1;
handle = yajl_alloc(&ypc.ypc_callbacks, nullptr, &ypc);
auto handle = yajlpp::alloc_handle(&ypc.ypc_callbacks, &ypc);
yajl_config(handle, yajl_allow_comments, 1);
yajl_config(handle, yajl_allow_multiple_values, 1);
ypc.ypc_handle = handle;
@ -1498,10 +1497,10 @@ load_default_config(struct _lnav_config& config_obj,
{
yajlpp_parse_context ypc_builtin(intern_string::lookup(bsf.get_name()),
&lnav_config_handlers);
auto_mem<yajl_handle_t> handle(yajl_free);
struct config_userdata ud(errors);
handle = yajl_alloc(&ypc_builtin.ypc_callbacks, nullptr, &ypc_builtin);
auto handle
= yajlpp::alloc_handle(&ypc_builtin.ypc_callbacks, &ypc_builtin);
ypc_builtin.ypc_locations = &lnav_config_locations;
ypc_builtin.with_handle(handle);
ypc_builtin.with_obj(config_obj);
@ -1515,9 +1514,7 @@ load_default_config(struct _lnav_config& config_obj,
yajl_config(handle, yajl_allow_comments, 1);
yajl_config(handle, yajl_allow_multiple_values, 1);
if (ypc_builtin.parse(bsf.to_string_fragment()) == yajl_status_ok) {
ypc_builtin.complete_parse();
}
ypc_builtin.parse_doc(bsf.to_string_fragment());
return path == "*" || ypc_builtin.ypc_active_paths.empty();
}

@ -280,7 +280,7 @@ next_format(
}
bool
log_format::next_format(pcre_format* fmt, int& index, int& locked_index)
log_format::next_format(const pcre_format* fmt, int& index, int& locked_index)
{
bool retval = true;
@ -301,7 +301,7 @@ log_format::next_format(pcre_format* fmt, int& index, int& locked_index)
const char*
log_format::log_scanf(uint32_t line_number,
string_fragment line,
pcre_format* fmt,
const pcre_format* fmt,
const char* time_fmt[],
struct exttm* tm_out,
struct timeval* tv_out,

@ -450,6 +450,11 @@ public:
return false;
}
virtual std::map<intern_string_t, logline_value_meta> get_field_states()
{
return {};
}
const char* const* get_timestamp_formats() const
{
if (this->lf_timestamp_format.empty()) {
@ -555,11 +560,13 @@ protected:
int pf_timestamp_index{-1};
};
static bool next_format(pcre_format* fmt, int& index, int& locked_index);
static bool next_format(const pcre_format* fmt,
int& index,
int& locked_index);
const char* log_scanf(uint32_t line_number,
string_fragment line,
pcre_format* fmt,
const pcre_format* fmt,
const char* time_fmt[],
struct exttm* tm_out,
struct timeval* tv_out,

@ -169,6 +169,17 @@ public:
bool hide_field(const intern_string_t field_name, bool val) override;
std::map<intern_string_t, logline_value_meta> get_field_states() override
{
std::map<intern_string_t, logline_value_meta> retval;
for (const auto& vd : this->elf_value_defs) {
retval.emplace(vd.first, vd.second->vd_meta);
}
return retval;
}
std::shared_ptr<log_format> specialized(int fmt_lock) override;
const logline_value_stats* stats_for_value(

@ -41,13 +41,14 @@
#include "config.h"
#include "formats/logfmt/logfmt.parser.hh"
#include "log_vtab_impl.hh"
#include "scn/scn.h"
#include "sql_util.hh"
#include "yajlpp/yajlpp.hh"
class generic_log_format : public log_format {
static pcre_format* get_pcre_log_formats()
static const pcre_format* get_pcre_log_formats()
{
static pcre_format log_fmt[] = {
static const pcre_format log_fmt[] = {
pcre_format(
"^(?:\\*\\*\\*\\s+)?(?<timestamp>@[0-9a-zA-Z]{16,24})(.*)"),
pcre_format(
@ -88,7 +89,10 @@ class generic_log_format : public log_format {
const intern_string_t get_name() const override
{
return intern_string::lookup("generic_log");
static const intern_string_t RETVAL
= intern_string::lookup("generic_log");
return RETVAL;
}
scan_result_t scan(logfile& lf,
@ -140,7 +144,7 @@ class generic_log_format : public log_format {
{
auto& line = values.lvv_sbr;
int pat_index = this->pattern_index_for_line(line_number);
auto& fmt = get_pcre_log_formats()[pat_index];
const auto& fmt = get_pcre_log_formats()[pat_index];
int prefix_len = 0;
auto md = fmt.pcre->create_match_data();
auto match_res = fmt.pcre->capture_from(line.to_string_fragment())
@ -324,13 +328,15 @@ class bro_log_format : public log_format {
public:
struct field_def {
logline_value_meta fd_meta;
logline_value_meta* fd_root_meta;
std::string fd_collator;
nonstd::optional<size_t> fd_numeric_index;
explicit field_def(const intern_string_t name,
int col,
log_format* format)
: fd_meta(name, value_kind_t::VALUE_TEXT, col, format)
: fd_meta(name, value_kind_t::VALUE_TEXT, col, format),
fd_root_meta(&FIELD_META.find(name)->second)
{
}
@ -351,6 +357,9 @@ public:
}
};
static std::unordered_map<const intern_string_t, logline_value_meta>
FIELD_META;
bro_log_format()
{
this->lf_is_self_describing = true;
@ -410,13 +419,13 @@ public:
found_ts = true;
}
} else if (STATUS_CODE == fd.fd_meta.lvm_name) {
string_fragment sf = *iter;
const auto sf = *iter;
if (!sf.empty() && sf[0] >= '4') {
level = LEVEL_ERROR;
}
} else if (UID == fd.fd_meta.lvm_name) {
string_fragment sf = *iter;
const auto sf = *iter;
opid = hash_str(sf.data(), sf.length());
}
@ -425,14 +434,11 @@ public:
switch (fd.fd_meta.lvm_kind) {
case value_kind_t::VALUE_INTEGER:
case value_kind_t::VALUE_FLOAT: {
string_fragment sf = *iter;
char field_copy[sf.length() + 1];
double val;
if (sscanf(sf.to_string(field_copy), "%lf", &val) == 1)
{
const auto sv = (*iter).to_string_view();
auto scan_float_res = scn::scan_value<double>(sv);
if (scan_float_res) {
this->lf_value_stats[fd.fd_numeric_index.value()]
.add_value(val);
.add_value(scan_float_res.value());
}
break;
}
@ -531,10 +537,18 @@ public:
this->blf_format_name = intern_string::lookup(full_name);
} else if (directive == "#fields" && this->blf_field_defs.empty()) {
do {
auto field_name
= intern_string::lookup("bro_" + sql_safe_ident(*iter));
auto common_iter = FIELD_META.find(field_name);
if (common_iter == FIELD_META.end()) {
FIELD_META.emplace(field_name,
logline_value_meta{
field_name,
value_kind_t::VALUE_TEXT,
});
}
this->blf_field_defs.emplace_back(
intern_string::lookup("bro_" + sql_safe_ident(*iter)),
this->blf_field_defs.size(),
this);
field_name, this->blf_field_defs.size(), this);
++iter;
} while (iter != ss.end());
} else if (directive == "#types") {
@ -651,6 +665,8 @@ public:
} else {
values.lvv_values.emplace_back(fd.fd_meta);
}
values.lvv_values.back().lv_meta.lvm_user_hidden
= fd.fd_root_meta->lvm_user_hidden;
}
}
@ -675,20 +691,27 @@ public:
bool hide_field(const intern_string_t field_name, bool val) override
{
auto fd_iter
= std::find_if(this->blf_field_defs.begin(),
this->blf_field_defs.end(),
[field_name](const field_def& elem) {
return elem.fd_meta.lvm_name == field_name;
});
if (fd_iter == this->blf_field_defs.end()) {
auto fd_iter = FIELD_META.find(field_name);
if (fd_iter == FIELD_META.end()) {
return false;
}
fd_iter->fd_meta.lvm_user_hidden = val;
fd_iter->second.lvm_user_hidden = val;
return true;
}
std::map<intern_string_t, logline_value_meta> get_field_states() override
{
std::map<intern_string_t, logline_value_meta> retval;
for (const auto& fd : FIELD_META) {
retval.emplace(fd.first, fd.second);
}
return retval;
}
std::shared_ptr<log_format> specialized(int fmt_lock = -1) override
{
auto retval = std::make_shared<bro_log_format>(*this);
@ -707,9 +730,8 @@ public:
void get_columns(std::vector<vtab_column>& cols) const override
{
for (const auto& fd : this->blt_format.blf_field_defs) {
std::pair<int, unsigned int> type_pair
= log_vtab_impl::logline_value_to_sqlite_type(
fd.fd_meta.lvm_kind);
auto type_pair = log_vtab_impl::logline_value_to_sqlite_type(
fd.fd_meta.lvm_kind);
cols.emplace_back(fd.fd_meta.lvm_name.to_string(),
type_pair.first,
@ -775,6 +797,9 @@ public:
std::vector<field_def> blf_field_defs;
};
std::unordered_map<const intern_string_t, logline_value_meta>
bro_log_format::FIELD_META;
struct ws_separated_string {
const char* ss_str;
size_t ss_len;
@ -877,6 +902,7 @@ public:
struct field_def {
const intern_string_t fd_name;
logline_value_meta fd_meta;
logline_value_meta* fd_root_meta{nullptr};
std::string fd_collator;
nonstd::optional<size_t> fd_numeric_index;
@ -924,6 +950,9 @@ public:
}
};
static std::unordered_map<const intern_string_t, logline_value_meta>
FIELD_META;
struct field_to_struct_t {
field_to_struct_t(const char* prefix, const char* struct_name)
: fs_prefix(prefix),
@ -990,7 +1019,7 @@ public:
break;
}
const field_def& fd = this->wlf_field_defs[iter.index()];
const auto& fd = this->wlf_field_defs[iter.index()];
string_fragment sf = *iter;
if (sf.startswith("#")) {
@ -1051,13 +1080,12 @@ public:
switch (fd.fd_meta.lvm_kind) {
case value_kind_t::VALUE_INTEGER:
case value_kind_t::VALUE_FLOAT: {
char field_copy[sf.length() + 1];
double val;
auto scan_float_res
= scn::scan_value<double>(sf.to_string_view());
if (sscanf(sf.to_string(field_copy), "%lf", &val) == 1)
{
if (scan_float_res) {
this->lf_value_stats[fd.fd_numeric_index.value()]
.add_value(val);
.add_value(scan_float_res.value());
}
break;
}
@ -1131,8 +1159,7 @@ public:
auto line = next_read_result.unwrap();
ws_separated_string ss(line.get_data(), line.length());
auto iter = ss.begin();
string_fragment directive = *iter;
const auto directive = *iter;
if (directive.empty() || directive[0] != '#') {
continue;
@ -1170,9 +1197,25 @@ public:
[&sf](auto elem) { return sf == elem.fd_name; });
if (field_iter != end(KNOWN_FIELDS)) {
this->wlf_field_defs.emplace_back(*field_iter);
auto& fd = this->wlf_field_defs.back();
auto common_iter = FIELD_META.find(fd.fd_meta.lvm_name);
if (common_iter == FIELD_META.end()) {
auto emp_res = FIELD_META.emplace(
fd.fd_meta.lvm_name, fd.fd_meta);
common_iter = emp_res.first;
}
fd.fd_root_meta = &common_iter->second;
} else if (sf == "date" || sf == "time") {
this->wlf_field_defs.emplace_back(
intern_string::lookup(sf));
auto& fd = this->wlf_field_defs.back();
auto common_iter = FIELD_META.find(fd.fd_meta.lvm_name);
if (common_iter == FIELD_META.end()) {
auto emp_res = FIELD_META.emplace(
fd.fd_meta.lvm_name, fd.fd_meta);
common_iter = emp_res.first;
}
fd.fd_root_meta = &common_iter->second;
} else {
const auto fs_iter = std::find_if(
begin(KNOWN_STRUCT_FIELDS),
@ -1181,7 +1224,7 @@ public:
return sf.startswith(elem.fs_prefix);
});
if (fs_iter != end(KNOWN_STRUCT_FIELDS)) {
auto field_name
const intern_string_t field_name
= intern_string::lookup(sf.substr(3));
this->wlf_field_defs.emplace_back(
field_name,
@ -1195,7 +1238,8 @@ public:
this)
.with_struct_name(fs_iter->fs_struct_name));
} else {
auto field_name = intern_string::lookup(sf);
const intern_string_t field_name
= intern_string::lookup(sf);
this->wlf_field_defs.emplace_back(
field_name,
logline_value_meta(
@ -1253,7 +1297,7 @@ public:
return;
}
const field_def& fd = this->wlf_field_defs[iter.index()];
const auto& fd = this->wlf_field_defs[iter.index()];
if (sf == "-") {
sf.invalidate();
@ -1275,6 +1319,10 @@ public:
} else {
values.lvv_values.emplace_back(fd.fd_meta);
}
if (fd.fd_root_meta != nullptr) {
values.lvv_values.back().lv_meta.lvm_user_hidden
= fd.fd_root_meta->lvm_user_hidden;
}
}
}
@ -1299,20 +1347,27 @@ public:
bool hide_field(const intern_string_t field_name, bool val) override
{
auto fd_iter
= std::find_if(this->wlf_field_defs.begin(),
this->wlf_field_defs.end(),
[field_name](const field_def& elem) {
return elem.fd_meta.lvm_name == field_name;
});
if (fd_iter == this->wlf_field_defs.end()) {
auto fd_iter = FIELD_META.find(field_name);
if (fd_iter == FIELD_META.end()) {
return false;
}
fd_iter->fd_meta.lvm_user_hidden = val;
fd_iter->second.lvm_user_hidden = val;
return true;
}
std::map<intern_string_t, logline_value_meta> get_field_states() override
{
std::map<intern_string_t, logline_value_meta> retval;
for (const auto& fd : FIELD_META) {
retval.emplace(fd.first, fd.second);
}
return retval;
}
std::shared_ptr<log_format> specialized(int fmt_lock = -1) override
{
auto retval = std::make_shared<w3c_log_format>(*this);
@ -1402,6 +1457,9 @@ public:
std::vector<field_def> wlf_field_defs;
};
std::unordered_map<const intern_string_t, logline_value_meta>
w3c_log_format::FIELD_META;
static int KNOWN_FIELD_INDEX = 0;
const std::vector<w3c_log_format::field_def> w3c_log_format::KNOWN_FIELDS = {
{
@ -1551,7 +1609,7 @@ class logfmt_format : public log_format {
public:
const intern_string_t get_name() const override
{
const static auto NAME = intern_string::lookup("logfmt_log");
const static intern_string_t NAME = intern_string::lookup("logfmt_log");
return NAME;
}

@ -918,7 +918,7 @@ const struct json_path_container format_handlers = {
.with_description("A URL with more information about this log format"),
json_path_handler("title", read_format_field)
.with_description("The human-readable name for this log format"),
json_path_handler("description", read_format_field)
json_path_handler("description")
.with_description("A longer description of this log format")
.for_field(&external_log_format::lf_description),
json_path_handler("timestamp-format#", read_format_field)
@ -926,7 +926,7 @@ const struct json_path_container format_handlers = {
json_path_handler("module-field", read_format_field)
.with_description(
"The name of the module field in the log message pattern"),
json_path_handler("opid-field", read_format_field)
json_path_handler("opid-field")
.with_description(
"The name of the operation-id field in the log message pattern")
.for_field(&external_log_format::elf_opid_field),

@ -1918,7 +1918,8 @@ vt_update(sqlite3_vtab* tab,
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 auto* log_tags = sqlite3_value_text(argv[2 + VT_COL_LOG_TAGS]);
const auto log_tags = from_sqlite<nonstd::optional<string_fragment>>()(
argc, argv, 2 + VT_COL_LOG_TAGS);
bookmark_metadata tmp_bm;
if (log_tags) {
@ -1937,7 +1938,7 @@ vt_update(sqlite3_vtab* tab,
errors.emplace_back(msg);
})
.with_obj(tmp_bm);
ypc.parse_doc(string_fragment{log_tags});
ypc.parse_doc(log_tags.value());
if (!errors.empty()) {
auto top_error = lnav::console::user_message::error(
attr_line_t("invalid value for ")
@ -1946,16 +1947,14 @@ vt_update(sqlite3_vtab* tab,
.append_quoted(lnav::roles::symbol(
vt->vi->get_name().to_string())))
.with_reason(errors[0].to_attr_line({}));
auto json_error = lnav::to_json(top_error);
tab->zErrMsg
= sqlite3_mprintf("lnav-error:%s", json_error.c_str());
set_vtable_errmsg(tab, top_error);
return SQLITE_ERROR;
}
}
auto& bv = vt->tc->get_bookmarks()[&textview_curses::BM_META];
bool has_meta = part_name != nullptr || log_comment != nullptr
|| log_tags != nullptr;
|| log_tags.has_value();
if (binary_search(bv.begin(), bv.end(), vrowid) && !has_meta) {
vt->tc->set_user_mark(&textview_curses::BM_META, vrowid, false);

@ -259,6 +259,8 @@ public:
const std::string& get_pattern() const { return this->p_pattern; }
std::string to_string() const { return this->p_pattern; }
named_captures get_named_captures() const;
const char* get_name_for_capture(size_t index) const;

@ -504,7 +504,7 @@ add_recent_netlocs_possibilities()
isc::to<tailer::looper&, services::remote_tailer_t>().send_and_wait(
[&netlocs](auto& tlooper) { netlocs = tlooper.active_netlocs(); });
netlocs.insert(session_data.sd_recent_netlocs.begin(),
session_data.sd_recent_netlocs.end());
netlocs.insert(recent_refs.rr_netlocs.begin(),
recent_refs.rr_netlocs.end());
rc->add_possibility(ln_mode_t::COMMAND, "recent-netlocs", netlocs);
}

@ -31,6 +31,7 @@
# include <alloca.h>
#endif
#include "base/lnav.console.into.hh"
#include "base/lnav_log.hh"
#include "column_namer.hh"
#include "config.h"
@ -238,9 +239,12 @@ rcFilter(sqlite3_vtab_cursor* pVtabCursor,
auto pattern = from_sqlite<string_fragment>()(argc, argv, 1);
auto compile_res = lnav::pcre2pp::code::from(pattern);
if (compile_res.isErr()) {
pVtabCursor->pVtab->zErrMsg
= sqlite3_mprintf("Invalid regular expression: %s",
compile_res.unwrapErr().get_message().c_str());
static const intern_string_t PATTERN_SRC
= intern_string::lookup("pattern");
set_vtable_errmsg(pVtabCursor->pVtab,
lnav::console::to_user_message(
PATTERN_SRC, compile_res.unwrapErr()));
return SQLITE_ERROR;
}
@ -486,9 +490,12 @@ rcjFilter(sqlite3_vtab_cursor* pVtabCursor,
auto pattern = from_sqlite<string_fragment>()(argc, argv, 1);
auto compile_res = lnav::pcre2pp::code::from(pattern);
if (compile_res.isErr()) {
pVtabCursor->pVtab->zErrMsg
= sqlite3_mprintf("Invalid regular expression: %s",
compile_res.unwrapErr().get_message().c_str());
static const intern_string_t PATTERN_SRC
= intern_string::lookup("pattern");
set_vtable_errmsg(pVtabCursor->pVtab,
lnav::console::to_user_message(
PATTERN_SRC, compile_res.unwrapErr()));
return SQLITE_ERROR;
}
@ -508,8 +515,7 @@ rcjFilter(sqlite3_vtab_cursor* pVtabCursor,
"unable to parse flags")
.with_reason(parse_res.unwrapErr()[0]);
pVtabCursor->pVtab->zErrMsg = sqlite3_mprintf(
"%s%s", sqlitepp::ERROR_PREFIX, lnav::to_json(um).c_str());
set_vtable_errmsg(pVtabCursor->pVtab, um);
return SQLITE_ERROR;
}

@ -49,7 +49,6 @@
#include "hasher.hh"
#include "lnav.events.hh"
#include "lnav.hh"
#include "lnav_util.hh"
#include "log_format_ext.hh"
#include "logfile.hh"
#include "service_tags.hh"
@ -60,7 +59,8 @@
#include "yajlpp/yajlpp.hh"
#include "yajlpp/yajlpp_def.hh"
struct session_data_t session_data;
session_data_t session_data;
recent_refs_t recent_refs;
static const char* LOG_METADATA_NAME = "log_metadata.db";
@ -413,7 +413,7 @@ load_time_bookmarks()
while (!done) {
done = netloc_stmt.fetch_row<std::string>().match(
[](const std::string& netloc) {
session_data.sd_recent_netlocs.insert(netloc);
recent_refs.rr_netlocs.insert(netloc);
return false;
},
[](const prepared_stmt::fetch_error& fe) {
@ -472,7 +472,6 @@ load_time_bookmarks()
date_time_scanner dts;
bool done = false;
std::string line;
int64_t last_mark_time = -1;
while (!done) {
@ -510,8 +509,11 @@ load_time_bookmarks()
continue;
}
if (!dts.scan(
log_time, strlen(log_time), NULL, &log_tm, log_tv))
if (!dts.scan(log_time,
strlen(log_time),
nullptr,
&log_tm,
log_tv))
{
continue;
}
@ -762,136 +764,32 @@ read_files(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
return 1;
}
static int
read_current_search(yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len)
{
const auto regex = std::string((const char*) str, len);
const char** view_name;
int view_index;
view_name = find(lnav_view_strings,
lnav_view_strings + LNV__MAX,
ypc->get_path_fragment(-2));
view_index = view_name - lnav_view_strings;
if (view_index < LNV__MAX && !regex.empty()) {
lnav_data.ld_views[view_index].execute_search(regex);
lnav_data.ld_views[view_index].set_follow_search_for(-1, {});
}
return 1;
}
static int
read_top_line(yajlpp_parse_context* ypc, long long value)
{
const char** view_name;
int view_index;
view_name = find(lnav_view_strings,
lnav_view_strings + LNV__MAX,
ypc->get_path_fragment(-2));
view_index = view_name - lnav_view_strings;
if (view_index < LNV__MAX) {
session_data.sd_view_states[view_index].vs_top = value;
}
return 1;
}
static int
read_focused_line(yajlpp_parse_context* ypc, long long value)
{
const char** view_name;
int view_index;
view_name = find(lnav_view_strings,
lnav_view_strings + LNV__MAX,
ypc->get_path_fragment(-2));
view_index = view_name - lnav_view_strings;
if (view_index < LNV__MAX) {
session_data.sd_view_states[view_index].vs_selection = value;
}
return 1;
}
static int
read_word_wrap(yajlpp_parse_context* ypc, int value)
{
const char** view_name;
int view_index;
view_name = find(lnav_view_strings,
lnav_view_strings + LNV__MAX,
ypc->get_path_fragment(-2));
view_index = view_name - lnav_view_strings;
if (view_index == LNV_HELP) {
} else if (view_index < LNV__MAX) {
textview_curses& tc = lnav_data.ld_views[view_index];
tc.set_word_wrap(value);
}
return 1;
}
static int
read_filtering(yajlpp_parse_context* ypc, int value)
{
const char** view_name;
int view_index;
view_name = find(lnav_view_strings,
lnav_view_strings + LNV__MAX,
ypc->get_path_fragment(-2));
view_index = view_name - lnav_view_strings;
if (view_index == LNV_HELP) {
} else if (view_index < LNV__MAX) {
textview_curses& tc = lnav_data.ld_views[view_index];
if (tc.get_sub_source() != nullptr) {
tc.get_sub_source()->tss_apply_filters = value;
}
}
return 1;
}
static int
read_commands(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
{
std::string cmdline = std::string((const char*) str, len);
const char** view_name;
int view_index;
view_name = find(lnav_view_strings,
lnav_view_strings + LNV__MAX,
ypc->get_path_fragment(-3));
view_index = view_name - lnav_view_strings;
bool active = ensure_view(&lnav_data.ld_views[view_index]);
execute_command(lnav_data.ld_exec_context, cmdline);
if (!active) {
lnav_data.ld_view_stack.pop_back();
}
return 1;
}
static const struct json_path_container view_def_handlers = {
json_path_handler("top_line", read_top_line),
json_path_handler("focused_line", read_focused_line),
json_path_handler("search", read_current_search),
json_path_handler("word_wrap", read_word_wrap),
json_path_handler("filtering", read_filtering),
json_path_handler("commands#", read_commands),
json_path_handler("top_line").for_field(&view_state::vs_top),
json_path_handler("focused_line").for_field(&view_state::vs_selection),
json_path_handler("search").for_field(&view_state::vs_search),
json_path_handler("word_wrap").for_field(&view_state::vs_word_wrap),
json_path_handler("filtering").for_field(&view_state::vs_filtering),
json_path_handler("commands#").for_field(&view_state::vs_commands),
};
static const struct json_path_container view_handlers = {
yajlpp::pattern_property_handler("([^/]+)").with_children(
view_def_handlers),
yajlpp::pattern_property_handler("(?<view_name>[\\w\\-]+)")
.with_obj_provider<view_state, session_data_t>(
+[](const yajlpp_provider_context& ypc, session_data_t* root) {
const char** view_name;
int view_index;
view_name = find(lnav_view_strings,
lnav_view_strings + LNV__MAX,
ypc.get_substr("view_name"));
view_index = view_name - lnav_view_strings;
if (view_index < LNV__MAX) {
return &root->sd_view_states[view_index];
}
return (view_state*) nullptr;
})
.with_children(view_def_handlers),
};
static const struct json_path_container file_state_handlers = {
@ -903,14 +801,15 @@ static const struct json_path_container file_state_handlers = {
static const struct json_path_container file_states_handlers = {
yajlpp::pattern_property_handler(R"((?<filename>[^/]+))")
.with_description("Map of file names to file state objects")
.with_obj_provider<file_state, void>([](const auto& ypc, auto* root) {
auto fn = ypc.get_substr("filename");
return &session_data.sd_file_states[fn];
})
.with_obj_provider<file_state, session_data_t>(
[](const auto& ypc, session_data_t* root) {
auto fn = ypc.get_substr("filename");
return &root->sd_file_states[fn];
})
.with_children(file_state_handlers),
};
static const struct json_path_container view_info_handlers = {
static const typed_json_path_container<session_data_t> view_info_handlers = {
yajlpp::property_handler("save-time")
.for_field(&session_data_t::sd_save_time),
yajlpp::property_handler("time-offset")
@ -925,33 +824,51 @@ load_session()
{
load_time_bookmarks();
scan_sessions() | [](const auto pair) {
yajl_handle handle;
auto_fd fd;
lnav_data.ld_session_load_time = pair.first.second;
session_data.sd_save_time = pair.first.second;
const auto& view_info_path = pair.second;
yajlpp_parse_context ypc(intern_string::lookup(view_info_path.string()),
&view_info_handlers);
ypc.with_obj(session_data);
handle = yajl_alloc(&ypc.ypc_callbacks, nullptr, &ypc);
auto view_info_src = intern_string::lookup(view_info_path.string());
load_time_bookmarks();
if ((fd = lnav::filesystem::openp(view_info_path, O_RDONLY)) < 0) {
perror("cannot open session file");
} else {
unsigned char buffer[1024];
ssize_t rc;
auto open_res = lnav::filesystem::open_file(view_info_path, O_RDONLY);
if (open_res.isErr()) {
log_error("cannot open session file: %s -- %s",
view_info_path.c_str(),
open_res.unwrapErr().c_str());
return;
}
log_info("loading session file: %s", view_info_path.c_str());
while ((rc = read(fd, buffer, sizeof(buffer))) > 0) {
yajl_parse(handle, buffer, rc);
auto fd = open_res.unwrap();
unsigned char buffer[1024];
ssize_t rc;
log_info("loading session file: %s", view_info_path.c_str());
auto parser = view_info_handlers.parser_for(view_info_src);
while ((rc = read(fd, buffer, sizeof(buffer))) > 0) {
auto buf_frag = string_fragment::from_bytes(buffer, rc);
auto parse_res = parser.consume(buf_frag);
if (parse_res.isErr()) {
log_error("failed to load session: %s -- %s",
view_info_path.c_str(),
parse_res.unwrapErr()[0]
.to_attr_line()
.get_string()
.c_str());
return;
}
yajl_complete_parse(handle);
}
yajl_free(handle);
auto complete_res = parser.complete();
if (complete_res.isErr()) {
log_error("failed to load session: %s -- %s",
view_info_path.c_str(),
complete_res.unwrapErr()[0]
.to_attr_line()
.get_string()
.c_str());
return;
}
session_data = complete_res.unwrap();
bool log_changes = false, text_changes = false;
@ -1143,7 +1060,7 @@ save_time_bookmarks()
sqlite3_reset(stmt.in());
}
session_data.sd_recent_netlocs.insert(netlocs.begin(), netlocs.end());
recent_refs.rr_netlocs.insert(netlocs.begin(), netlocs.end());
}
logfile_sub_source& lss = lnav_data.ld_log_source;
@ -1470,7 +1387,7 @@ save_session_with_id(const std::string& session_id)
yajlpp_map top_view_map(handle);
for (int lpc = 0; lpc < LNV__MAX; lpc++) {
textview_curses& tc = lnav_data.ld_views[lpc];
auto& tc = lnav_data.ld_views[lpc];
unsigned long width;
vis_line_t height;
@ -1541,32 +1458,28 @@ save_session_with_id(const std::string& session_id)
for (const auto& format :
log_format::get_root_formats())
{
auto* elf = dynamic_cast<external_log_format*>(
format.get());
if (elf == nullptr) {
continue;
}
auto field_states = format->get_field_states();
for (const auto& vd : elf->elf_value_defs) {
if (!vd.second->vd_meta.lvm_user_hidden) {
for (const auto& fs_pair : field_states) {
if (!fs_pair.second.lvm_user_hidden) {
continue;
}
if (vd.second->vd_meta.lvm_user_hidden.value())
{
cmd_array.gen("hide-fields "
+ elf->get_name().to_string()
+ "." + vd.first.to_string());
} else if (vd.second->vd_meta.lvm_hidden) {
cmd_array.gen("show-fields "
+ elf->get_name().to_string()
+ "." + vd.first.to_string());
if (fs_pair.second.lvm_user_hidden.value()) {
cmd_array.gen(
"hide-fields "
+ format->get_name().to_string() + "."
+ fs_pair.first.to_string());
} else if (fs_pair.second.lvm_hidden) {
cmd_array.gen(
"show-fields "
+ format->get_name().to_string() + "."
+ fs_pair.first.to_string());
}
}
}
logfile_sub_source& lss = lnav_data.ld_log_source;
auto& lss = lnav_data.ld_log_source;
struct timeval min_time, max_time;
bool have_min_time = lss.get_min_log_time(min_time);
@ -1701,6 +1614,49 @@ reset_session()
}
}
void
lnav::session::restore_view_states()
{
log_debug("restoring view states");
for (size_t view_index = 0; view_index < LNV__MAX; view_index++) {
const auto& vs = session_data.sd_view_states[view_index];
auto& tview = lnav_data.ld_views[view_index];
if (vs.vs_top >= 0
&& (view_index == LNV_LOG || tview.get_top() == 0_vl
|| tview.get_top() == tview.get_top_for_last_row()))
{
log_info("restoring %s view top: %d",
lnav_view_strings[view_index],
vs.vs_top);
lnav_data.ld_views[view_index].set_top(vis_line_t(vs.vs_top));
}
if (vs.vs_selection) {
log_info("restoring %s view selection: %d",
lnav_view_strings[view_index],
vs.vs_selection.value());
lnav_data.ld_views[view_index].set_selection(
vis_line_t(vs.vs_selection.value()));
}
if (!vs.vs_search.empty()) {
tview.execute_search(vs.vs_search);
tview.set_follow_search_for(-1, {});
}
tview.set_word_wrap(vs.vs_word_wrap);
if (tview.get_sub_source() != nullptr) {
tview.get_sub_source()->tss_apply_filters = vs.vs_filtering;
}
for (const auto& cmdline : vs.vs_commands) {
auto active = ensure_view(&tview);
execute_command(lnav_data.ld_exec_context, cmdline);
if (!active) {
lnav_data.ld_view_stack.pop_back();
}
}
}
}
void
lnav::session::regex101::insert_entry(const lnav::session::regex101::entry& ei)
{

@ -48,17 +48,25 @@ struct file_state {
struct view_state {
int64_t vs_top{0};
nonstd::optional<int64_t> vs_selection;
std::string vs_search;
bool vs_word_wrap{false};
bool vs_filtering{true};
std::vector<std::string> vs_commands;
};
struct session_data_t {
uint64_t sd_save_time{0};
bool sd_time_offset{false};
std::map<std::string, file_state> sd_file_states;
std::set<std::string> sd_recent_netlocs;
view_state sd_view_states[LNV__MAX];
};
struct recent_refs_t {
std::set<std::string> rr_netlocs;
};
extern struct session_data_t session_data;
extern struct recent_refs_t recent_refs;
void init_session();
void load_session();
@ -68,6 +76,9 @@ void reset_session();
namespace lnav {
namespace session {
void restore_view_states();
namespace regex101 {
struct entry {

@ -163,7 +163,7 @@ sfvt_open(sqlite3_vtab* p_svt, sqlite3_vtab_cursor** pp_cursor)
{
static_file_vtab* p_vt = (static_file_vtab*) p_svt;
p_vt->base.zErrMsg = NULL;
p_vt->base.zErrMsg = nullptr;
sf_vtab_cursor* p_cur = (sf_vtab_cursor*) new sf_vtab_cursor();

@ -53,17 +53,18 @@ static const struct json_path_container term_color_handler = {
.with_children(term_color_rgb_handler),
};
static const struct json_path_container root_color_handler = {
yajlpp::property_handler("#")
.with_obj_provider<term_color, std::vector<term_color>>(
[](const yajlpp_provider_context& ypc,
std::vector<term_color>* palette) {
if (ypc.ypc_index >= palette->size()) {
palette->resize(ypc.ypc_index + 1);
}
return &((*palette)[ypc.ypc_index]);
})
.with_children(term_color_handler),
static const typed_json_path_container<std::vector<term_color>>
root_color_handler = {
yajlpp::property_handler("#")
.with_obj_provider<term_color, std::vector<term_color>>(
[](const yajlpp_provider_context& ypc,
std::vector<term_color>* palette) {
if (ypc.ypc_index >= palette->size()) {
palette->resize(ypc.ypc_index + 1);
}
return &((*palette)[ypc.ypc_index]);
})
.with_children(term_color_handler),
};
term_color_palette*
@ -186,20 +187,19 @@ rgb_color::operator!=(const rgb_color& rhs) const
term_color_palette::term_color_palette(const char* name,
const string_fragment& json)
{
yajlpp_parse_context ypc_xterm(intern_string::lookup(name),
&root_color_handler);
yajl_handle handle;
handle = yajl_alloc(&ypc_xterm.ypc_callbacks, nullptr, &ypc_xterm);
ypc_xterm.with_ignore_unused(true)
.with_obj(this->tc_palette)
.with_handle(handle);
yajl_status st = ypc_xterm.parse(json);
ensure(st == yajl_status_ok);
st = ypc_xterm.complete_parse();
ensure(st == yajl_status_ok);
yajl_free(handle);
intern_string_t iname = intern_string::lookup(name);
auto parse_res
= root_color_handler.parser_for(iname).with_ignore_unused(true).of(
json);
if (parse_res.isErr()) {
log_error("failed to parse palette: %s -- %s",
name,
parse_res.unwrapErr()[0].to_attr_line().get_string().c_str());
}
require(parse_res.isOk());
this->tc_palette = parse_res.unwrap();
for (auto& xc : this->tc_palette) {
xc.xc_lab_color = lab_color(xc.xc_color);
}

@ -40,6 +40,7 @@
#include "log_level.hh"
#include "mapbox/variant.hpp"
#include "yajlpp/yajlpp.hh"
#include "yajlpp/yajlpp_def.hh"
struct rgb_color {
static Result<rgb_color, std::string> from_str(const string_fragment& sf);
@ -155,7 +156,7 @@ struct style_config {
};
struct highlighter_config {
std::string hc_regex;
factory_container<lnav::pcre2pp::code> hc_regex;
style_config hc_style;
};

@ -29,6 +29,8 @@
* @file text_format.cc
*/
#include <set>
#include "text_format.hh"
#include "config.h"
@ -39,8 +41,13 @@ text_format_t
detect_text_format(string_fragment sf,
nonstd::optional<ghc::filesystem::path> path)
{
static const auto GZ_EXT = ghc::filesystem::path(".gz");
static const auto BZ2_EXT = ghc::filesystem::path(".bz2");
static const std::set<ghc::filesystem::path> FILTER_EXTS = {
".bz2",
".gz",
".lzma",
".xz",
".zst",
};
static const auto MD_EXT = ghc::filesystem::path(".md");
static const auto MARKDOWN_EXT = ghc::filesystem::path(".markdown");
@ -99,10 +106,7 @@ detect_text_format(string_fragment sf,
text_format_t retval = text_format_t::TF_UNKNOWN;
if (path) {
if (path->extension() == GZ_EXT) {
path = path->stem();
}
if (path->extension() == BZ2_EXT) {
while (FILTER_EXTS.count(path->extension()) > 0) {
path = path->stem();
}

@ -638,9 +638,9 @@ textfile_sub_source::rescan_files(
} else if (content_sf.startswith("{")) {
yajlpp_parse_context ypc(
intern_string::lookup(lf->get_filename()));
auto_mem<yajl_handle_t> handle(yajl_free);
auto handle
= yajlpp::alloc_handle(&ypc.ypc_callbacks, &ypc);
handle = yajl_alloc(&ypc.ypc_callbacks, nullptr, &ypc);
yajl_config(
handle.in(), yajl_allow_trailing_garbage, 1);
ypc.with_ignore_unused(true)

@ -226,19 +226,7 @@ textview_curses::reload_config(error_reporter& reporter)
}
for (const auto& hl_pair : theme_iter->second.lt_highlights) {
if (hl_pair.second.hc_regex.empty()) {
continue;
}
auto regex = lnav::pcre2pp::code::from(hl_pair.second.hc_regex);
if (regex.isErr()) {
const static intern_string_t PATTERN_SRC
= intern_string::lookup("pattern");
auto ce = regex.unwrapErr();
reporter(&hl_pair.second.hc_regex,
lnav::console::to_user_message(PATTERN_SRC, ce));
if (hl_pair.second.hc_regex.pp_value == nullptr) {
continue;
}
@ -283,7 +271,7 @@ textview_curses::reload_config(error_reporter& reporter)
attrs.ta_attrs |= A_UNDERLINE;
}
this->tc_highlights[{highlight_source_t::THEME, hl_pair.first}]
= highlighter(regex.unwrap().to_shared())
= highlighter(hl_pair.second.hc_regex.pp_value)
.with_attrs(attrs)
.with_color(fg, bg)
.with_nestable(false);

@ -45,6 +45,8 @@
#include "vtab_module_json.hh"
#include "yajlpp/yajlpp_def.hh"
using namespace lnav::roles::literals;
template<>
struct from_sqlite<lnav_view_t> {
inline lnav_view_t operator()(int argc, sqlite3_value** val, int argi)
@ -406,7 +408,14 @@ CREATE TABLE lnav_views (
}
}
} else {
tab->zErrMsg = sqlite3_mprintf("Invalid time: %s", top_time);
auto um = lnav::console::user_message::error(
attr_line_t("Invalid ")
.append_quoted("top_time"_symbol)
.append(" value"))
.with_reason(
attr_line_t("Unrecognized time value: ")
.append(lnav::roles::string(top_time)));
set_vtable_errmsg(tab, um);
return SQLITE_ERROR;
}
}
@ -421,9 +430,8 @@ CREATE TABLE lnav_views (
string_fragment::from_c_str(top_meta));
if (parse_res.isErr()) {
auto errmsg = parse_res.unwrapErr();
tab->zErrMsg = sqlite3_mprintf(
"Invalid top_meta: %s",
errmsg[0].to_attr_line().get_string().c_str());
set_vtable_errmsg(tab, errmsg[0]);
return SQLITE_ERROR;
}
@ -431,9 +439,15 @@ CREATE TABLE lnav_views (
if (index == LNV_TEXT && tlm.tlm_file) {
if (!lnav_data.ld_text_source.to_front(tlm.tlm_file.value())) {
auto errmsg = parse_res.unwrapErr();
tab->zErrMsg = sqlite3_mprintf("unknown top_meta.file: %s",
tlm.tlm_file->c_str());
auto um
= lnav::console::user_message::error(
attr_line_t("Invalid ")
.append_quoted("top_meta.file"_symbol)
.append(" value"))
.with_reason(attr_line_t("Unknown text file: ")
.append(lnav::roles::file(
tlm.tlm_file.value())));
set_vtable_errmsg(tab, um);
return SQLITE_ERROR;
}
}
@ -451,8 +465,15 @@ CREATE TABLE lnav_views (
tc.set_selection(req_anchor_top.value());
}
} else {
tab->zErrMsg = sqlite3_mprintf(
"unknown top_meta.anchor: %s", req_anchor.c_str());
auto um
= lnav::console::user_message::error(
attr_line_t("Invalid ")
.append_quoted("top_meta.anchor"_symbol)
.append(" value"))
.with_reason(
attr_line_t("Unknown anchor: ")
.append(lnav::roles::symbol(req_anchor)));
set_vtable_errmsg(tab, um);
return SQLITE_ERROR;
}
}
@ -570,15 +591,15 @@ struct lnav_view_filter_base {
iterator& operator++()
{
while (this->i_view_index < LNV__MAX) {
textview_curses& tc = lnav_data.ld_views[this->i_view_index];
text_sub_source* tss = tc.get_sub_source();
const auto& tc = lnav_data.ld_views[this->i_view_index];
auto* tss = tc.get_sub_source();
if (tss == nullptr) {
this->i_view_index = lnav_view_t(this->i_view_index + 1);
continue;
}
filter_stack& fs = tss->get_filters();
const auto& fs = tss->get_filters();
this->i_filter_index += 1;
if (this->i_filter_index >= (ssize_t) fs.size()) {
@ -802,10 +823,7 @@ CREATE TABLE lnav_view_filters (
auto set_res = lnav_data.ld_log_source.set_sql_filter(
clause, stmt.release());
if (set_res.isErr()) {
tab->zErrMsg = sqlite3_mprintf(
"%s%s",
sqlitepp::ERROR_PREFIX,
lnav::to_json(set_res.unwrapErr()).c_str());
set_vtable_errmsg(tab, set_res.unwrapErr());
return SQLITE_ERROR;
}
tf = lnav_data.ld_log_source.get_sql_filter().value();
@ -903,10 +921,7 @@ CREATE TABLE lnav_view_filters (
auto set_res = lnav_data.ld_log_source.set_sql_filter(
clause, stmt.release());
if (set_res.isErr()) {
tab->zErrMsg = sqlite3_mprintf(
"%s%s",
sqlitepp::ERROR_PREFIX,
lnav::to_json(set_res.unwrapErr()).c_str());
set_vtable_errmsg(tab, set_res.unwrapErr());
return SQLITE_ERROR;
}
*iter = lnav_data.ld_log_source.get_sql_filter().value();

@ -153,9 +153,12 @@ template<>
struct from_sqlite<string_fragment> {
inline string_fragment operator()(int argc, sqlite3_value** val, int argi)
{
return string_fragment::from_bytes(
(const char*) sqlite3_value_blob(val[argi]),
sqlite3_value_bytes(val[argi]));
auto ptr = (const char*) sqlite3_value_blob(val[argi]);
if (ptr == nullptr) {
return string_fragment::invalid();
}
return string_fragment::from_bytes(ptr, sqlite3_value_bytes(val[argi]));
}
};

@ -141,7 +141,7 @@ CREATE TABLE xpath (
{
switch (col) {
case XP_COL_RESULT: {
auto& xpath_node = vc.c_results[vc.c_rowid];
const auto& xpath_node = vc.c_results[vc.c_rowid];
if (xpath_node.node()) {
std::ostringstream oss;

@ -1584,3 +1584,17 @@ yajlpp_gen::to_string_fragment()
return string_fragment::from_bytes(buf, len);
}
namespace yajlpp {
auto_mem<yajl_handle_t>
alloc_handle(const yajl_callbacks* cb, void* cu)
{
auto_mem<yajl_handle_t> retval(yajl_free);
retval = yajl_alloc(cb, nullptr, cu);
return retval;
}
} // namespace yajlpp

@ -112,6 +112,14 @@ struct factory_container : public positioned_property<std::shared_ptr<T>> {
return Err(
lnav::console::to_user_message(src, from_res.unwrapErr()));
}
std::string to_string() const
{
if (this->pp_value != nullptr) {
return this->pp_value->to_string();
}
return "";
}
};
template<typename... Args>
@ -131,6 +139,14 @@ struct factory_container : public positioned_property<std::shared_ptr<T>> {
return Err(lnav::console::to_user_message(src, from_res.unwrapErr()));
}
std::string to_string() const
{
if (this->pp_value != nullptr) {
return this->pp_value->to_string();
}
return "";
}
};
class yajlpp_gen_context;
@ -283,8 +299,7 @@ struct json_path_handler_base {
std::function<int(yajlpp_parse_context*, int)> jph_bool_cb;
std::function<int(yajlpp_parse_context*, long long)> jph_integer_cb;
std::function<int(yajlpp_parse_context*, double)> jph_double_cb;
std::function<int(
yajlpp_parse_context*, const unsigned char* str, size_t len)>
std::function<int(yajlpp_parse_context*, const string_fragment& sf)>
jph_str_cb;
void validate_string(yajlpp_parse_context& ypc, string_fragment sf) const;
@ -689,4 +704,10 @@ struct json_string {
void dump_schema_to(const json_path_container& jpc, const char* internals_dir);
namespace yajlpp {
auto_mem<yajl_handle_t> alloc_handle(const yajl_callbacks* cb, void* cu);
} // namespace yajlpp
#endif

@ -256,7 +256,8 @@ struct json_path_handler : public json_path_handler_base {
size_t len)
{
ypc->fill_in_source();
return ypc->ypc_current_handler->jph_str_cb(ypc, str, len);
return ypc->ypc_current_handler->jph_str_cb(
ypc, string_fragment::from_bytes(str, len));
}
static int int_field_cb(yajlpp_parse_context* ypc, long long val)
@ -439,15 +440,13 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
auto obj = ypc->ypc_obj_stack.top();
auto value_str = std::string((const char*) str, len);
auto jph = ypc->ypc_current_handler;
const string_fragment& value_str) {
auto* obj = ypc->ypc_obj_stack.top();
const auto* jph = ypc->ypc_current_handler;
jph->validate_string(*ypc, value_str);
json_path_handler::get_field(obj, args...)
.emplace_back(std::move(value_str));
.emplace_back(value_str.to_string());
return 1;
};
@ -520,13 +519,12 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
auto obj = ypc->ypc_obj_stack.top();
const string_fragment& value_str) {
auto* obj = ypc->ypc_obj_stack.top();
auto key = ypc->get_path_fragment(-1);
json_path_handler::get_field(obj, args...)[key]
= std::string((const char*) str, len);
= value_str.to_string();
return 1;
};
@ -591,13 +589,12 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
const string_fragment& value_str) {
auto obj = ypc->ypc_obj_stack.top();
auto key = ypc->get_path_fragment(-1);
json_path_handler::get_field(obj, args...)[key]
= std::string((const char*) str, len);
= value_str.to_string();
return 1;
};
@ -669,13 +666,12 @@ struct json_path_handler : public json_path_handler_base {
};
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
const string_fragment& value_str) {
auto* obj = ypc->ypc_obj_stack.top();
auto key = ypc->get_path_fragment(-1);
json_path_handler::get_field(obj, args...)[key]
= std::string((const char*) str, len);
= value_str.to_string();
return 1;
};
@ -718,14 +714,12 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
auto obj = ypc->ypc_obj_stack.top();
auto value_str = std::string((const char*) str, len);
auto jph = ypc->ypc_current_handler;
const string_fragment& value_str) {
auto* obj = ypc->ypc_obj_stack.top();
const auto* jph = ypc->ypc_current_handler;
jph->validate_string(*ypc, value_str);
json_path_handler::get_field(obj, args...) = std::move(value_str);
json_path_handler::get_field(obj, args...) = value_str.to_string();
return 1;
};
@ -765,23 +759,22 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
auto obj = ypc->ypc_obj_stack.top();
auto jph = ypc->ypc_current_handler;
const string_fragment& value_str) {
auto* obj = ypc->ypc_obj_stack.top();
const auto* jph = ypc->ypc_current_handler;
date_time_scanner dts;
timeval tv{};
exttm tm;
if (dts.scan((char*) str, len, nullptr, &tm, tv) == nullptr) {
ypc->report_error(
lnav::console::user_message::error(
attr_line_t("unrecognized timestamp ")
.append_quoted(
string_fragment::from_bytes(str, len)))
.with_snippet(ypc->get_snippet())
.with_help(jph->get_help_text(ypc)));
if (dts.scan(value_str.data(), value_str.length(), nullptr, &tm, tv)
== nullptr)
{
ypc->report_error(lnav::console::user_message::error(
attr_line_t("unrecognized timestamp ")
.append_quoted(value_str))
.with_snippet(ypc->get_snippet())
.with_help(jph->get_help_text(ypc)));
} else {
json_path_handler::get_field(obj, args...) = tv;
}
@ -831,14 +824,12 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
auto obj = ypc->ypc_obj_stack.top();
auto value_str = std::string((const char*) str, len);
auto jph = ypc->ypc_current_handler;
const string_fragment& value_str) {
auto* obj = ypc->ypc_obj_stack.top();
const auto* jph = ypc->ypc_current_handler;
jph->validate_string(*ypc, value_str);
json_path_handler::get_field(obj, args...) = std::move(value_str);
json_path_handler::get_field(obj, args...) = value_str.to_string();
return 1;
};
@ -893,11 +884,9 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
auto obj = ypc->ypc_obj_stack.top();
auto value_str = std::string((const char*) str, len);
auto jph = ypc->ypc_current_handler;
const string_fragment& value_str) {
auto* obj = ypc->ypc_obj_stack.top();
const auto* jph = ypc->ypc_current_handler;
jph->validate_string(*ypc, value_str);
auto& field = json_path_handler::get_field(obj, args...);
@ -905,7 +894,7 @@ struct json_path_handler : public json_path_handler_base {
field.pp_path = ypc->get_full_path();
field.pp_location.sl_source = ypc->ypc_source;
field.pp_location.sl_line_number = ypc->get_line_number();
field.pp_value = std::move(value_str);
field.pp_value = value_str.to_string();
return 1;
};
@ -946,11 +935,9 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
auto obj = ypc->ypc_obj_stack.top();
auto value_str = std::string((const char*) str, len);
auto jph = ypc->ypc_current_handler;
const string_fragment& value_str) {
auto* obj = ypc->ypc_obj_stack.top();
const auto* jph = ypc->ypc_current_handler;
jph->validate_string(*ypc, value_str);
json_path_handler::get_field(obj, args...)
@ -993,11 +980,9 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
auto obj = ypc->ypc_obj_stack.top();
auto value_str = std::string((const char*) str, len);
auto jph = ypc->ypc_current_handler;
const string_fragment& value_str) {
auto* obj = ypc->ypc_obj_stack.top();
const auto* jph = ypc->ypc_current_handler;
jph->validate_string(*ypc, value_str);
auto& field = json_path_handler::get_field(obj, args...);
@ -1036,7 +1021,7 @@ struct json_path_handler : public json_path_handler_base {
template<typename>
struct int_ {
typedef int type;
using type = int;
};
template<
typename C,
@ -1048,11 +1033,10 @@ struct json_path_handler : public json_path_handler_base {
json_path_handler& for_field(Args... args, T C::*ptr_arg)
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args..., ptr_arg](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
this->jph_str_cb = [args..., ptr_arg](
yajlpp_parse_context* ypc,
const string_fragment& value_frag) {
auto* obj = ypc->ypc_obj_stack.top();
auto value_frag = string_fragment::from_bytes(str, len);
const auto* jph = ypc->ypc_current_handler;
auto loc = source_location{ypc->ypc_source, ypc->get_line_number()};
@ -1067,6 +1051,30 @@ struct json_path_handler : public json_path_handler_base {
return 1;
};
this->jph_gen_callback
= [args..., ptr_arg](yajlpp_gen_context& ygc,
const json_path_handler_base& jph,
yajl_gen handle) {
const auto& field = json_path_handler::get_field(
ygc.ygc_obj_stack.top(), args..., ptr_arg);
if (!ygc.ygc_default_stack.empty()) {
const auto& field_def = json_path_handler::get_field(
ygc.ygc_default_stack.top(), args..., ptr_arg);
if (field.pp_value == field_def.pp_value) {
return yajl_gen_status_ok;
}
}
if (ygc.ygc_depth) {
yajl_gen_string(handle, jph.jph_property);
}
yajlpp_generator gen(handle);
return gen(field.to_string());
};
return *this;
}
@ -1077,7 +1085,7 @@ struct json_path_handler : public json_path_handler_base {
this->add_cb(int_field_cb);
this->jph_integer_cb
= [args...](yajlpp_parse_context* ypc, long long val) {
auto jph = ypc->ypc_current_handler;
const auto* jph = ypc->ypc_current_handler;
auto* obj = ypc->ypc_obj_stack.top();
if (val < jph->jph_min_value) {
@ -1130,7 +1138,7 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(dbl_field_cb);
this->jph_double_cb = [args...](yajlpp_parse_context* ypc, double val) {
auto jph = ypc->ypc_current_handler;
const auto* jph = ypc->ypc_current_handler;
auto* obj = ypc->ypc_obj_stack.top();
if (val < jph->jph_min_value) {
@ -1185,18 +1193,16 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
auto obj = ypc->ypc_obj_stack.top();
auto handler = ypc->ypc_current_handler;
auto parse_res = relative_time::from_str(
string_fragment::from_bytes(str, len));
const string_fragment& value_str) {
auto* obj = ypc->ypc_obj_stack.top();
const auto* handler = ypc->ypc_current_handler;
auto parse_res = relative_time::from_str(value_str);
if (parse_res.isErr()) {
auto parse_error = parse_res.unwrapErr();
auto value_str = std::string((const char*) str, len);
handler->report_duration_error(ypc, value_str, parse_error);
handler->report_duration_error(
ypc, value_str.to_string(), parse_error);
return 1;
}
@ -1243,18 +1249,16 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
auto obj = ypc->ypc_obj_stack.top();
auto handler = ypc->ypc_current_handler;
auto res = handler->to_enum_value(string_fragment(str, 0, len));
const string_fragment& value_str) {
auto* obj = ypc->ypc_obj_stack.top();
const auto* handler = ypc->ypc_current_handler;
auto res = handler->to_enum_value(value_str);
if (res) {
json_path_handler::get_field(obj, args...)
= (typename LastIsEnum<Args...>::value_type) res.value();
} else {
handler->report_enum_error(ypc,
std::string((const char*) str, len));
handler->report_enum_error(ypc, value_str.to_string());
}
return 1;
@ -1364,6 +1368,27 @@ public:
return *this;
}
Result<void, std::vector<lnav::console::user_message>> consume(
const string_fragment& json)
{
if (this->yp_parse_context.parse(json) == yajl_status_ok) {
if (this->yp_errors.empty()) {
return Ok();
}
}
return Err(std::move(this->yp_errors));
}
Result<T, std::vector<lnav::console::user_message>> complete()
{
if (this->yp_parse_context.complete_parse() == yajl_status_ok) {
return Ok(std::move(this->yp_obj));
}
return Err(std::move(this->yp_errors));
}
Result<T, std::vector<lnav::console::user_message>> of(
const string_fragment& json)
{

@ -8,6 +8,11 @@
"color": "InvalidColor",
"bad-property": "abc"
}
},
"highlights": {
"foobar": {
"pattern": "abc("
}
}
}
}

@ -402,6 +402,8 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_sessions.sh_0300a1391c33b1c45ddfa90198a6bd0a5404a77f.out \
$(srcdir)/%reldir%/test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.err \
$(srcdir)/%reldir%/test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.out \
$(srcdir)/%reldir%/test_sessions.sh_33ab03afda2c9331a289fcbd1abdbc1c37b2e87b.err \
$(srcdir)/%reldir%/test_sessions.sh_33ab03afda2c9331a289fcbd1abdbc1c37b2e87b.out \
$(srcdir)/%reldir%/test_sessions.sh_345b0e66dab7b881397c4b38380da81092ab70dd.err \
$(srcdir)/%reldir%/test_sessions.sh_345b0e66dab7b881397c4b38380da81092ab70dd.out \
$(srcdir)/%reldir%/test_sessions.sh_430b9522ba1a37983138f3c4935cba91b781e415.err \
@ -428,6 +430,8 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_sessions.sh_b932b33dd087b94d4306dd179c5d4f9ddd394960.out \
$(srcdir)/%reldir%/test_sessions.sh_ddf45811e9906de9f3930fe802ac7b2cc6e48106.err \
$(srcdir)/%reldir%/test_sessions.sh_ddf45811e9906de9f3930fe802ac7b2cc6e48106.out \
$(srcdir)/%reldir%/test_sessions.sh_e57697be4d81ac8e5b2b2fa84f919b2d494978f3.err \
$(srcdir)/%reldir%/test_sessions.sh_e57697be4d81ac8e5b2b2fa84f919b2d494978f3.out \
$(srcdir)/%reldir%/test_shlexer.sh_14dd967cb2af90899c9e5e45d00b676b5a3163aa.err \
$(srcdir)/%reldir%/test_shlexer.sh_14dd967cb2af90899c9e5e45d00b676b5a3163aa.out \
$(srcdir)/%reldir%/test_shlexer.sh_2781f5dd570580cbe746ad91b58a28b8371283b3.err \
@ -766,8 +770,12 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_sql_json_func.sh_f34f5dfa938a1ac7721f924beb16bbceec127a1b.out \
$(srcdir)/%reldir%/test_sql_regexp.sh_03257c56e85558aa0cc925b68d3af962afc25125.err \
$(srcdir)/%reldir%/test_sql_regexp.sh_03257c56e85558aa0cc925b68d3af962afc25125.out \
$(srcdir)/%reldir%/test_sql_regexp.sh_219a579cf7744fa08ab79fadd08b521b2f18a661.err \
$(srcdir)/%reldir%/test_sql_regexp.sh_219a579cf7744fa08ab79fadd08b521b2f18a661.out \
$(srcdir)/%reldir%/test_sql_regexp.sh_51293df041b6969ccecc60204dce3676d0fb006d.err \
$(srcdir)/%reldir%/test_sql_regexp.sh_51293df041b6969ccecc60204dce3676d0fb006d.out \
$(srcdir)/%reldir%/test_sql_regexp.sh_a610798fefdacd8d0179a4b17cd757d00fb731be.err \
$(srcdir)/%reldir%/test_sql_regexp.sh_a610798fefdacd8d0179a4b17cd757d00fb731be.out \
$(srcdir)/%reldir%/test_sql_regexp.sh_b841a0c09601e2419eeb99e85f7e286c889e4801.err \
$(srcdir)/%reldir%/test_sql_regexp.sh_b841a0c09601e2419eeb99e85f7e286c889e4801.out \
$(srcdir)/%reldir%/test_sql_regexp.sh_bbd1128cf61a9af8f9dc937b46217443f42e1a7a.err \
@ -1006,6 +1014,8 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_sql_views_vtab.sh_a1e6ee4f098d525330d5f58a9d71cbbd816d51bb.out \
$(srcdir)/%reldir%/test_sql_views_vtab.sh_a2c0f0e51b3f85ea2a05ecdcacaad962b4fe5d4f.err \
$(srcdir)/%reldir%/test_sql_views_vtab.sh_a2c0f0e51b3f85ea2a05ecdcacaad962b4fe5d4f.out \
$(srcdir)/%reldir%/test_sql_views_vtab.sh_a7a7fd577f710aa8b0ad5a94fdfb35daea75e06c.err \
$(srcdir)/%reldir%/test_sql_views_vtab.sh_a7a7fd577f710aa8b0ad5a94fdfb35daea75e06c.out \
$(srcdir)/%reldir%/test_sql_views_vtab.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.err \
$(srcdir)/%reldir%/test_sql_views_vtab.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.out \
$(srcdir)/%reldir%/test_sql_views_vtab.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.err \

@ -6,7 +6,18 @@
background-color #hex|color_name
underline
bold
✘ error: 'bad' is not a supported configuration $schema version
✘ error: “abc(” is not a valid regular expression
reason: missing closing parenthesis
 --> /ui/theme-defs/invalid-theme/highlights/foobar/pattern
 | abc( 
 |  ^ missing closing parenthesis 
 --> {test_dir}/bad-config2/configs/invalid-theme/config.json:14
 |  "pattern": "abc("
 = help: Property Synopsis
/ui/theme-defs/invalid-theme/highlights/foobar/pattern regular expression
Description
The regular expression to highlight
✘ error: “bad” is not a supported configuration $schema version
 --> {test_dir}/bad-config2/formats/invalid-config/config.bad-schema.json:2
 |  "$schema": "bad" 
 = note: expecting one of the following $schema values:

@ -0,0 +1,11 @@
2011-11-02 17:20:39.348000 ⋮ 192.168.2.76 52099 192.150.187.43 80 2 GET www.bro-ids.org /frames/header.html http://git.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 3516 200 OK - - (empty) - - - - - - Fzea5XNhn9eNRMvx7 - text/html
2011-11-02 17:20:39.448000 ⋮ 192.168.2.76 52109 192.150.187.43 80 1 GET www.bro-ids.org /frames/footer.html http://git.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6695 200 OK - - (empty) - - - - - - FkCp6k4tqksK3tiSy7 - text/html
2011-11-02 17:20:39.463000 ⋮ 192.168.2.76 52099 192.150.187.43 80 3 GET www.bro-ids.org /images/logo-bro-small.png http://www.bro-ids.org/frames/header.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6075 200 OK - - (empty) - - - - - - Fw6FlF4WtotJFNXmHb - image/png
2011-11-02 17:20:39.786000 ⋮ 192.168.2.76 52110 199.59.148.201 80 1 GET search.twitter.com /search.json?&q=#BroIDS&rpp=2&callback=jsonp1320279639636 http://www.bro-ids.org/frames/footer.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1543 200 OK - - (empty) - - - - - - Feut0t346XEHsQ0OC7 - text/plain
2011-11-02 17:21:12.372000 ⋮ 192.168.2.76 52111 192.150.187.43 80 1 GET www.bro-ids.org /research/index.html http://www.bro-ids.org/frames/header.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 47728 200 OK - - (empty) - - - - - - FOze0l2aT79uPyMiv7 - text/html
2011-11-02 17:21:13.121000 ⋮ 192.168.2.76 52087 209.85.145.95 80 7 GET ajax.googleapis.com /ajax/services/feed/load?v=1.0&callback=jsonp1320279672539&q=http://blog.bro-ids.org/feeds/posts/default&num=5 http://www.bro-ids.org/research/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6584 200 OK - - (empty) - - - - - - FXEXQEMH8DrEuAdg8 - text/plain
2011-11-02 17:21:13.123000 ⋮ 192.168.2.76 52089 74.125.225.83 80 4 GET www.google.com /uds/css/clear.gif http://www.google.com/uds/api/search/1.0/473bb688d0c0dd605119ad983f5a4386/default+en.css 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
2011-11-02 17:21:13.123000 ⋮ 192.168.2.76 52084 74.125.225.83 80 9 GET www.google.com /uds/css/small-logo.png http://www.bro-ids.org/research/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
2011-11-02 17:21:13.198000 ⋮ 192.168.2.76 52112 199.59.148.201 80 1 GET search.twitter.com /search.json?&q=#BroIDS&rpp=2&callback=jsonp1320279672537 http://www.bro-ids.org/research/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1543 200 OK - - (empty) - - - - - - Fzjgwn8xXem3Esvk - text/plain
#close 2017-04-16-21-36-10
2011-11-02 17:21:13.204000 ⋮ 192.168.2.76 52113 199.59.148.20 80 1 GET api.twitter.com /1/statuses/user_timeline.json?screen_name=Bro_IDS&count=2&include_rts=1&callback=jsonp1320279672538 http://www.bro-ids.org/research/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6095 200 OK - - (empty) - - - - - - FAVIuu2XZQyVznfnq8 - text/plain

@ -0,0 +1,11 @@
2011-11-02 17:20:39.348000 ⋮ 192.168.2.76 52099 192.150.187.43 80 2 GET www.bro-ids.org /frames/header.html http://git.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 3516 200 OK - - (empty) - - - - - - Fzea5XNhn9eNRMvx7 - text/html
2011-11-02 17:20:39.448000 ⋮ 192.168.2.76 52109 192.150.187.43 80 1 GET www.bro-ids.org /frames/footer.html http://git.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6695 200 OK - - (empty) - - - - - - FkCp6k4tqksK3tiSy7 - text/html
2011-11-02 17:20:39.463000 ⋮ 192.168.2.76 52099 192.150.187.43 80 3 GET www.bro-ids.org /images/logo-bro-small.png http://www.bro-ids.org/frames/header.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6075 200 OK - - (empty) - - - - - - Fw6FlF4WtotJFNXmHb - image/png
2011-11-02 17:20:39.786000 ⋮ 192.168.2.76 52110 199.59.148.201 80 1 GET search.twitter.com /search.json?&q=#BroIDS&rpp=2&callback=jsonp1320279639636 http://www.bro-ids.org/frames/footer.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1543 200 OK - - (empty) - - - - - - Feut0t346XEHsQ0OC7 - text/plain
2011-11-02 17:21:12.372000 ⋮ 192.168.2.76 52111 192.150.187.43 80 1 GET www.bro-ids.org /research/index.html http://www.bro-ids.org/frames/header.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 47728 200 OK - - (empty) - - - - - - FOze0l2aT79uPyMiv7 - text/html
2011-11-02 17:21:13.121000 ⋮ 192.168.2.76 52087 209.85.145.95 80 7 GET ajax.googleapis.com /ajax/services/feed/load?v=1.0&callback=jsonp1320279672539&q=http://blog.bro-ids.org/feeds/posts/default&num=5 http://www.bro-ids.org/research/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6584 200 OK - - (empty) - - - - - - FXEXQEMH8DrEuAdg8 - text/plain
2011-11-02 17:21:13.123000 ⋮ 192.168.2.76 52089 74.125.225.83 80 4 GET www.google.com /uds/css/clear.gif http://www.google.com/uds/api/search/1.0/473bb688d0c0dd605119ad983f5a4386/default+en.css 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
2011-11-02 17:21:13.123000 ⋮ 192.168.2.76 52084 74.125.225.83 80 9 GET www.google.com /uds/css/small-logo.png http://www.bro-ids.org/research/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
2011-11-02 17:21:13.198000 ⋮ 192.168.2.76 52112 199.59.148.201 80 1 GET search.twitter.com /search.json?&q=#BroIDS&rpp=2&callback=jsonp1320279672537 http://www.bro-ids.org/research/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1543 200 OK - - (empty) - - - - - - Fzjgwn8xXem3Esvk - text/plain
#close 2017-04-16-21-36-10
2011-11-02 17:21:13.204000 ⋮ 192.168.2.76 52113 199.59.148.20 80 1 GET api.twitter.com /1/statuses/user_timeline.json?screen_name=Bro_IDS&count=2&include_rts=1&callback=jsonp1320279672538 http://www.bro-ids.org/research/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6095 200 OK - - (empty) - - - - - - FAVIuu2XZQyVznfnq8 - text/plain

@ -1,4 +1 @@
error: sqlite3_exec failed -- parse error: premature EOF
[123, true
(right here) ------^
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"invalid JSON","attrs":[]},"reason":{"str":"parse error: premature EOF\n [123, true\n (right here) ------^","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}

@ -1,4 +1 @@
error: sqlite3_exec failed -- parse error: premature EOF
[null, true, 20, 30, 40
(right here) ------^
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"invalid JSON","attrs":[]},"reason":{"str":"parse error: premature EOF\n [null, true, 20, 30, 40\n (right here) ------^","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}

@ -0,0 +1,7 @@
✘ error: “^(” is not a valid regular expression
reason: missing closing parenthesis
 --> command-option:1
 | ;SELECT * from regexp_capture_into_json('abc=def;ghi=jkl;', '^(')
 --> pattern
 | ^( 
 |  ^ missing closing parenthesis 

@ -0,0 +1,7 @@
✘ error: “^(” is not a valid regular expression
reason: missing closing parenthesis
 --> command-option:1
 | ;SELECT * from regexp_capture('abc=def;ghi=jkl;', '^(')
 --> pattern
 | ^( 
 |  ^ missing closing parenthesis 

@ -1 +1 @@
error: sqlite3_exec failed -- Invalid regular expression: missing closing parenthesis
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"“(” is not a valid regular expression","attrs":[]},"reason":{"str":"missing closing parenthesis","attrs":[]},"snippets":[{"source":"pattern","line":0,"content":{"str":"(\n ^ missing closing parenthesis","attrs":[{"start":0,"end":1,"type":"role","value":3},{"start":0,"end":1,"type":"style","value":2359296},{"start":0,"end":1,"type":"role","value":5},{"start":3,"end":5,"type":"role","value":5},{"start":5,"end":32,"type":"role","value":5},{"start":0,"end":-1,"type":"role","value":40}]}}],"help":{"str":"","attrs":[]}}

@ -0,0 +1,4 @@
✘ error: Invalid “top_meta.file” value
reason: Unknown text file: bad
 --> command-option:1
 | ;UPDATE lnav_views SET top_meta = json_object('file', 'bad') WHERE name = 'text'

@ -1,4 +1,4 @@
✘ error: SQL statement failed
reason: Invalid time: bad-time
✘ error: Invalid “top_time” value
reason: Unrecognized time value: bad-time
 --> command-option:1
 | ;UPDATE lnav_views SET top_time = 'bad-time' WHERE name = 'log'

@ -117,3 +117,19 @@ run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
-c ":load-session" \
-c ":test-comment restore hidden lines" \
${test_dir}/logfile_access_log.0
# hiding fields failed
rm -rf ./sessions
mkdir -p $HOME
run_cap_test ${lnav_test} -n \
-c ":hide-fields bro_uid" \
-c ":goto -10" \
-c ":save-session" \
${test_dir}/logfile_bro_http.log.0
# restoring hidden fields failed
run_cap_test ${lnav_test} -n \
-c ":load-session" \
-c ":goto -10" \
-c ":test-comment restoring hidden fields" \
${test_dir}/logfile_bro_http.log.0

@ -28,5 +28,11 @@ run_cap_test ${lnav_test} -n \
run_cap_test ${lnav_test} -nN \
-c ";SELECT * from regexp_capture('abc=def;ghi=jkl;', '^(\w+)=([^;]+);')"
run_cap_test ${lnav_test} -nN \
-c ";SELECT * from regexp_capture('abc=def;ghi=jkl;', '^(')"
run_cap_test ${lnav_test} -nN \
-c ";SELECT * from regexp_capture_into_json('abc=def;ghi=jkl;', '^(\w+)=([^;]+);')"
run_cap_test ${lnav_test} -nN \
-c ";SELECT * from regexp_capture_into_json('abc=def;ghi=jkl;', '^(')"

@ -177,3 +177,7 @@ run_cap_test ${lnav_test} -n \
-c ";SELECT top_meta FROM lnav_top_view" \
-c ":write-json-to -" \
${test_dir}/logfile_xml_msg.0
run_cap_test ${lnav_test} -n \
-c ";UPDATE lnav_views SET top_meta = json_object('file', 'bad') WHERE name = 'text'" \
${test_dir}/textfile_ansi.0

Loading…
Cancel
Save