[textview] highlights that start from the beginning of the line are not working in the log view

The log view prefixes lines with some extra characters and they
were mistakenly being included when performing the highlight
regex.

Fixes #590
This commit is contained in:
Timothy Stack 2019-01-01 08:24:02 -08:00
parent 66ef968529
commit 7dfa0e9dd4
5 changed files with 97 additions and 89 deletions

View File

@ -155,17 +155,20 @@ struct highlighter {
void annotate(attr_line_t &al, int start) const {
const std::string &str = al.get_string();
string_attrs_t &sa = al.get_attrs();
// The line we pass to pcre_exec will be treated as the start when the
// carat (^) operator is used.
const char *line_start = &(str.c_str()[start]);
size_t re_end;
if (str.length() > 8192)
if ((str.length() - start) > 8192)
re_end = 8192;
else
re_end = str.length();
for (int off = start; off < (int)str.size(); ) {
re_end = str.length() - start;
for (int off = 0; off < (int)str.size() - start; ) {
int rc, matches[60];
rc = pcre_exec(this->h_code,
this->h_code_extra,
str.c_str(),
line_start,
re_end,
off,
0,
@ -175,12 +178,12 @@ struct highlighter {
struct line_range lr;
if (rc == 2) {
lr.lr_start = matches[2];
lr.lr_end = matches[3];
lr.lr_start = start + matches[2];
lr.lr_end = start + matches[3];
}
else {
lr.lr_start = matches[0];
lr.lr_end = matches[1];
lr.lr_start = start + matches[0];
lr.lr_end = start + matches[1];
}
if (lr.lr_end > lr.lr_start) {
@ -201,8 +204,8 @@ struct highlighter {
std::string h_pattern;
rgb_color h_fg;
rgb_color h_bg;
pcre * h_code;
pcre_extra * h_code_extra;
pcre *h_code;
pcre_extra *h_code_extra;
int h_attrs;
text_format_t h_text_format;
intern_string_t h_format_name;

View File

@ -744,6 +744,10 @@ void external_log_format::annotate(shared_buffer_ref &line,
pattern &pat = *this->elf_pattern_order[this->lf_fmt_lock];
if (!pat.p_pcre->match(pc, pi)) {
// A continued line still needs a body.
lr.lr_start = 0;
lr.lr_end = line.length();
sa.emplace_back(lr, &textview_curses::SA_BODY);
return;
}

View File

@ -198,73 +198,70 @@ void logfile_sub_source::text_value_for_line(textview_curses &tc,
format->scrub(value_out);
}
if (!this->lss_token_line->is_continued() ||
this->lss_token_line->get_sub_offset() != 0) {
shared_buffer_ref sbr;
shared_buffer_ref sbr;
sbr.share(this->lss_share_manager,
(char *)this->lss_token_value.c_str(), this->lss_token_value.size());
format->annotate(sbr, this->lss_token_attrs, this->lss_token_values);
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;
sbr.share(this->lss_share_manager,
(char *)this->lss_token_value.c_str(), this->lss_token_value.size());
format->annotate(sbr, this->lss_token_attrs, this->lss_token_values);
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;
}
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) &&
format->lf_date_time.dts_fmt_lock != -1) {
auto time_attr = find_string_attr(
this->lss_token_attrs, &logline::L_TIMESTAMP);
if (time_attr != this->lss_token_attrs.end()) {
const struct line_range time_range = time_attr->sa_range;
struct timeval adjusted_time;
struct exttm adjusted_tm;
char buffer[128];
const char *fmt;
ssize_t len;
if ((this->lss_token_file->is_time_adjusted() ||
format->lf_timestamp_flags & ETF_MACHINE_ORIENTED) &&
format->lf_date_time.dts_fmt_lock != -1) {
auto time_attr = find_string_attr(
this->lss_token_attrs, &logline::L_TIMESTAMP);
if (time_attr != this->lss_token_attrs.end()) {
const struct line_range time_range = time_attr->sa_range;
struct timeval adjusted_time;
struct exttm adjusted_tm;
char buffer[128];
const char *fmt;
ssize_t len;
if (format->lf_timestamp_flags & ETF_MACHINE_ORIENTED) {
format->lf_date_time.convert_to_timeval(
&this->lss_token_value.c_str()[time_range.lr_start],
time_range.length(),
format->get_timestamp_formats(),
adjusted_time);
fmt = "%Y-%m-%d %H:%M:%S.%f";
gmtime_r(&adjusted_time.tv_sec, &adjusted_tm.et_tm);
adjusted_tm.et_nsec = adjusted_time.tv_usec * 1000;
len = ftime_fmt(buffer, sizeof(buffer), fmt, adjusted_tm);
}
else {
adjusted_time = this->lss_token_line->get_timeval();
gmtime_r(&adjusted_time.tv_sec, &adjusted_tm.et_tm);
adjusted_tm.et_nsec = adjusted_time.tv_usec * 1000;
len = format->lf_date_time.ftime(buffer, sizeof(buffer), adjusted_tm);
}
if (len > time_range.length()) {
ssize_t padding = len - time_range.length();
value_out.insert(time_range.lr_start,
padding,
' ');
}
value_out.replace(time_range.lr_start,
len,
buffer,
len);
this->lss_token_shift_start = time_range.lr_start;
this->lss_token_shift_size = len - time_range.length();
if (format->lf_timestamp_flags & ETF_MACHINE_ORIENTED) {
format->lf_date_time.convert_to_timeval(
&this->lss_token_value.c_str()[time_range.lr_start],
time_range.length(),
format->get_timestamp_formats(),
adjusted_time);
fmt = "%Y-%m-%d %H:%M:%S.%f";
gmtime_r(&adjusted_time.tv_sec, &adjusted_tm.et_tm);
adjusted_tm.et_nsec = adjusted_time.tv_usec * 1000;
len = ftime_fmt(buffer, sizeof(buffer), fmt, adjusted_tm);
} else {
adjusted_time = this->lss_token_line->get_timeval();
gmtime_r(&adjusted_time.tv_sec, &adjusted_tm.et_tm);
adjusted_tm.et_nsec = adjusted_time.tv_usec * 1000;
len = format->lf_date_time.ftime(buffer, sizeof(buffer),
adjusted_tm);
}
if (len > time_range.length()) {
ssize_t padding = len - time_range.length();
value_out.insert(time_range.lr_start,
padding,
' ');
}
value_out.replace(time_range.lr_start,
len,
buffer,
len);
this->lss_token_shift_start = time_range.lr_start;
this->lss_token_shift_size = len - time_range.length();
}
}
@ -365,30 +362,28 @@ void logfile_sub_source::text_attrs_for_line(textview_curses &lv,
value_out.emplace_back(lr, &view_curses::VC_STYLE, attrs);
for (auto lv_iter = line_values.cbegin();
lv_iter != line_values.cend();
++lv_iter) {
for (const auto &line_value : line_values) {
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()) {
line_value.lv_sub_offset != this->lss_token_line->get_sub_offset()) ||
!line_value.lv_origin.is_valid()) {
continue;
}
if (lv_iter->lv_hidden) {
if (line_value.lv_hidden) {
value_out.emplace_back(
lv_iter->lv_origin, &textview_curses::SA_HIDDEN);
line_value.lv_origin, &textview_curses::SA_HIDDEN);
}
if (!lv_iter->lv_identifier || !lv_iter->lv_origin.is_valid()) {
if (!line_value.lv_identifier || !line_value.lv_origin.is_valid()) {
continue;
}
int id_attrs = vc.attrs_for_ident(lv_iter->text_value(),
lv_iter->text_length());
int id_attrs = vc.attrs_for_ident(line_value.text_value(),
line_value.text_length());
line_range ident_range = lv_iter->lv_origin;
line_range ident_range = line_value.lv_origin;
if (this->lss_token_flags & RF_FULL) {
ident_range = lv_iter->origin_in_full_msg(
ident_range = line_value.origin_in_full_msg(
this->lss_token_value.c_str(), this->lss_token_value.length());
}

View File

@ -284,7 +284,13 @@ void textview_curses::textview_value_for_row(vis_line_t row,
continue;
}
tc_highlight.second.annotate(value_out, internal_hl ? body.lr_start : 0);
// Internal highlights should only apply to the log message body so
// that we don't start highlighting other fields. User-provided
// highlights should apply only to the line itself and not any of the
// surrounding decorations that are added (for example, the file lines
// that are inserted at the beginning of the log view).
int start_pos = internal_hl ? body.lr_start : orig_line.lr_start;
tc_highlight.second.annotate(value_out, start_pos);
}
if (this->tc_hide_fields) {

View File

@ -844,9 +844,9 @@ cat ${test_dir}/logfile_syslog.0 | run_test ${lnav_test} -n \
check_output "querying against stdin is not working?" <<EOF
log_time
2018-11-03 09:23:38.000
2018-11-03 09:23:38.000
2018-11-03 09:23:38.000
2019-11-03 09:23:38.000
2019-11-03 09:23:38.000
2019-11-03 09:23:38.000
EOF
@ -855,7 +855,7 @@ cat ${test_dir}/logfile_syslog.0 | run_test ${lnav_test} -n \
check_output "single result is not working?" <<EOF
log_time
2018-11-03 09:47:02.000
2019-11-03 09:47:02.000
EOF
# Create a dummy database for the next couple of tests to consume.