mirror of
https://github.com/tstack/lnav.git
synced 2024-09-11 13:05:51 +03:00
[pretty] highlight log messages in the pretty view as in the normal log view
This commit is contained in:
parent
697d22705d
commit
7fb881222d
2
NEWS
2
NEWS
@ -8,6 +8,8 @@ lnav v0.8.4:
|
||||
* When typing in a search, instead of moving the view to the first match
|
||||
that was found, the first ten matches will be displayed in the preview
|
||||
window.
|
||||
* The pretty-print view maintains highlighting from the log view.
|
||||
* The pretty-print view no longer tries to reverse lookup IP addresses.
|
||||
|
||||
Fixes:
|
||||
* The HOME key should now work in the command-prompt and move the cursor
|
||||
|
11
configure.ac
11
configure.ac
@ -41,8 +41,15 @@ AC_PROG_CXX
|
||||
|
||||
CPPFLAGS="$CPPFLAGS -D_ISOC99_SOURCE -D__STDC_LIMIT_MACROS -D_GNU_SOURCE"
|
||||
|
||||
# CFLAGS=`echo $CFLAGS | sed 's/-O2//g'`
|
||||
# CXXFLAGS=`echo $CXXFLAGS | sed 's/-O2//g'`
|
||||
AC_ARG_ENABLE([debug],
|
||||
AS_HELP_STRING([--enable-debug],
|
||||
[Compile with symbols]))
|
||||
|
||||
AS_VAR_IF([enable_profiling], [yes],
|
||||
[CFLAGS=`echo $CFLAGS | sed 's/-O2//g'`
|
||||
CXXFLAGS=`echo $CXXFLAGS | sed 's/-O2//g'`],
|
||||
[enable_debug=no]dnl
|
||||
)
|
||||
|
||||
AC_ARG_VAR(SFTP_TEST_URL)
|
||||
|
||||
|
@ -93,7 +93,7 @@ time_fmts.cc: ptimec
|
||||
|
||||
if HAVE_RE2C
|
||||
%.cc: %.re
|
||||
$(RE2C_V)$(RE2C_CMD) -o $@ $<
|
||||
$(RE2C_V)$(RE2C_CMD) -8 -o $@ $<
|
||||
$(REC2_V)test $@ -ef $(srcdir)/$*.cc || cp $@ $(srcdir)/$*.cc
|
||||
endif
|
||||
|
||||
|
@ -418,7 +418,11 @@ public:
|
||||
return *this;
|
||||
};
|
||||
|
||||
attr_line_t &append(const attr_line_t &al, text_wrap_settings *tws = nullptr);
|
||||
attr_line_t &insert(size_t index, const attr_line_t &al, text_wrap_settings *tws = nullptr);
|
||||
|
||||
attr_line_t &append(const attr_line_t &al, text_wrap_settings *tws = nullptr) {
|
||||
return this->insert(this->al_string.length(), al, tws);
|
||||
};
|
||||
|
||||
attr_line_t &append(size_t len, char c) {
|
||||
this->al_string.append(len, c);
|
||||
|
@ -45,6 +45,8 @@ using namespace std;
|
||||
|
||||
exec_context INIT_EXEC_CONTEXT;
|
||||
|
||||
bookmark_type_t BM_QUERY("query");
|
||||
|
||||
static const string MSG_FORMAT_STMT =
|
||||
"SELECT count(*) as total, min(log_line) as log_line, log_msg_format "
|
||||
"FROM all_logs GROUP BY log_msg_format ORDER BY total desc";
|
||||
@ -742,3 +744,19 @@ future<string> pipe_callback(exec_context &ec, const string &cmdline, auto_fd &f
|
||||
|
||||
return task.get_future();
|
||||
}
|
||||
|
||||
void add_global_vars(exec_context &ec)
|
||||
{
|
||||
for (const auto &iter : lnav_config.lc_global_vars) {
|
||||
shlex subber(iter.second);
|
||||
string str;
|
||||
|
||||
if (!subber.eval(str, ec.ec_global_vars)) {
|
||||
log_error("Unable to evaluate global variable value: %s",
|
||||
iter.second.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
ec.ec_global_vars[iter.first] = str;
|
||||
}
|
||||
}
|
||||
|
@ -85,4 +85,8 @@ std::future<std::string> pipe_callback(
|
||||
|
||||
int sql_progress(const struct log_cursor &lc);
|
||||
|
||||
void add_global_vars(exec_context &ec);
|
||||
|
||||
extern bookmark_type_t BM_QUERY;
|
||||
|
||||
#endif //LNAV_COMMAND_EXECUTOR_H
|
||||
|
@ -136,11 +136,7 @@ public:
|
||||
|
||||
void reset() {
|
||||
this->ds_pcre_input.reset_next_offset();
|
||||
if (!this->ds_line.empty() &&
|
||||
this->ds_line[this->ds_line.length() - 1] == '.') {
|
||||
this->ds_pcre_input.pi_length -= 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
std::string ds_line;
|
||||
|
103605
src/data_scanner_re.cc
103605
src/data_scanner_re.cc
File diff suppressed because it is too large
Load Diff
@ -37,9 +37,9 @@
|
||||
|
||||
bool data_scanner::tokenize2(pcre_context &pc, data_token_t &token_out)
|
||||
{
|
||||
# define YYCTYPE char
|
||||
# define YYCTYPE unsigned char
|
||||
# define CAPTURE(tok) { \
|
||||
pi.pi_next_offset = YYCURSOR.val - pi.get_string(); \
|
||||
pi.pi_next_offset = YYCURSOR.val - (const unsigned char *) pi.get_string(); \
|
||||
cap[0].c_end = pi.pi_next_offset; \
|
||||
cap[1].c_end = pi.pi_next_offset; \
|
||||
token_out = tok; \
|
||||
@ -48,7 +48,7 @@ bool data_scanner::tokenize2(pcre_context &pc, data_token_t &token_out)
|
||||
CAPTURE(tok); \
|
||||
return true; \
|
||||
}
|
||||
static const char *EMPTY = "";
|
||||
static const unsigned char *EMPTY = (const unsigned char *) "";
|
||||
pcre_input &pi = this->ds_pcre_input;
|
||||
struct _YYCURSOR {
|
||||
const YYCTYPE operator*() const {
|
||||
@ -87,10 +87,12 @@ bool data_scanner::tokenize2(pcre_context &pc, data_token_t &token_out)
|
||||
const YYCTYPE *val;
|
||||
const YYCTYPE *lim;
|
||||
} YYCURSOR;
|
||||
YYCURSOR = pi.get_string() + pi.pi_next_offset;
|
||||
YYCURSOR = (const unsigned char *) pi.get_string() + pi.pi_next_offset;
|
||||
_YYCURSOR yyt1;
|
||||
_YYCURSOR yyt2;
|
||||
const YYCTYPE *YYLIMIT = pi.get_string() + pi.pi_length;
|
||||
_YYCURSOR yyt3;
|
||||
_YYCURSOR yyt4;
|
||||
const YYCTYPE *YYLIMIT = (const unsigned char *) pi.get_string() + pi.pi_length;
|
||||
const YYCTYPE *YYMARKER = YYCURSOR;
|
||||
pcre_context::capture_t *cap = pc.all();
|
||||
|
||||
@ -161,7 +163,7 @@ bool data_scanner::tokenize2(pcre_context &pc, data_token_t &token_out)
|
||||
(SPACE|NUM)NUM":"NUM{2}/[^:] { RET(DT_TIME); }
|
||||
(SPACE|NUM)NUM?":"NUM{2}":"NUM{2}("."NUM{3,6})?/[^:] { RET(DT_TIME); }
|
||||
[0-9a-fA-F][0-9a-fA-F](":"[0-9a-fA-F][0-9a-fA-F])+ {
|
||||
if ((YYCURSOR - pi.get_string()) == 17) {
|
||||
if ((YYCURSOR - (const unsigned char *) pi.get_string()) == 17) {
|
||||
RET(DT_MAC_ADDRESS);
|
||||
} else {
|
||||
RET(DT_HEX_DUMP);
|
||||
|
@ -56,7 +56,7 @@ public:
|
||||
return this->dls_rows.size();
|
||||
};
|
||||
|
||||
size_t text_size_for_line(textview_curses &tc, int line, bool raw) {
|
||||
size_t text_size_for_line(textview_curses &tc, int line, line_flags_t flags) {
|
||||
return this->text_line_width(tc);
|
||||
};
|
||||
|
||||
@ -74,7 +74,7 @@ public:
|
||||
void text_value_for_line(textview_curses &tc,
|
||||
int row,
|
||||
std::string &label_out,
|
||||
bool raw)
|
||||
line_flags_t flags)
|
||||
{
|
||||
/*
|
||||
* start_value is the result rowid, each bucket type is a column value
|
||||
|
@ -49,7 +49,7 @@ hist_source::hist_source()
|
||||
void hist_source::text_value_for_line(textview_curses &tc,
|
||||
int row,
|
||||
std::string &value_out,
|
||||
bool no_scrub)
|
||||
line_flags_t flags)
|
||||
{
|
||||
int grow = row / (this->buckets_per_group() + 1);
|
||||
int brow = row % (this->buckets_per_group() + 1);
|
||||
|
@ -153,12 +153,12 @@ public:
|
||||
void text_value_for_line(textview_curses &tc,
|
||||
int row,
|
||||
std::string &value_out,
|
||||
bool no_scrub);
|
||||
line_flags_t flags);
|
||||
void text_attrs_for_line(textview_curses &tc,
|
||||
int row,
|
||||
string_attrs_t &value_out);
|
||||
|
||||
size_t text_size_for_line(textview_curses &tc, int row, bool raw) {
|
||||
size_t text_size_for_line(textview_curses &tc, int row, line_flags_t flags) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
@ -550,7 +550,7 @@ public:
|
||||
void text_value_for_line(textview_curses &tc,
|
||||
int row,
|
||||
std::string &value_out,
|
||||
bool no_scrub) {
|
||||
line_flags_t flags) {
|
||||
bucket_t &bucket = this->find_bucket(row);
|
||||
struct tm bucket_tm;
|
||||
char tm_buffer[128];
|
||||
@ -591,7 +591,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
size_t text_size_for_line(textview_curses &tc, int row, bool raw) {
|
||||
size_t text_size_for_line(textview_curses &tc, int row, line_flags_t flags) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
122
src/lnav.cc
122
src/lnav.cc
@ -166,8 +166,6 @@ const int ZOOM_LEVELS[] = {
|
||||
|
||||
const ssize_t ZOOM_COUNT = sizeof(ZOOM_LEVELS) / sizeof(int);
|
||||
|
||||
bookmark_type_t BM_QUERY("query");
|
||||
|
||||
const char *lnav_view_strings[LNV__MAX + 1] = {
|
||||
"log",
|
||||
"text",
|
||||
@ -252,22 +250,6 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
static void add_global_vars(exec_context &ec)
|
||||
{
|
||||
for (const auto &iter : lnav_config.lc_global_vars) {
|
||||
shlex subber(iter.second);
|
||||
string str;
|
||||
|
||||
if (!subber.eval(str, ec.ec_global_vars)) {
|
||||
log_error("Unable to evaluate global variable value: %s",
|
||||
iter.second.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
ec.ec_global_vars[iter.first] = str;
|
||||
}
|
||||
}
|
||||
|
||||
static void regenerate_unique_file_names()
|
||||
{
|
||||
unique_path_generator upg;
|
||||
@ -770,49 +752,6 @@ static void open_schema_view(void)
|
||||
schema_tc->set_sub_source(pts);
|
||||
}
|
||||
|
||||
static int pretty_sql_callback(exec_context &ec, sqlite3_stmt *stmt)
|
||||
{
|
||||
if (!sqlite3_stmt_busy(stmt)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ncols = sqlite3_column_count(stmt);
|
||||
|
||||
for (int lpc = 0; lpc < ncols; lpc++) {
|
||||
if (lpc > 0) {
|
||||
ec.ec_accumulator.append(", ");
|
||||
}
|
||||
ec.ec_accumulator.append((const char *)sqlite3_column_text(stmt, lpc));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static future<string> pretty_pipe_callback(exec_context &ec,
|
||||
const string &cmdline,
|
||||
auto_fd &fd)
|
||||
{
|
||||
auto retval = std::async(std::launch::async, [&]() {
|
||||
char buffer[1024];
|
||||
ostringstream ss;
|
||||
ssize_t rc;
|
||||
|
||||
while ((rc = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
ss.write(buffer, rc);
|
||||
}
|
||||
|
||||
string retval = ss.str();
|
||||
|
||||
if (endswith(retval.c_str(), "\n")) {
|
||||
retval.resize(retval.length() - 1);
|
||||
}
|
||||
|
||||
return retval;
|
||||
});
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void open_pretty_view(void)
|
||||
{
|
||||
static const char *NOTHING_MSG =
|
||||
@ -822,7 +761,7 @@ static void open_pretty_view(void)
|
||||
textview_curses *pretty_tc = &lnav_data.ld_views[LNV_PRETTY];
|
||||
textview_curses *log_tc = &lnav_data.ld_views[LNV_LOG];
|
||||
textview_curses *text_tc = &lnav_data.ld_views[LNV_TEXT];
|
||||
ostringstream stream;
|
||||
attr_line_t full_text;
|
||||
|
||||
delete pretty_tc->get_sub_source();
|
||||
if (top_tc->get_inner_height() == 0) {
|
||||
@ -837,35 +776,51 @@ static void open_pretty_view(void)
|
||||
for (vis_line_t vl = log_tc->get_top(); vl <= log_tc->get_bottom(); ++vl) {
|
||||
content_line_t cl = lss.at(vl);
|
||||
shared_ptr<logfile> lf = lss.find(cl);
|
||||
log_format *format = lf->get_format();
|
||||
logfile::iterator ll = lf->begin() + cl;
|
||||
auto ll = lf->begin() + cl;
|
||||
shared_buffer_ref sbr;
|
||||
|
||||
if (!first_line && ll->is_continued()) {
|
||||
continue;
|
||||
}
|
||||
ll = lf->message_start(ll);
|
||||
|
||||
lf->read_full_message(ll, sbr);
|
||||
|
||||
string_attrs_t sa;
|
||||
auto ll_start = lf->message_start(ll);
|
||||
vector<logline_value> values;
|
||||
string rewritten_line;
|
||||
attr_line_t al;
|
||||
|
||||
format->annotate(sbr, sa, values);
|
||||
exec_context ec(&values, pretty_sql_callback, pretty_pipe_callback);
|
||||
ec.ec_top_line = vl;
|
||||
add_ansi_vars(ec.ec_global_vars);
|
||||
add_global_vars(ec);
|
||||
format->rewrite(ec, sbr, sa, rewritten_line);
|
||||
vl -= vis_line_t(distance(ll_start, ll));
|
||||
lss.text_value_for_line(*log_tc, vl, al.get_string(),
|
||||
text_sub_source::RF_FULL|
|
||||
text_sub_source::RF_REWRITE);
|
||||
lss.text_attrs_for_line(*log_tc, vl, al.get_attrs());
|
||||
|
||||
data_scanner ds(rewritten_line);
|
||||
pretty_printer pp(&ds);
|
||||
line_range orig_lr = find_string_attr_range(
|
||||
al.get_attrs(), &textview_curses::SA_ORIGINAL_LINE);
|
||||
attr_line_t orig_al = al.subline(orig_lr.lr_start, orig_lr.length());
|
||||
attr_line_t prefix_al = al.subline(0, orig_lr.lr_start);
|
||||
|
||||
data_scanner ds(orig_al.get_string());
|
||||
pretty_printer pp(&ds, orig_al.get_attrs());
|
||||
attr_line_t pretty_al;
|
||||
vector<attr_line_t> pretty_lines;
|
||||
|
||||
// TODO: dump more details of the line in the output.
|
||||
stream << trim(pp.print()) << endl;
|
||||
pp.append_to(pretty_al);
|
||||
pretty_al.split_lines(pretty_lines);
|
||||
|
||||
for (auto &pretty_line : pretty_lines) {
|
||||
if (pretty_line.empty() && &pretty_line == &pretty_lines.back()) {
|
||||
break;
|
||||
}
|
||||
pretty_line.insert(0, prefix_al);
|
||||
pretty_line.append("\n");
|
||||
full_text.append(pretty_line);
|
||||
}
|
||||
|
||||
first_line = false;
|
||||
}
|
||||
|
||||
if (!full_text.empty()) {
|
||||
full_text.erase(full_text.length() - 1, 1);
|
||||
}
|
||||
}
|
||||
else if (top_tc == text_tc) {
|
||||
shared_ptr<logfile> lf = lnav_data.ld_text_source.current_file();
|
||||
@ -876,12 +831,15 @@ static void open_pretty_view(void)
|
||||
|
||||
lf->read_full_message(ll, sbr);
|
||||
data_scanner ds(sbr);
|
||||
pretty_printer pp(&ds);
|
||||
string_attrs_t sa;
|
||||
pretty_printer pp(&ds, sa);
|
||||
|
||||
stream << pp.print() << endl;
|
||||
pp.append_to(full_text);
|
||||
}
|
||||
}
|
||||
pretty_tc->set_sub_source(new plain_text_source(stream.str()));
|
||||
plain_text_source *pts = new plain_text_source();
|
||||
pts->replace_with(full_text);
|
||||
pretty_tc->set_sub_source(pts);
|
||||
if (lnav_data.ld_last_pretty_print_top != log_tc->get_top()) {
|
||||
pretty_tc->set_top(vis_line_t(0));
|
||||
}
|
||||
|
@ -319,7 +319,6 @@ struct _lnav_data {
|
||||
extern struct _lnav_data lnav_data;
|
||||
|
||||
extern readline_context::command_map_t lnav_commands;
|
||||
extern bookmark_type_t BM_QUERY;
|
||||
extern const int ZOOM_LEVELS[];
|
||||
extern const ssize_t ZOOM_COUNT;
|
||||
|
||||
|
@ -638,7 +638,8 @@ static string com_save_to(exec_context &ec, string cmdline, vector<string> &args
|
||||
|
||||
string line;
|
||||
|
||||
dls.text_value_for_line(lnav_data.ld_views[LNV_DB], lpc, line, true);
|
||||
dls.text_value_for_line(lnav_data.ld_views[LNV_DB], lpc, line,
|
||||
text_sub_source::RF_RAW);
|
||||
fputs(line.c_str(), outfile);
|
||||
fputc('\n', outfile);
|
||||
}
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "auto_pid.hh"
|
||||
#include "lnav_config.hh"
|
||||
#include "yajlpp.hh"
|
||||
#include "shlex.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -493,4 +494,4 @@ void reload_config()
|
||||
curr->reload_config();
|
||||
curr = curr->lcl_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,12 +60,12 @@ using namespace std;
|
||||
* iostat
|
||||
*/
|
||||
|
||||
string_attr_type logline::L_PREFIX;
|
||||
string_attr_type logline::L_TIMESTAMP;
|
||||
string_attr_type logline::L_FILE;
|
||||
string_attr_type logline::L_PARTITION;
|
||||
string_attr_type logline::L_MODULE;
|
||||
string_attr_type logline::L_OPID;
|
||||
string_attr_type logline::L_PREFIX("prefix");
|
||||
string_attr_type logline::L_TIMESTAMP("timestamp");
|
||||
string_attr_type logline::L_FILE("file");
|
||||
string_attr_type logline::L_PARTITION("partition");
|
||||
string_attr_type logline::L_MODULE("module");
|
||||
string_attr_type logline::L_OPID("opid");
|
||||
|
||||
const char *logline::level_names[LEVEL__MAX + 1] = {
|
||||
"unknown",
|
||||
@ -201,6 +201,47 @@ logline_value::kind_t logline_value::string2kind(const char *kindstr)
|
||||
return VALUE_UNKNOWN;
|
||||
}
|
||||
|
||||
struct line_range logline_value::origin_in_full_msg(const char *msg, size_t len) const
|
||||
{
|
||||
if (this->lv_sub_offset == 0) {
|
||||
return this->lv_origin;
|
||||
}
|
||||
|
||||
if (len == -1) {
|
||||
len = strlen(msg);
|
||||
}
|
||||
|
||||
struct line_range retval = this->lv_origin;
|
||||
const char *last = msg, *msg_end = msg + len;
|
||||
|
||||
for (int lpc = 0; lpc < this->lv_sub_offset; lpc++) {
|
||||
const auto *next = (const char *) memchr(last, '\n', msg_end - last);
|
||||
require(next != NULL);
|
||||
|
||||
next += 1;
|
||||
int amount = (next - last);
|
||||
|
||||
retval.lr_start += amount;
|
||||
if (retval.lr_end != -1) {
|
||||
retval.lr_end += amount;
|
||||
}
|
||||
|
||||
last = next + 1;
|
||||
}
|
||||
|
||||
if (retval.lr_end == -1) {
|
||||
const auto *eol = (const char *) memchr(last, '\n', msg_end - last);
|
||||
|
||||
if (eol == nullptr) {
|
||||
retval.lr_end = len;
|
||||
} else {
|
||||
retval.lr_end = eol - msg;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
vector<log_format *> log_format::lf_root_formats;
|
||||
|
||||
vector<log_format *> &log_format::get_root_formats(void)
|
||||
@ -960,27 +1001,23 @@ void external_log_format::rewrite(exec_context &ec,
|
||||
|
||||
value_def &vd = *vd_iter->second;
|
||||
|
||||
if (!vd.vd_rewriter.empty()) {
|
||||
string field_value = iter->to_string();
|
||||
|
||||
field_value = execute_any(ec, vd.vd_rewriter);
|
||||
|
||||
struct line_range adj_origin = iter->origin_in_full_msg(
|
||||
value_out.c_str(), value_out.length());
|
||||
|
||||
value_out.erase(adj_origin.lr_start, adj_origin.length());
|
||||
|
||||
int32_t shift_amount = field_value.length() - adj_origin.length();
|
||||
value_out.insert(adj_origin.lr_start, field_value);
|
||||
for (shift_iter = values.begin();
|
||||
shift_iter != values.end(); ++shift_iter) {
|
||||
if (shift_iter->lv_name == iter->lv_name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
shift_iter->lv_origin.shift(adj_origin.lr_start, shift_amount);
|
||||
}
|
||||
if (vd.vd_rewriter.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string field_value = execute_any(ec, vd.vd_rewriter);
|
||||
struct line_range adj_origin = iter->origin_in_full_msg(
|
||||
value_out.c_str(), value_out.length());
|
||||
|
||||
value_out.erase(adj_origin.lr_start, adj_origin.length());
|
||||
|
||||
int32_t shift_amount = field_value.length() - adj_origin.length();
|
||||
value_out.insert(adj_origin.lr_start, field_value);
|
||||
for (shift_iter = values.begin();
|
||||
shift_iter != values.end(); ++shift_iter) {
|
||||
shift_iter->lv_origin.shift(adj_origin.lr_start, shift_amount);
|
||||
}
|
||||
shift_string_attrs(sa, adj_origin.lr_start, shift_amount);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -545,37 +545,7 @@ public:
|
||||
return this->lv_sbr.length();
|
||||
}
|
||||
|
||||
struct line_range origin_in_full_msg(const char *msg, size_t len) {
|
||||
if (this->lv_sub_offset == 0) {
|
||||
return this->lv_origin;
|
||||
}
|
||||
|
||||
struct line_range retval = this->lv_origin;
|
||||
const char *last = msg;
|
||||
|
||||
for (int lpc = 0; lpc < this->lv_sub_offset; lpc++) {
|
||||
const char *next = strchr(last, '\n');
|
||||
require(next != NULL);
|
||||
|
||||
next += 1;
|
||||
int amount = (next - last);
|
||||
|
||||
retval.lr_start += amount;
|
||||
if (retval.lr_end != -1) {
|
||||
retval.lr_end += amount;
|
||||
}
|
||||
|
||||
last = next + 1;
|
||||
}
|
||||
|
||||
if (retval.lr_end == -1) {
|
||||
const char *eol = strchr(last, '\n');
|
||||
|
||||
retval.lr_end = eol - msg;
|
||||
}
|
||||
|
||||
return retval;
|
||||
};
|
||||
struct line_range origin_in_full_msg(const char *msg, size_t len) const;;
|
||||
|
||||
intern_string_t lv_name;
|
||||
kind_t lv_kind;
|
||||
|
@ -29,13 +29,17 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <future>
|
||||
#include <algorithm>
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "k_merge_tree.h"
|
||||
#include "lnav_util.hh"
|
||||
#include "log_accel.hh"
|
||||
#include "relative_time.hh"
|
||||
#include "logfile_sub_source.hh"
|
||||
#include "command_executor.hh"
|
||||
#include "ansi_scrubber.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -43,6 +47,55 @@ bookmark_type_t logfile_sub_source::BM_ERRORS("error");
|
||||
bookmark_type_t logfile_sub_source::BM_WARNINGS("warning");
|
||||
bookmark_type_t logfile_sub_source::BM_FILES("");
|
||||
|
||||
static int pretty_sql_callback(exec_context &ec, sqlite3_stmt *stmt)
|
||||
{
|
||||
if (!sqlite3_stmt_busy(stmt)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ncols = sqlite3_column_count(stmt);
|
||||
|
||||
for (int lpc = 0; lpc < ncols; lpc++) {
|
||||
if (!ec.ec_accumulator.empty()) {
|
||||
ec.ec_accumulator.append(", ");
|
||||
}
|
||||
|
||||
const char *res = (const char *)sqlite3_column_text(stmt, lpc);
|
||||
if (res == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ec.ec_accumulator.append(res);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static future<string> pretty_pipe_callback(exec_context &ec,
|
||||
const string &cmdline,
|
||||
auto_fd &fd)
|
||||
{
|
||||
auto retval = std::async(std::launch::async, [&]() {
|
||||
char buffer[1024];
|
||||
ostringstream ss;
|
||||
ssize_t rc;
|
||||
|
||||
while ((rc = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
ss.write(buffer, rc);
|
||||
}
|
||||
|
||||
string retval = ss.str();
|
||||
|
||||
if (endswith(retval.c_str(), "\n")) {
|
||||
retval.resize(retval.length() - 1);
|
||||
}
|
||||
|
||||
return retval;
|
||||
});
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
logfile_sub_source::logfile_sub_source()
|
||||
: lss_flags(0),
|
||||
lss_force_rebuild(false),
|
||||
@ -102,7 +155,7 @@ vis_line_t logfile_sub_source::find_from_time(const struct timeval &start)
|
||||
void logfile_sub_source::text_value_for_line(textview_curses &tc,
|
||||
int row,
|
||||
string &value_out,
|
||||
bool raw)
|
||||
line_flags_t flags)
|
||||
{
|
||||
content_line_t line(0);
|
||||
|
||||
@ -110,19 +163,27 @@ void logfile_sub_source::text_value_for_line(textview_curses &tc,
|
||||
require((size_t)row < this->lss_filtered_index.size());
|
||||
|
||||
line = this->at(vis_line_t(row));
|
||||
this->lss_token_file = this->find(line);
|
||||
this->lss_token_line = this->lss_token_file->begin() + line;
|
||||
|
||||
if (raw) {
|
||||
this->lss_token_file->read_line(this->lss_token_line, value_out);
|
||||
if (flags & RF_RAW) {
|
||||
shared_ptr<logfile> lf = this->find(line);
|
||||
lf->read_line(lf->begin() + line, value_out);
|
||||
return;
|
||||
}
|
||||
|
||||
this->lss_token_flags = flags;
|
||||
this->lss_token_file = this->find(line);
|
||||
this->lss_token_line = this->lss_token_file->begin() + line;
|
||||
|
||||
this->lss_token_attrs.clear();
|
||||
this->lss_token_values.clear();
|
||||
this->lss_share_manager.invalidate_refs();
|
||||
this->lss_token_value =
|
||||
this->lss_token_file->read_line(this->lss_token_line);
|
||||
if (flags & text_sub_source::RF_FULL) {
|
||||
this->lss_token_file->read_full_message(this->lss_token_line,
|
||||
this->lss_token_value);
|
||||
} else {
|
||||
this->lss_token_value =
|
||||
this->lss_token_file->read_line(this->lss_token_line);
|
||||
}
|
||||
this->lss_token_shift_start = 0;
|
||||
this->lss_token_shift_size = 0;
|
||||
|
||||
@ -143,6 +204,17 @@ void logfile_sub_source::text_value_for_line(textview_curses &tc,
|
||||
if (this->lss_token_line->get_sub_offset() != 0) {
|
||||
this->lss_token_attrs.clear();
|
||||
}
|
||||
if (flags & RF_REWRITE) {
|
||||
exec_context ec(&this->lss_token_values, pretty_sql_callback, pretty_pipe_callback);
|
||||
string rewritten_line;
|
||||
|
||||
ec.ec_top_line = vis_line_t(row);
|
||||
add_ansi_vars(ec.ec_global_vars);
|
||||
add_global_vars(ec);
|
||||
format->rewrite(ec, sbr, this->lss_token_attrs, rewritten_line);
|
||||
this->lss_token_value.assign(rewritten_line);
|
||||
value_out = this->lss_token_value;
|
||||
}
|
||||
|
||||
if ((this->lss_token_file->is_time_adjusted() ||
|
||||
format->lf_timestamp_flags & ETF_MACHINE_ORIENTED) &&
|
||||
@ -289,10 +361,11 @@ void logfile_sub_source::text_attrs_for_line(textview_curses &lv,
|
||||
|
||||
value_out.emplace_back(lr, &view_curses::VC_STYLE, attrs);
|
||||
|
||||
for (vector<logline_value>::const_iterator lv_iter = line_values.begin();
|
||||
lv_iter != line_values.end();
|
||||
for (auto lv_iter = line_values.cbegin();
|
||||
lv_iter != line_values.cend();
|
||||
++lv_iter) {
|
||||
if (lv_iter->lv_sub_offset != this->lss_token_line->get_sub_offset() ||
|
||||
if ((!(this->lss_token_flags & RF_FULL) &&
|
||||
lv_iter->lv_sub_offset != this->lss_token_line->get_sub_offset()) ||
|
||||
!lv_iter->lv_origin.is_valid()) {
|
||||
continue;
|
||||
}
|
||||
@ -309,8 +382,13 @@ void logfile_sub_source::text_attrs_for_line(textview_curses &lv,
|
||||
int id_attrs = vc.attrs_for_ident(lv_iter->text_value(),
|
||||
lv_iter->text_length());
|
||||
|
||||
value_out.emplace_back(
|
||||
lv_iter->lv_origin, &view_curses::VC_STYLE, id_attrs);
|
||||
line_range ident_range = lv_iter->lv_origin;
|
||||
if (this->lss_token_flags & RF_FULL) {
|
||||
ident_range = lv_iter->origin_in_full_msg(
|
||||
this->lss_token_value.c_str(), this->lss_token_value.length());
|
||||
}
|
||||
|
||||
value_out.emplace_back(ident_range, &view_curses::VC_STYLE, id_attrs);
|
||||
}
|
||||
|
||||
if (this->lss_token_shift_size) {
|
||||
@ -344,12 +422,15 @@ void logfile_sub_source::text_attrs_for_line(textview_curses &lv,
|
||||
value_out.push_back(
|
||||
string_attr(lr, &view_curses::VC_GRAPHIC, graph));
|
||||
|
||||
bookmark_vector<vis_line_t> &bv_search = bm[&textview_curses::BM_SEARCH];
|
||||
if (!(this->lss_token_flags & RF_FULL)) {
|
||||
bookmark_vector<vis_line_t> &bv_search = bm[&textview_curses::BM_SEARCH];
|
||||
|
||||
if (binary_search(::begin(bv_search), ::end(bv_search), vis_line_t(row))) {
|
||||
lr.lr_start = 0;
|
||||
lr.lr_end = 1;
|
||||
value_out.emplace_back(lr, &view_curses::VC_STYLE, A_REVERSE);
|
||||
if (binary_search(::begin(bv_search), ::end(bv_search),
|
||||
vis_line_t(row))) {
|
||||
lr.lr_start = 0;
|
||||
lr.lr_end = 1;
|
||||
value_out.emplace_back(lr, &view_curses::VC_STYLE, A_REVERSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,19 +226,19 @@ public:
|
||||
void text_value_for_line(textview_curses &tc,
|
||||
int row,
|
||||
std::string &value_out,
|
||||
bool raw);
|
||||
line_flags_t flags);
|
||||
|
||||
void text_attrs_for_line(textview_curses &tc,
|
||||
int row,
|
||||
string_attrs_t &value_out);
|
||||
|
||||
size_t text_size_for_line(textview_curses &tc, int row, bool raw) {
|
||||
size_t text_size_for_line(textview_curses &tc, int row, line_flags_t flags) {
|
||||
size_t index = row % LINE_SIZE_CACHE_SIZE;
|
||||
|
||||
if (this->lss_line_size_cache[index].first != row) {
|
||||
std::string value;
|
||||
|
||||
this->text_value_for_line(tc, row, value, raw);
|
||||
this->text_value_for_line(tc, row, value, flags);
|
||||
this->lss_line_size_cache[index].second = value.size();
|
||||
this->lss_line_size_cache[index].first = row;
|
||||
}
|
||||
@ -680,6 +680,7 @@ private:
|
||||
bookmarks<content_line_t>::type lss_user_marks;
|
||||
std::map<content_line_t, bookmark_metadata> lss_user_mark_metadata;
|
||||
|
||||
line_flags_t lss_token_flags;
|
||||
std::shared_ptr<logfile> lss_token_file;
|
||||
std::string lss_token_value;
|
||||
string_attrs_t lss_token_attrs;
|
||||
|
@ -110,7 +110,7 @@ public:
|
||||
void text_value_for_line(textview_curses &tc,
|
||||
int row,
|
||||
std::string &value_out,
|
||||
bool no_scrub) {
|
||||
line_flags_t flags) {
|
||||
value_out = this->tds_lines[row].get_string();
|
||||
};
|
||||
|
||||
@ -119,7 +119,7 @@ public:
|
||||
value_out = this->tds_lines[line].get_attrs();
|
||||
};
|
||||
|
||||
size_t text_size_for_line(textview_curses &tc, int row, bool raw) {
|
||||
size_t text_size_for_line(textview_curses &tc, int row, line_flags_t flags) {
|
||||
return this->tds_lines[row].length();
|
||||
};
|
||||
|
||||
|
@ -41,7 +41,7 @@ void sigalrm_handler(int sig)
|
||||
}
|
||||
}
|
||||
|
||||
std::string pretty_printer::print() {
|
||||
void pretty_printer::append_to(attr_line_t &al) {
|
||||
pcre_context_static<30> pc;
|
||||
data_token_t dt;
|
||||
|
||||
@ -51,16 +51,16 @@ std::string pretty_printer::print() {
|
||||
|
||||
switch (dt) {
|
||||
case DT_XML_EMPTY_TAG:
|
||||
if (is_xml) {
|
||||
if (this->pp_is_xml && this->pp_line_length > 0) {
|
||||
this->start_new_line();
|
||||
}
|
||||
this->pp_values.push_back(el);
|
||||
if (is_xml) {
|
||||
if (this->pp_is_xml) {
|
||||
this->start_new_line();
|
||||
}
|
||||
continue;
|
||||
case DT_XML_OPEN_TAG:
|
||||
if (is_xml) {
|
||||
if (this->pp_is_xml) {
|
||||
this->start_new_line();
|
||||
this->write_element(el);
|
||||
this->descend();
|
||||
@ -100,8 +100,9 @@ std::string pretty_printer::print() {
|
||||
}
|
||||
break;
|
||||
case DT_WHITE:
|
||||
if (this->pp_values.empty() && this->pp_depth == 0) {
|
||||
// this->pp_leading_indent = el.e_capture.length();
|
||||
if (this->pp_values.empty() && this->pp_depth == 0 &&
|
||||
this->pp_line_length == 0) {
|
||||
this->pp_leading_indent = el.e_capture.length();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
@ -115,7 +116,14 @@ std::string pretty_printer::print() {
|
||||
}
|
||||
this->flush_values();
|
||||
|
||||
return this->pp_stream.str();
|
||||
attr_line_t combined;
|
||||
combined.get_string() = this->pp_stream.str();
|
||||
combined.get_attrs() = this->pp_attrs;
|
||||
|
||||
if (!al.empty()) {
|
||||
al.append("\n");
|
||||
}
|
||||
al.append(combined);
|
||||
}
|
||||
|
||||
void pretty_printer::convert_ip_address(const pretty_printer::element &el) {
|
||||
@ -170,33 +178,41 @@ void pretty_printer::convert_ip_address(const pretty_printer::element &el) {
|
||||
log_info("Reverse lookup in pretty-print view disabled");
|
||||
}
|
||||
}
|
||||
this->pp_stream << " " << ANSI_UNDERLINE_START <<
|
||||
"(" << result << ")" <<
|
||||
ANSI_NORM;
|
||||
ssize_t start_size = this->pp_stream.tellp();
|
||||
this->pp_stream << " (" << result << ")";
|
||||
struct line_range lr{(int) start_size + 1, (int) this->pp_stream.tellp()};
|
||||
this->pp_attrs.emplace_back(lr, &view_curses::VC_STYLE, A_UNDERLINE);
|
||||
}
|
||||
|
||||
void pretty_printer::write_element(const pretty_printer::element &el) {
|
||||
if (this->pp_leading_indent == 0 &&
|
||||
this->pp_line_length == 0 &&
|
||||
el.e_token == DT_WHITE) {
|
||||
if (this->pp_depth == 0) {
|
||||
this->pp_soft_indent += el.e_capture.length();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (this->pp_line_length == 0 && el.e_token == DT_LINE) {
|
||||
if (this->pp_line_length <= this->pp_leading_indent && el.e_token == DT_LINE) {
|
||||
this->pp_soft_indent = 0;
|
||||
return;
|
||||
}
|
||||
pcre_input &pi = this->pp_scanner->get_input();
|
||||
if (this->pp_line_length == 0) {
|
||||
this->append_indent();
|
||||
}
|
||||
ssize_t start_size = this->pp_stream.tellp();
|
||||
if (el.e_token == DT_QUOTED_STRING) {
|
||||
auto_mem<char> unquoted_str((char *)malloc(el.e_capture.length() + 1));
|
||||
const char *start = pi.get_substr_start(&el.e_capture);
|
||||
unquote(unquoted_str.in(), start, el.e_capture.length());
|
||||
data_scanner ds(unquoted_str.in());
|
||||
pretty_printer str_pp(&ds,
|
||||
string_attrs_t sa;
|
||||
pretty_printer str_pp(&ds, sa,
|
||||
this->pp_leading_indent + this->pp_depth * 4);
|
||||
std::string result = str_pp.print();
|
||||
if (result.find('\n') != std::string::npos) {
|
||||
attr_line_t result;
|
||||
str_pp.append_to(result);
|
||||
if (result.get_string().find('\n') != std::string::npos) {
|
||||
switch (start[0]) {
|
||||
case 'r':
|
||||
case 'u':
|
||||
@ -209,8 +225,8 @@ void pretty_printer::write_element(const pretty_printer::element &el) {
|
||||
}
|
||||
this->pp_stream
|
||||
<< std::endl
|
||||
<< result;
|
||||
if (!endswith(result.c_str(), "\n")) {
|
||||
<< result.get_string();
|
||||
if (!endswith(result.get_string().c_str(), "\n")) {
|
||||
this->pp_stream << std::endl;
|
||||
}
|
||||
this->pp_stream
|
||||
@ -221,14 +237,9 @@ void pretty_printer::write_element(const pretty_printer::element &el) {
|
||||
}
|
||||
} else {
|
||||
this->pp_stream << pi.get_substr(&el.e_capture);
|
||||
switch (el.e_token) {
|
||||
case DT_IPV4_ADDRESS:
|
||||
case DT_IPV6_ADDRESS:
|
||||
this->convert_ip_address(el);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
int shift_amount = start_size - el.e_capture.c_begin - this->pp_shift_accum;
|
||||
shift_string_attrs(this->pp_attrs, el.e_capture.c_begin, shift_amount);
|
||||
this->pp_shift_accum = start_size - el.e_capture.c_begin;
|
||||
}
|
||||
this->pp_line_length += el.e_capture.length();
|
||||
if (el.e_token == DT_LINE) {
|
||||
@ -238,7 +249,8 @@ void pretty_printer::write_element(const pretty_printer::element &el) {
|
||||
}
|
||||
|
||||
void pretty_printer::append_indent() {
|
||||
this->pp_stream << std::string(this->pp_leading_indent, ' ');
|
||||
this->pp_stream << std::string(this->pp_leading_indent + this->pp_soft_indent, ' ');
|
||||
this->pp_soft_indent = 0;
|
||||
if (this->pp_stream.tellp() == this->pp_leading_indent) {
|
||||
return;
|
||||
}
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include <deque>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <utility>
|
||||
#include "timer.hh"
|
||||
#include "ansi_scrubber.hh"
|
||||
#include "data_scanner.hh"
|
||||
@ -66,12 +66,10 @@ public:
|
||||
pcre_context::capture_t e_capture;
|
||||
};
|
||||
|
||||
pretty_printer(data_scanner *ds, int leading_indent=0)
|
||||
pretty_printer(data_scanner *ds, string_attrs_t sa, int leading_indent=0)
|
||||
: pp_leading_indent(leading_indent),
|
||||
pp_depth(0),
|
||||
pp_line_length(0),
|
||||
pp_scanner(ds),
|
||||
is_xml(false) {
|
||||
pp_attrs(sa) {
|
||||
this->pp_body_lines.push(0);
|
||||
|
||||
pcre_context_static<30> pc;
|
||||
@ -80,12 +78,12 @@ public:
|
||||
this->pp_scanner->reset();
|
||||
while (this->pp_scanner->tokenize2(pc, dt)) {
|
||||
if (dt == DT_XML_CLOSE_TAG) {
|
||||
is_xml = true;
|
||||
pp_is_xml = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::string print();
|
||||
void append_to(attr_line_t &al);
|
||||
|
||||
private:
|
||||
|
||||
@ -104,13 +102,16 @@ private:
|
||||
void write_element(const element &el);
|
||||
|
||||
int pp_leading_indent;
|
||||
int pp_depth;
|
||||
int pp_line_length;
|
||||
std::stack<int> pp_body_lines;
|
||||
int pp_depth{0};
|
||||
int pp_line_length{0};
|
||||
int pp_soft_indent{0};
|
||||
std::stack<int> pp_body_lines{};
|
||||
data_scanner *pp_scanner;
|
||||
string_attrs_t pp_attrs;
|
||||
std::ostringstream pp_stream;
|
||||
std::deque<element> pp_values;
|
||||
bool is_xml;
|
||||
std::deque<element> pp_values{};
|
||||
int pp_shift_accum{0};
|
||||
bool pp_is_xml{false};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -209,7 +209,7 @@ void add_view_text_possibilities(int context, const string &type, textview_curse
|
||||
++curr_line) {
|
||||
string line;
|
||||
|
||||
tss->text_value_for_line(*tc, curr_line, line);
|
||||
tss->text_value_for_line(*tc, curr_line, line, text_sub_source::RF_RAW);
|
||||
|
||||
add_text_possibilities(context, type, line);
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ public:
|
||||
return width;
|
||||
};
|
||||
|
||||
size_t text_size_for_line(textview_curses &tc, int row, bool raw) {
|
||||
size_t text_size_for_line(textview_curses &tc, int row, line_flags_t flags) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
@ -345,7 +345,7 @@ public:
|
||||
void text_value_for_line(textview_curses &tc,
|
||||
int row,
|
||||
std::string &value_out,
|
||||
bool no_scrub) {
|
||||
line_flags_t flags) {
|
||||
spectrogram_row &s_row = this->load_row(tc, row);
|
||||
|
||||
time_t row_time;
|
||||
|
@ -70,7 +70,7 @@ public:
|
||||
void text_value_for_line(textview_curses &tc,
|
||||
int line,
|
||||
std::string &value_out,
|
||||
bool raw = false)
|
||||
line_flags_t flags)
|
||||
{
|
||||
if (!this->tss_files.empty()) {
|
||||
std::shared_ptr<logfile> lf = this->current_file();
|
||||
@ -97,7 +97,7 @@ public:
|
||||
value_out.push_back(string_attr(lr, &logline::L_FILE, this->current_file().get()));
|
||||
};
|
||||
|
||||
size_t text_size_for_line(textview_curses &tc, int line, bool raw) {
|
||||
size_t text_size_for_line(textview_curses &tc, int line, line_flags_t flags) {
|
||||
size_t retval = 0;
|
||||
|
||||
if (!this->tss_files.empty()) {
|
||||
|
@ -58,10 +58,10 @@ bookmark_type_t textview_curses::BM_USER("user");
|
||||
bookmark_type_t textview_curses::BM_PARTITION("partition");
|
||||
bookmark_type_t textview_curses::BM_SEARCH("search");
|
||||
|
||||
string_attr_type textview_curses::SA_ORIGINAL_LINE;
|
||||
string_attr_type textview_curses::SA_BODY;
|
||||
string_attr_type textview_curses::SA_HIDDEN;
|
||||
string_attr_type textview_curses::SA_FORMAT;
|
||||
string_attr_type textview_curses::SA_ORIGINAL_LINE("original_line");
|
||||
string_attr_type textview_curses::SA_BODY("body");
|
||||
string_attr_type textview_curses::SA_HIDDEN("hidden");
|
||||
string_attr_type textview_curses::SA_FORMAT("format");
|
||||
|
||||
textview_curses::textview_curses()
|
||||
: tc_sub_source(NULL),
|
||||
|
@ -313,6 +313,20 @@ class text_sub_source {
|
||||
public:
|
||||
virtual ~text_sub_source() { };
|
||||
|
||||
enum {
|
||||
RB_RAW,
|
||||
RB_FULL,
|
||||
RB_REWRITE,
|
||||
};
|
||||
|
||||
enum {
|
||||
RF_RAW = (1L << RB_RAW),
|
||||
RF_FULL = (1L << RB_FULL),
|
||||
RF_REWRITE = (1L << RB_REWRITE),
|
||||
};
|
||||
|
||||
typedef long line_flags_t;
|
||||
|
||||
virtual void toggle_scrub(void) { };
|
||||
|
||||
/**
|
||||
@ -337,9 +351,9 @@ public:
|
||||
virtual void text_value_for_line(textview_curses &tc,
|
||||
int line,
|
||||
std::string &value_out,
|
||||
bool raw = false) = 0;
|
||||
line_flags_t flags = 0) = 0;
|
||||
|
||||
virtual size_t text_size_for_line(textview_curses &tc, int line, bool raw = false) = 0;
|
||||
virtual size_t text_size_for_line(textview_curses &tc, int line, line_flags_t raw = 0) = 0;
|
||||
|
||||
/**
|
||||
* Inform the source that the given line has been marked/unmarked. This
|
||||
@ -647,7 +661,7 @@ public:
|
||||
this->tc_sub_source->text_value_for_line(*this,
|
||||
line,
|
||||
value_out,
|
||||
true);
|
||||
text_sub_source::RF_RAW);
|
||||
retval = true;
|
||||
}
|
||||
|
||||
|
@ -224,25 +224,27 @@ attr_line_t &attr_line_t::with_ansi_string(const std::string &str)
|
||||
return *this;
|
||||
}
|
||||
|
||||
attr_line_t &attr_line_t::append(const attr_line_t &al, text_wrap_settings *tws)
|
||||
attr_line_t &attr_line_t::insert(size_t index, const attr_line_t &al, text_wrap_settings *tws)
|
||||
{
|
||||
size_t start_len = this->al_string.length();
|
||||
if (index < this->al_string.length()) {
|
||||
shift_string_attrs(this->al_attrs, index, al.al_string.length());
|
||||
}
|
||||
|
||||
this->al_string.append(al.al_string);
|
||||
this->al_string.insert(index, al.al_string);
|
||||
|
||||
for (auto &sa : al.al_attrs) {
|
||||
this->al_attrs.emplace_back(sa);
|
||||
|
||||
line_range &lr = this->al_attrs.back().sa_range;
|
||||
|
||||
lr.shift(0, start_len);
|
||||
lr.shift(0, index);
|
||||
if (lr.lr_end == -1) {
|
||||
lr.lr_end = this->al_string.length();
|
||||
lr.lr_end = index + al.al_string.length();
|
||||
}
|
||||
}
|
||||
|
||||
if (tws != nullptr && (int)this->al_string.length() > tws->tws_width) {
|
||||
ssize_t start_pos = start_len;
|
||||
ssize_t start_pos = index;
|
||||
ssize_t line_start = this->al_string.rfind('\n', start_pos);
|
||||
|
||||
if (line_start == (ssize_t)string::npos) {
|
||||
@ -251,7 +253,7 @@ attr_line_t &attr_line_t::append(const attr_line_t &al, text_wrap_settings *tws)
|
||||
line_start += 1;
|
||||
}
|
||||
|
||||
ssize_t line_len = start_len - line_start;
|
||||
ssize_t line_len = index - line_start;
|
||||
ssize_t usable_width = tws->tws_width - tws->tws_indent;
|
||||
ssize_t avail = max((ssize_t) 0, (ssize_t) tws->tws_width - line_len);
|
||||
|
||||
@ -328,7 +330,7 @@ attr_line_t &attr_line_t::append(const attr_line_t &al, text_wrap_settings *tws)
|
||||
attr_line_t attr_line_t::subline(size_t start, size_t len) const
|
||||
{
|
||||
if (len == std::string::npos) {
|
||||
len = this->length();
|
||||
len = this->al_string.length() - start;
|
||||
}
|
||||
|
||||
line_range lr{(int) start, (int) (start + len)};
|
||||
@ -342,8 +344,11 @@ attr_line_t attr_line_t::subline(size_t start, size_t len) const
|
||||
|
||||
retval.al_attrs.emplace_back(lr.intersection(sa.sa_range)
|
||||
.shift(lr.lr_start, -lr.lr_start),
|
||||
sa.sa_type,
|
||||
sa.sa_value);
|
||||
sa.sa_type, sa.sa_value);
|
||||
|
||||
line_range &last_lr = retval.al_attrs.back().sa_range;
|
||||
|
||||
ensure(last_lr.lr_end <= retval.al_string.length());
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
@ -56,6 +56,10 @@ string execute_any(exec_context &ec, const string &cmdline_with_mode)
|
||||
return "";
|
||||
}
|
||||
|
||||
void add_global_vars(exec_context &ec)
|
||||
{
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int c, retval = EXIT_SUCCESS;
|
||||
@ -157,10 +161,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (format.get() != NULL) {
|
||||
vector<logline_value> ll_values;
|
||||
string_attrs_t sa;
|
||||
vector<logline_value> ll_values;
|
||||
string_attrs_t sa;
|
||||
|
||||
if (format.get() != NULL) {
|
||||
format->annotate(sbr, sa, ll_values);
|
||||
body = find_string_attr_range(sa, &textview_curses::SA_BODY);
|
||||
}
|
||||
@ -179,10 +183,11 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (pretty_print) {
|
||||
data_scanner ds2(sub_line, body.lr_start, sub_line.length());
|
||||
pretty_printer pp(&ds2);
|
||||
pretty_printer pp(&ds2, sa);
|
||||
attr_line_t pretty_out;
|
||||
|
||||
string pretty_out = pp.print();
|
||||
fprintf(out, "\n--\n%s", pretty_out.c_str());
|
||||
pp.append_to(pretty_out);
|
||||
fprintf(out, "\n--\n%s", pretty_out.get_string().c_str());
|
||||
}
|
||||
|
||||
auto_mem<yajl_gen_t> gen(yajl_gen_free);
|
||||
|
@ -62,6 +62,10 @@ string execute_any(exec_context &ec, const string &cmdline_with_mode)
|
||||
return "";
|
||||
}
|
||||
|
||||
void add_global_vars(exec_context &ec)
|
||||
{
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int c, retval = EXIT_SUCCESS;
|
||||
dl_mode_t mode = MODE_NONE;
|
||||
|
@ -61,6 +61,10 @@ string execute_any(exec_context &ec, const string &cmdline_with_mode)
|
||||
return "";
|
||||
}
|
||||
|
||||
void add_global_vars(exec_context &ec)
|
||||
{
|
||||
}
|
||||
|
||||
struct exec_context {
|
||||
|
||||
};
|
||||
|
@ -38,6 +38,10 @@ std::string execute_any(exec_context &ec, const std::string &cmdline_with_mode)
|
||||
return "";
|
||||
}
|
||||
|
||||
void add_global_vars(exec_context &ec)
|
||||
{
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int retval = EXIT_SUCCESS;
|
||||
|
@ -614,21 +614,21 @@ check_output "pretty-printer is not working" <<EOF
|
||||
<response>
|
||||
<locale>en-US</locale>
|
||||
<requestid>ipInfo</requestid>
|
||||
<value id="ipv4Gateway" actions="enabled">198.51.100.253 (unknown)</value>
|
||||
<value id="ipv4Gateway" actions="enabled">198.51.100.253</value>
|
||||
<value id="ipv6Gateway" actions="enabled"/>
|
||||
<value id="ipv6Enabled" actions="enabled">true</value>
|
||||
<value id="ipv4Enabled" actions="enabled">true</value>
|
||||
<value id="name" actions="enabled">nic1</value>
|
||||
<value id="v4config" actions="enabled">
|
||||
<value id="defaultGateway" actions="enabled">0.0.0.0 (unknown)</value>
|
||||
<value id="defaultGateway" actions="enabled">0.0.0.0</value>
|
||||
<value id="updateable" actions="enabled">True</value>
|
||||
<value id="prefix" actions="enabled">22</value>
|
||||
<value id="mode" actions="enabled">dhcp</value>
|
||||
<value id="address" actions="enabled">198.51.100.110 (unknown)</value>
|
||||
<value id="address" actions="enabled">198.51.100.110</value>
|
||||
<value id="interface" actions="enabled">nic1</value>
|
||||
</value>
|
||||
<value id="v6config" actions="enabled">
|
||||
<value id="defaultGateway" actions="enabled">fe80::214:f609:19f7:6bf1 (unknown)</value>
|
||||
<value id="defaultGateway" actions="enabled">fe80::214:f609:19f7:6bf1</value>
|
||||
<value id="updateable" actions="enabled">True</value>
|
||||
<value id="interface" actions="enabled">nic1</value>
|
||||
<value id="dhcp" actions="enabled">False</value>
|
||||
@ -637,7 +637,7 @@ check_output "pretty-printer is not working" <<EOF
|
||||
<value id="origin" actions="enabled">other</value>
|
||||
<value id="status" actions="enabled">preferred</value>
|
||||
<value id="prefix" actions="enabled">64</value>
|
||||
<value id="address" actions="enabled">fe80::250:56ff:feaa:5abf (unknown)</value>
|
||||
<value id="address" actions="enabled">fe80::250:56ff:feaa:5abf</value>
|
||||
</value>
|
||||
</value>
|
||||
<value id="interfaceInfo" actions="enabled">
|
||||
|
@ -29,9 +29,9 @@ echo '2015-04-18T13:16:30.003 8.8.8.8 <foo>8.8.8.8</foo>9 8.8.8.8<1054 198.51.10
|
||||
run_test ${lnav_test} -n -c ":switch-to-view pretty"
|
||||
|
||||
check_output "pretty print not able to properly grok ipv4?" <<EOF
|
||||
2015-04-18T13:16:30.003 8.8.8.8 (google-public-dns-a.google.com)
|
||||
<foo>8.8.8.8 (google-public-dns-a.google.com)</foo>
|
||||
9 8.8.8.8 (google-public-dns-a.google.com)<1054 198.51.100.1546 544.9.8.7 98.542.241.99 19143.2.5.6
|
||||
2015-04-18T13:16:30.003 8.8.8.8
|
||||
<foo>8.8.8.8</foo>
|
||||
9 8.8.8.8<1054 198.51.100.1546 544.9.8.7 98.542.241.99 19143.2.5.6
|
||||
EOF
|
||||
|
||||
cat <<EOF
|
||||
|
@ -52,6 +52,10 @@ string execute_any(exec_context &ec, const string &cmdline_with_mode)
|
||||
return "";
|
||||
}
|
||||
|
||||
void add_global_vars(exec_context &ec)
|
||||
{
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int retval = EXIT_SUCCESS;
|
||||
|
Loading…
Reference in New Issue
Block a user