mirror of
https://github.com/tstack/lnav.git
synced 2024-09-11 13:05:51 +03:00
[listview] scroll within overlay
This commit is contained in:
parent
f2ec975b1c
commit
7c8d32308a
5
NEWS.md
5
NEWS.md
@ -73,6 +73,11 @@ Interface changes:
|
||||
alternation is also now done in groups of two rows instead
|
||||
of only a single row. Numbers are also rendered using the
|
||||
"number" theme style as well.
|
||||
* The log message overlay in the LOG view is now limited
|
||||
2/3rds of the height and supports scrolling. The "alt-text"
|
||||
theme style is also used to draw the overlay contents now
|
||||
as well. (The overlay is used to display the parser
|
||||
details, comments, and annotations.)
|
||||
|
||||
Breaking changes:
|
||||
* Removed the `-w` command-line option. This option was
|
||||
|
@ -278,19 +278,23 @@ breadcrumb_curses::handle_key(int ch)
|
||||
retval = true;
|
||||
break;
|
||||
case KEY_NPAGE:
|
||||
this->bc_match_view.shift_selection(3);
|
||||
this->bc_match_view.shift_selection(
|
||||
listview_curses::shift_amount_t::down_page);
|
||||
retval = true;
|
||||
break;
|
||||
case KEY_PPAGE:
|
||||
this->bc_match_view.shift_selection(-3);
|
||||
this->bc_match_view.shift_selection(
|
||||
listview_curses::shift_amount_t::up_page);
|
||||
retval = true;
|
||||
break;
|
||||
case KEY_UP:
|
||||
this->bc_match_view.shift_selection(-1);
|
||||
this->bc_match_view.shift_selection(
|
||||
listview_curses::shift_amount_t::up_line);
|
||||
retval = true;
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
this->bc_match_view.shift_selection(1);
|
||||
this->bc_match_view.shift_selection(
|
||||
listview_curses::shift_amount_t::down_line);
|
||||
retval = true;
|
||||
break;
|
||||
case 0x7f:
|
||||
@ -371,40 +375,55 @@ breadcrumb_curses::perform_selection(
|
||||
}
|
||||
|
||||
bool
|
||||
breadcrumb_curses::search_overlay_source::list_value_for_overlay(
|
||||
const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
vis_line_t line,
|
||||
attr_line_t& value_out)
|
||||
breadcrumb_curses::search_overlay_source::list_static_overlay(
|
||||
const listview_curses& lv, int y, int bottom, attr_line_t& value_out)
|
||||
{
|
||||
if (y == 0) {
|
||||
auto* parent = this->sos_parent;
|
||||
auto sel_opt = parent->bc_focused_crumbs
|
||||
| lnav::itertools::nth(parent->bc_selected_crumb);
|
||||
auto exp_input = sel_opt
|
||||
| lnav::itertools::map(&breadcrumb::crumb::c_expected_input)
|
||||
| lnav::itertools::unwrap_or(
|
||||
breadcrumb::crumb::expected_input_t::exact);
|
||||
if (y != 0) {
|
||||
return false;
|
||||
}
|
||||
auto* parent = this->sos_parent;
|
||||
auto sel_opt = parent->bc_focused_crumbs
|
||||
| lnav::itertools::nth(parent->bc_selected_crumb);
|
||||
auto exp_input = sel_opt
|
||||
| lnav::itertools::map(&breadcrumb::crumb::c_expected_input)
|
||||
| lnav::itertools::unwrap_or(
|
||||
breadcrumb::crumb::expected_input_t::exact);
|
||||
|
||||
value_out.with_attr_for_all(VC_STYLE.value(text_attrs{A_UNDERLINE}));
|
||||
value_out.with_attr_for_all(VC_STYLE.value(text_attrs{A_UNDERLINE}));
|
||||
|
||||
if (!parent->bc_current_search.empty()) {
|
||||
value_out = parent->bc_current_search;
|
||||
if (!parent->bc_current_search.empty()) {
|
||||
value_out = parent->bc_current_search;
|
||||
|
||||
role_t combobox_role = role_t::VCR_STATUS;
|
||||
switch (exp_input) {
|
||||
case breadcrumb::crumb::expected_input_t::exact:
|
||||
if (parent->bc_similar_values.empty()) {
|
||||
combobox_role = role_t::VCR_ALERT_STATUS;
|
||||
}
|
||||
break;
|
||||
case breadcrumb::crumb::expected_input_t::index: {
|
||||
size_t index;
|
||||
role_t combobox_role = role_t::VCR_STATUS;
|
||||
switch (exp_input) {
|
||||
case breadcrumb::crumb::expected_input_t::exact:
|
||||
if (parent->bc_similar_values.empty()) {
|
||||
combobox_role = role_t::VCR_ALERT_STATUS;
|
||||
}
|
||||
break;
|
||||
case breadcrumb::crumb::expected_input_t::index: {
|
||||
size_t index;
|
||||
|
||||
if (sscanf(parent->bc_current_search.c_str(), "%zu", &index)
|
||||
!= 1
|
||||
|| index < 0
|
||||
if (sscanf(parent->bc_current_search.c_str(), "%zu", &index)
|
||||
!= 1
|
||||
|| index < 0
|
||||
|| (index
|
||||
>= (sel_opt | lnav::itertools::map([](const auto& cr) {
|
||||
return cr->c_possible_range.value_or(0);
|
||||
})
|
||||
| lnav::itertools::unwrap_or(size_t{0}))))
|
||||
{
|
||||
combobox_role = role_t::VCR_ALERT_STATUS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case breadcrumb::crumb::expected_input_t::index_or_exact: {
|
||||
size_t index;
|
||||
|
||||
if (sscanf(parent->bc_current_search.c_str(), "%zu", &index)
|
||||
== 1)
|
||||
{
|
||||
if (index < 0
|
||||
|| (index
|
||||
>= (sel_opt
|
||||
| lnav::itertools::map([](const auto& cr) {
|
||||
@ -414,46 +433,26 @@ breadcrumb_curses::search_overlay_source::list_value_for_overlay(
|
||||
{
|
||||
combobox_role = role_t::VCR_ALERT_STATUS;
|
||||
}
|
||||
break;
|
||||
} else if (parent->bc_similar_values.empty()) {
|
||||
combobox_role = role_t::VCR_ALERT_STATUS;
|
||||
}
|
||||
case breadcrumb::crumb::expected_input_t::index_or_exact: {
|
||||
size_t index;
|
||||
|
||||
if (sscanf(parent->bc_current_search.c_str(), "%zu", &index)
|
||||
== 1)
|
||||
{
|
||||
if (index < 0
|
||||
|| (index
|
||||
>= (sel_opt
|
||||
| lnav::itertools::map([](const auto& cr) {
|
||||
return cr->c_possible_range.value_or(
|
||||
0);
|
||||
})
|
||||
| lnav::itertools::unwrap_or(size_t{0}))))
|
||||
{
|
||||
combobox_role = role_t::VCR_ALERT_STATUS;
|
||||
}
|
||||
} else if (parent->bc_similar_values.empty()) {
|
||||
combobox_role = role_t::VCR_ALERT_STATUS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case breadcrumb::crumb::expected_input_t::anything:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
value_out.with_attr_for_all(VC_ROLE.value(combobox_role));
|
||||
return true;
|
||||
case breadcrumb::crumb::expected_input_t::anything:
|
||||
break;
|
||||
}
|
||||
if (parent->bc_selected_crumb) {
|
||||
auto& selected_crumb_ref
|
||||
= parent->bc_focused_crumbs[parent->bc_selected_crumb.value()];
|
||||
value_out.with_attr_for_all(VC_ROLE.value(combobox_role));
|
||||
return true;
|
||||
}
|
||||
if (parent->bc_selected_crumb) {
|
||||
auto& selected_crumb_ref
|
||||
= parent->bc_focused_crumbs[parent->bc_selected_crumb.value()];
|
||||
|
||||
if (!selected_crumb_ref.c_search_placeholder.empty()) {
|
||||
value_out = selected_crumb_ref.c_search_placeholder;
|
||||
value_out.with_attr_for_all(
|
||||
VC_ROLE.value(role_t::VCR_INACTIVE_STATUS));
|
||||
return true;
|
||||
}
|
||||
if (!selected_crumb_ref.c_search_placeholder.empty()) {
|
||||
value_out = selected_crumb_ref.c_search_placeholder;
|
||||
value_out.with_attr_for_all(
|
||||
VC_ROLE.value(role_t::VCR_INACTIVE_STATUS));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,11 +73,10 @@ public:
|
||||
private:
|
||||
class search_overlay_source : public list_overlay_source {
|
||||
public:
|
||||
bool list_value_for_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
vis_line_t line,
|
||||
attr_line_t& value_out) override;
|
||||
bool list_static_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
attr_line_t& value_out) override;
|
||||
|
||||
breadcrumb_curses* sos_parent{nullptr};
|
||||
};
|
||||
|
@ -288,15 +288,15 @@ db_label_source::row_for_time(struct timeval time_bucket)
|
||||
return nonstd::nullopt;
|
||||
}
|
||||
|
||||
size_t
|
||||
db_overlay_source::list_overlay_count(const listview_curses& lv)
|
||||
void
|
||||
db_overlay_source::list_value_for_overlay(const listview_curses& lv,
|
||||
vis_line_t row,
|
||||
std::vector<attr_line_t>& value_out)
|
||||
{
|
||||
size_t retval = 1;
|
||||
|
||||
if (!this->dos_active || lv.get_inner_height() == 0) {
|
||||
this->dos_lines.clear();
|
||||
|
||||
return retval;
|
||||
return;
|
||||
}
|
||||
|
||||
auto& vc = view_colors::singleton();
|
||||
@ -307,7 +307,6 @@ db_overlay_source::list_overlay_count(const listview_curses& lv)
|
||||
|
||||
lv.get_dimensions(height, width);
|
||||
|
||||
this->dos_lines.clear();
|
||||
for (size_t col = 0; col < cols.size(); col++) {
|
||||
const char* col_value = cols[col];
|
||||
size_t col_len = strlen(col_value);
|
||||
@ -327,21 +326,21 @@ db_overlay_source::list_overlay_count(const listview_curses& lv)
|
||||
{
|
||||
const std::string& header
|
||||
= this->dos_labels->dls_headers[col].hm_name;
|
||||
this->dos_lines.emplace_back(" JSON Column: " + header);
|
||||
value_out.emplace_back(" JSON Column: " + header);
|
||||
|
||||
retval += 1;
|
||||
}
|
||||
|
||||
stacked_bar_chart<std::string> chart;
|
||||
int start_line = this->dos_lines.size();
|
||||
int start_line = value_out.size();
|
||||
|
||||
chart.with_stacking_enabled(false).with_margins(3, 0);
|
||||
|
||||
for (auto& jpw_value : jpw.jpw_values) {
|
||||
this->dos_lines.emplace_back(" " + jpw_value.wt_ptr + " = "
|
||||
+ jpw_value.wt_value);
|
||||
value_out.emplace_back(" " + jpw_value.wt_ptr + " = "
|
||||
+ jpw_value.wt_value);
|
||||
|
||||
string_attrs_t& sa = this->dos_lines.back().get_attrs();
|
||||
string_attrs_t& sa = value_out.back().get_attrs();
|
||||
struct line_range lr(1, 2);
|
||||
|
||||
sa.emplace_back(lr, VC_GRAPHIC.value(ACS_LTEE));
|
||||
@ -376,7 +375,7 @@ db_overlay_source::list_overlay_count(const listview_curses& lv)
|
||||
auto num_scan_res = scn::scan_value<double>(iter->wt_value);
|
||||
|
||||
if (num_scan_res) {
|
||||
auto& sa = this->dos_lines[curr_line].get_attrs();
|
||||
auto& sa = value_out[curr_line].get_attrs();
|
||||
int left = 3;
|
||||
|
||||
chart.chart_attrs_for_value(
|
||||
@ -387,9 +386,9 @@ db_overlay_source::list_overlay_count(const listview_curses& lv)
|
||||
}
|
||||
|
||||
if (retval > 1) {
|
||||
this->dos_lines.emplace_back("");
|
||||
value_out.emplace_back("");
|
||||
|
||||
string_attrs_t& sa = this->dos_lines.back().get_attrs();
|
||||
string_attrs_t& sa = value_out.back().get_attrs();
|
||||
struct line_range lr(1, 2);
|
||||
|
||||
sa.emplace_back(lr, VC_GRAPHIC.value(ACS_LLCORNER));
|
||||
@ -399,66 +398,55 @@ db_overlay_source::list_overlay_count(const listview_curses& lv)
|
||||
|
||||
retval += 1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool
|
||||
db_overlay_source::list_value_for_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
vis_line_t row,
|
||||
attr_line_t& value_out)
|
||||
db_overlay_source::list_static_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
attr_line_t& value_out)
|
||||
{
|
||||
if (y == 0) {
|
||||
this->list_overlay_count(lv);
|
||||
std::string& line = value_out.get_string();
|
||||
db_label_source* dls = this->dos_labels;
|
||||
string_attrs_t& sa = value_out.get_attrs();
|
||||
|
||||
for (size_t lpc = 0; lpc < this->dos_labels->dls_headers.size(); lpc++)
|
||||
{
|
||||
auto actual_col_size
|
||||
= std::min(dls->dls_max_column_width,
|
||||
dls->dls_headers[lpc].hm_column_size);
|
||||
std::string cell_title = dls->dls_headers[lpc].hm_name;
|
||||
|
||||
truncate_to(cell_title, dls->dls_max_column_width);
|
||||
|
||||
auto cell_length
|
||||
= utf8_string_length(cell_title).unwrapOr(actual_col_size);
|
||||
int before, total_fill = actual_col_size - cell_length;
|
||||
auto line_len_before = line.length();
|
||||
|
||||
before = total_fill / 2;
|
||||
total_fill -= before;
|
||||
line.append(before, ' ');
|
||||
line.append(cell_title);
|
||||
line.append(total_fill, ' ');
|
||||
line.append(1, ' ');
|
||||
|
||||
struct line_range header_range(line_len_before, line.length());
|
||||
|
||||
text_attrs attrs;
|
||||
if (this->dos_labels->dls_headers[lpc].hm_graphable) {
|
||||
attrs = dls->dls_headers[lpc].hm_title_attrs
|
||||
| text_attrs{A_REVERSE};
|
||||
} else {
|
||||
attrs.ta_attrs = A_UNDERLINE;
|
||||
}
|
||||
sa.emplace_back(header_range, VC_STYLE.value(text_attrs{attrs}));
|
||||
}
|
||||
|
||||
struct line_range lr(0);
|
||||
|
||||
sa.emplace_back(lr, VC_STYLE.value(text_attrs{A_BOLD | A_UNDERLINE}));
|
||||
return true;
|
||||
} else if (this->dos_active && y >= 2
|
||||
&& ((size_t) y) < (this->dos_lines.size() + 2))
|
||||
{
|
||||
value_out = this->dos_lines[y - 2];
|
||||
return true;
|
||||
if (y != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
auto& line = value_out.get_string();
|
||||
auto* dls = this->dos_labels;
|
||||
auto& sa = value_out.get_attrs();
|
||||
|
||||
for (size_t lpc = 0; lpc < this->dos_labels->dls_headers.size(); lpc++) {
|
||||
auto actual_col_size = std::min(dls->dls_max_column_width,
|
||||
dls->dls_headers[lpc].hm_column_size);
|
||||
std::string cell_title = dls->dls_headers[lpc].hm_name;
|
||||
|
||||
truncate_to(cell_title, dls->dls_max_column_width);
|
||||
|
||||
auto cell_length
|
||||
= utf8_string_length(cell_title).unwrapOr(actual_col_size);
|
||||
int before, total_fill = actual_col_size - cell_length;
|
||||
auto line_len_before = line.length();
|
||||
|
||||
before = total_fill / 2;
|
||||
total_fill -= before;
|
||||
line.append(before, ' ');
|
||||
line.append(cell_title);
|
||||
line.append(total_fill, ' ');
|
||||
line.append(1, ' ');
|
||||
|
||||
struct line_range header_range(line_len_before, line.length());
|
||||
|
||||
text_attrs attrs;
|
||||
if (this->dos_labels->dls_headers[lpc].hm_graphable) {
|
||||
attrs
|
||||
= dls->dls_headers[lpc].hm_title_attrs | text_attrs{A_REVERSE};
|
||||
} else {
|
||||
attrs.ta_attrs = A_UNDERLINE;
|
||||
}
|
||||
sa.emplace_back(header_range, VC_STYLE.value(text_attrs{attrs}));
|
||||
}
|
||||
|
||||
struct line_range lr(0);
|
||||
|
||||
sa.emplace_back(lr, VC_STYLE.value(text_attrs{A_BOLD | A_UNDERLINE}));
|
||||
return true;
|
||||
}
|
||||
|
@ -130,16 +130,16 @@ public:
|
||||
|
||||
class db_overlay_source : public list_overlay_source {
|
||||
public:
|
||||
size_t list_overlay_count(const listview_curses& lv);
|
||||
bool list_static_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
attr_line_t& value_out) override;
|
||||
|
||||
bool list_value_for_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
vis_line_t row,
|
||||
attr_line_t& value_out) override;
|
||||
void list_value_for_overlay(const listview_curses& lv,
|
||||
vis_line_t line,
|
||||
std::vector<attr_line_t>& value_out) override;
|
||||
|
||||
bool dos_active{false};
|
||||
db_label_source* dos_labels{nullptr};
|
||||
std::vector<attr_line_t> dos_lines;
|
||||
};
|
||||
#endif
|
||||
|
@ -77,8 +77,6 @@ field_overlay_source::build_field_lines(const listview_curses& lv,
|
||||
display = display || this->fos_contexts.top().c_show;
|
||||
}
|
||||
|
||||
this->build_meta_line(lv, this->fos_lines, row);
|
||||
|
||||
if (!display) {
|
||||
return;
|
||||
}
|
||||
@ -218,7 +216,7 @@ field_overlay_source::build_field_lines(const listview_curses& lv,
|
||||
}
|
||||
|
||||
if ((!this->fos_contexts.empty() && this->fos_contexts.top().c_show)
|
||||
|| diff_tv.tv_sec > 0)
|
||||
|| diff_tv.tv_sec > 0 || ll->is_time_skewed())
|
||||
{
|
||||
this->fos_lines.emplace_back(time_line);
|
||||
}
|
||||
@ -462,11 +460,13 @@ field_overlay_source::build_meta_line(const listview_curses& lv,
|
||||
&& (!line_meta_opt
|
||||
|| line_meta_opt.value()->bm_annotations.la_pairs.empty()))
|
||||
{
|
||||
auto anno_msg = attr_line_t(" ")
|
||||
.append(":memo:"_emoji)
|
||||
.append(" Annotations available, use ")
|
||||
.append(":annotate"_quoted_code)
|
||||
.append(" to apply them to this line");
|
||||
auto anno_msg
|
||||
= attr_line_t(" ")
|
||||
.append(":memo:"_emoji)
|
||||
.append(" Annotations available, use ")
|
||||
.append(":annotate"_quoted_code)
|
||||
.append(" to apply them to this line")
|
||||
.with_attr_for_all(VC_ROLE.value(role_t::VCR_COMMENT));
|
||||
|
||||
dst.emplace_back(anno_msg);
|
||||
}
|
||||
@ -600,10 +600,6 @@ field_overlay_source::build_meta_line(const listview_curses& lv,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dst.size() > 30) {
|
||||
dst.resize(30);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -619,38 +615,36 @@ field_overlay_source::add_key_line_attrs(int key_size, bool last_line)
|
||||
sa.emplace_back(lr, VC_STYLE.value(text_attrs{A_BOLD}));
|
||||
}
|
||||
|
||||
bool
|
||||
field_overlay_source::list_value_for_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
vis_line_t row,
|
||||
attr_line_t& value_out)
|
||||
void
|
||||
field_overlay_source::list_value_for_overlay(
|
||||
const listview_curses& lv,
|
||||
vis_line_t row,
|
||||
std::vector<attr_line_t>& value_out)
|
||||
{
|
||||
if (y == 0) {
|
||||
this->fos_meta_lines.clear();
|
||||
this->fos_meta_lines_row = -1_vl;
|
||||
if (row == lv.get_selection()) {
|
||||
this->build_field_lines(lv, row);
|
||||
return false;
|
||||
value_out = this->fos_lines;
|
||||
}
|
||||
|
||||
if (1 <= y && y <= (int) this->fos_lines.size()) {
|
||||
value_out = this->fos_lines[y - 1];
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this->fos_meta_lines.empty() && this->fos_meta_lines_row == row - 1_vl)
|
||||
{
|
||||
value_out = this->fos_meta_lines.front();
|
||||
this->fos_meta_lines.erase(this->fos_meta_lines.begin());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (row < lv.get_inner_height()) {
|
||||
this->fos_meta_lines.clear();
|
||||
this->build_meta_line(lv, this->fos_meta_lines, row);
|
||||
this->fos_meta_lines_row = row;
|
||||
}
|
||||
|
||||
return false;
|
||||
this->build_meta_line(lv, value_out, row);
|
||||
}
|
||||
|
||||
nonstd::optional<attr_line_t>
|
||||
field_overlay_source::list_header_for_overlay(const listview_curses& lv,
|
||||
vis_line_t vl)
|
||||
{
|
||||
attr_line_t retval;
|
||||
|
||||
retval.append(this->fos_lss.get_filename_offset(), ' ');
|
||||
if (this->fos_contexts.top().c_show) {
|
||||
return retval
|
||||
.appendf(FMT_STRING("\u258C Line {:L} parser details. "
|
||||
"(Press '"),
|
||||
(int) vl)
|
||||
.append("p"_hotkey)
|
||||
.append("' to toggle this view)");
|
||||
}
|
||||
|
||||
return retval.append("\u258C Line ")
|
||||
.append(lnav::roles::number(fmt::format(FMT_STRING("{:L}"), (int) vl)))
|
||||
.append(" metadata");
|
||||
}
|
||||
|
@ -55,11 +55,12 @@ public:
|
||||
this->fos_meta_lines_row = -1_vl;
|
||||
}
|
||||
|
||||
bool list_value_for_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
nonstd::optional<attr_line_t> list_header_for_overlay(
|
||||
const listview_curses& lv, vis_line_t vl) override;
|
||||
|
||||
void list_value_for_overlay(const listview_curses& lv,
|
||||
vis_line_t row,
|
||||
attr_line_t& value_out) override;
|
||||
std::vector<attr_line_t>& value_out) override;
|
||||
|
||||
void build_field_lines(const listview_curses& lv, vis_line_t row);
|
||||
void build_meta_line(const listview_curses& lv,
|
||||
|
@ -388,45 +388,44 @@ spinner_index()
|
||||
}
|
||||
|
||||
bool
|
||||
files_overlay_source::list_value_for_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
vis_line_t line,
|
||||
attr_line_t& value_out)
|
||||
files_overlay_source::list_static_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
attr_line_t& value_out)
|
||||
{
|
||||
if (y == 0) {
|
||||
static const char PROG[] = "-\\|/";
|
||||
constexpr size_t PROG_SIZE = sizeof(PROG) - 1;
|
||||
|
||||
auto& fc = lnav_data.ld_active_files;
|
||||
auto fc_prog = fc.fc_progress;
|
||||
safe::WriteAccess<safe_scan_progress> sp(*fc_prog);
|
||||
|
||||
if (!sp->sp_extractions.empty()) {
|
||||
const auto& prog = sp->sp_extractions.front();
|
||||
|
||||
value_out.with_ansi_string(fmt::format(
|
||||
"{} Extracting " ANSI_COLOR(COLOR_CYAN) "{}" ANSI_NORM
|
||||
"... {:>8}/{}",
|
||||
PROG[spinner_index() % PROG_SIZE],
|
||||
prog.ep_path.filename().string(),
|
||||
humanize::file_size(prog.ep_out_size,
|
||||
humanize::alignment::none),
|
||||
humanize::file_size(prog.ep_total_size,
|
||||
humanize::alignment::none)));
|
||||
return true;
|
||||
}
|
||||
if (!sp->sp_tailers.empty()) {
|
||||
auto first_iter = sp->sp_tailers.begin();
|
||||
|
||||
value_out.with_ansi_string(fmt::format(
|
||||
"{} Connecting to " ANSI_COLOR(COLOR_CYAN) "{}" ANSI_NORM
|
||||
": {}",
|
||||
PROG[spinner_index() % PROG_SIZE],
|
||||
first_iter->first,
|
||||
first_iter->second.tp_message));
|
||||
return true;
|
||||
}
|
||||
if (y != 0) {
|
||||
return false;
|
||||
}
|
||||
static const char PROG[] = "-\\|/";
|
||||
constexpr size_t PROG_SIZE = sizeof(PROG) - 1;
|
||||
|
||||
auto& fc = lnav_data.ld_active_files;
|
||||
auto fc_prog = fc.fc_progress;
|
||||
safe::WriteAccess<safe_scan_progress> sp(*fc_prog);
|
||||
|
||||
if (!sp->sp_extractions.empty()) {
|
||||
const auto& prog = sp->sp_extractions.front();
|
||||
|
||||
value_out.with_ansi_string(fmt::format(
|
||||
"{} Extracting " ANSI_COLOR(COLOR_CYAN) "{}" ANSI_NORM
|
||||
"... {:>8}/{}",
|
||||
PROG[spinner_index() % PROG_SIZE],
|
||||
prog.ep_path.filename().string(),
|
||||
humanize::file_size(prog.ep_out_size, humanize::alignment::none),
|
||||
humanize::file_size(prog.ep_total_size,
|
||||
humanize::alignment::none)));
|
||||
return true;
|
||||
}
|
||||
if (!sp->sp_tailers.empty()) {
|
||||
auto first_iter = sp->sp_tailers.begin();
|
||||
|
||||
value_out.with_ansi_string(fmt::format(
|
||||
"{} Connecting to " ANSI_COLOR(COLOR_CYAN) "{}" ANSI_NORM ": {}",
|
||||
PROG[spinner_index() % PROG_SIZE],
|
||||
first_iter->first,
|
||||
first_iter->second.tp_message));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -64,17 +64,15 @@ public:
|
||||
};
|
||||
|
||||
struct files_overlay_source : public list_overlay_source {
|
||||
bool list_value_for_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
vis_line_t line,
|
||||
attr_line_t& value_out) override;
|
||||
bool list_static_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
attr_line_t& value_out) override;
|
||||
};
|
||||
|
||||
namespace files_model {
|
||||
|
||||
struct no_selection {
|
||||
};
|
||||
struct no_selection {};
|
||||
|
||||
template<typename C, typename T>
|
||||
struct selection_base {
|
||||
@ -99,13 +97,11 @@ struct error_selection
|
||||
struct other_selection
|
||||
: public selection_base<
|
||||
other_selection,
|
||||
std::map<std::string, other_file_descriptor>::iterator> {
|
||||
};
|
||||
std::map<std::string, other_file_descriptor>::iterator> {};
|
||||
|
||||
struct file_selection
|
||||
: public selection_base<file_selection,
|
||||
std::vector<std::shared_ptr<logfile>>::iterator> {
|
||||
};
|
||||
std::vector<std::shared_ptr<logfile>>::iterator> {};
|
||||
|
||||
using files_list_selection = mapbox::util::
|
||||
variant<no_selection, error_selection, other_selection, file_selection>;
|
||||
|
@ -94,11 +94,13 @@ listview_curses::reload_data()
|
||||
{
|
||||
if (this->lv_source == nullptr) {
|
||||
this->lv_top = 0_vl;
|
||||
this->lv_focused_overlay_top = 0_vl;
|
||||
this->lv_left = 0;
|
||||
} else {
|
||||
if (this->lv_top >= this->get_inner_height()) {
|
||||
this->lv_top
|
||||
= std::max(0_vl, vis_line_t(this->get_inner_height() - 1));
|
||||
this->lv_focused_overlay_top = 0_vl;
|
||||
}
|
||||
if (this->lv_selectable) {
|
||||
if (this->get_inner_height() == 0) {
|
||||
@ -156,25 +158,22 @@ listview_curses::handle_key(int ch)
|
||||
case '\r':
|
||||
case 'j':
|
||||
case KEY_DOWN:
|
||||
if (this->is_selectable()) {
|
||||
this->shift_selection(1);
|
||||
} else {
|
||||
this->shift_top(1_vl);
|
||||
}
|
||||
this->shift_selection(shift_amount_t::down_line);
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
case KEY_UP:
|
||||
if (this->is_selectable()) {
|
||||
this->shift_selection(-1);
|
||||
} else {
|
||||
this->shift_top(-1_vl);
|
||||
}
|
||||
this->shift_selection(shift_amount_t::up_line);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
case KEY_BACKSPACE:
|
||||
case KEY_PPAGE:
|
||||
if (this->lv_focused_overlay_top != 0_vl) {
|
||||
this->shift_selection(shift_amount_t::up_page);
|
||||
break;
|
||||
}
|
||||
|
||||
if (this->lv_top == 0_vl && this->lv_selectable
|
||||
&& this->lv_selection != 0_vl)
|
||||
{
|
||||
@ -187,6 +186,16 @@ listview_curses::handle_key(int ch)
|
||||
|
||||
case ' ':
|
||||
case KEY_NPAGE: {
|
||||
if (this->lv_overlay_source != nullptr) {
|
||||
std::vector<attr_line_t> overlay_content;
|
||||
this->lv_overlay_source->list_value_for_overlay(
|
||||
*this, this->get_selection(), overlay_content);
|
||||
if (!overlay_content.empty()) {
|
||||
this->shift_selection(shift_amount_t::down_page);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto rows_avail
|
||||
= this->rows_available(this->lv_top, RD_DOWN) - 1_vl;
|
||||
auto top_for_last = this->get_top_for_last_row();
|
||||
@ -257,6 +266,20 @@ listview_curses::handle_key(int ch)
|
||||
return retval;
|
||||
}
|
||||
|
||||
vis_line_t
|
||||
listview_curses::get_overlay_top(vis_line_t row, size_t count, size_t total)
|
||||
{
|
||||
if (row == this->get_selection()) {
|
||||
return this->lv_focused_overlay_top;
|
||||
}
|
||||
|
||||
if (this->get_selection() > row && count < total) {
|
||||
return vis_line_t{static_cast<int>(total - count)};
|
||||
}
|
||||
|
||||
return 0_vl;
|
||||
}
|
||||
|
||||
void
|
||||
listview_curses::do_update()
|
||||
{
|
||||
@ -265,6 +288,7 @@ listview_curses::do_update()
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<attr_line_t> row_overlay_content;
|
||||
vis_line_t height;
|
||||
unsigned long width;
|
||||
|
||||
@ -303,12 +327,8 @@ listview_curses::do_update()
|
||||
lr.lr_start = this->lv_left;
|
||||
lr.lr_end = this->lv_left + wrap_width;
|
||||
if (this->lv_overlay_source != nullptr
|
||||
&& this->lv_overlay_source->list_value_for_overlay(
|
||||
*this,
|
||||
y - this->lv_y,
|
||||
bottom - this->lv_y,
|
||||
row,
|
||||
overlay_line))
|
||||
&& this->lv_overlay_source->list_static_overlay(
|
||||
*this, y - this->lv_y, bottom - this->lv_y, overlay_line))
|
||||
{
|
||||
mvwattrline(this->lv_window, y, this->lv_x, overlay_line, lr);
|
||||
overlay_line.clear();
|
||||
@ -335,6 +355,103 @@ listview_curses::do_update()
|
||||
lr.lr_end += wrap_width;
|
||||
++y;
|
||||
} while (this->lv_word_wrap && y < bottom && remaining > 0);
|
||||
|
||||
if (this->lv_overlay_source != nullptr) {
|
||||
row_overlay_content.clear();
|
||||
|
||||
lr.lr_start = this->lv_left;
|
||||
lr.lr_end = this->lv_left + wrap_width;
|
||||
this->lv_overlay_source->list_value_for_overlay(
|
||||
*this, row, row_overlay_content);
|
||||
auto overlay_height = this->get_overlay_height(
|
||||
row_overlay_content.size(), height);
|
||||
auto ov_height_remaining = overlay_height;
|
||||
auto overlay_top = this->get_overlay_top(
|
||||
row, overlay_height, row_overlay_content.size());
|
||||
auto overlay_row = overlay_top;
|
||||
if (row_overlay_content.size() > 1) {
|
||||
auto hdr
|
||||
= this->lv_overlay_source->list_header_for_overlay(
|
||||
*this, row);
|
||||
if (hdr) {
|
||||
auto ov_hdr_attrs = text_attrs{};
|
||||
ov_hdr_attrs.ta_attrs |= A_UNDERLINE;
|
||||
auto ov_hdr = hdr.value().with_attr_for_all(
|
||||
VC_STYLE.value(ov_hdr_attrs));
|
||||
mvwattrline(this->lv_window,
|
||||
y,
|
||||
this->lv_x,
|
||||
ov_hdr,
|
||||
lr,
|
||||
role_t::VCR_STATUS_INFO);
|
||||
++y;
|
||||
}
|
||||
}
|
||||
auto overlay_y = y;
|
||||
while (ov_height_remaining > 0 && y < bottom) {
|
||||
mvwattrline(this->lv_window,
|
||||
y,
|
||||
this->lv_x,
|
||||
row_overlay_content[overlay_row],
|
||||
lr,
|
||||
role_t::VCR_ALT_ROW);
|
||||
ov_height_remaining -= 1;
|
||||
++overlay_row;
|
||||
++y;
|
||||
}
|
||||
|
||||
if (overlay_height != row_overlay_content.size()) {
|
||||
double progress = 1.0;
|
||||
double coverage = 1.0;
|
||||
vis_line_t lines;
|
||||
|
||||
if (!row_overlay_content.empty()) {
|
||||
progress = (double) overlay_top
|
||||
/ (double) row_overlay_content.size();
|
||||
coverage = (double) overlay_height
|
||||
/ (double) row_overlay_content.size();
|
||||
}
|
||||
|
||||
auto scroll_y = overlay_y
|
||||
+ (int) (progress * (double) overlay_height);
|
||||
lines = vis_line_t(
|
||||
scroll_y
|
||||
+ std::min(
|
||||
(int) overlay_height,
|
||||
(int) (coverage * (double) overlay_height)));
|
||||
|
||||
for (unsigned int gutter_y = overlay_y;
|
||||
gutter_y < (overlay_y + overlay_height);
|
||||
gutter_y++)
|
||||
{
|
||||
auto role = this->vc_default_role;
|
||||
auto bar_role = role_t::VCR_SCROLLBAR;
|
||||
text_attrs attrs;
|
||||
chtype ch = gutter_y == overlay_y
|
||||
? ACS_URCORNER
|
||||
: (gutter_y == (overlay_y + overlay_height - 1)
|
||||
? ACS_LRCORNER
|
||||
: ACS_VLINE);
|
||||
|
||||
if (gutter_y >= (unsigned int) scroll_y
|
||||
&& gutter_y <= (unsigned int) lines)
|
||||
{
|
||||
role = bar_role;
|
||||
}
|
||||
attrs = vc.attrs_for_role(role);
|
||||
wattr_set(this->lv_window,
|
||||
attrs.ta_attrs,
|
||||
vc.ensure_color_pair(attrs.ta_fg_color,
|
||||
attrs.ta_bg_color),
|
||||
nullptr);
|
||||
mvwaddch(this->lv_window,
|
||||
gutter_y,
|
||||
this->lv_x + width - 2,
|
||||
ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++row;
|
||||
} else {
|
||||
wattr_set(this->lv_window,
|
||||
@ -421,43 +538,127 @@ listview_curses::do_update()
|
||||
}
|
||||
|
||||
view_curses::do_update();
|
||||
|
||||
#if 0
|
||||
else if (this->lv_overlay_needs_update && this->lv_overlay_source != NULL) {
|
||||
vis_line_t y(this->lv_y), height, bottom;
|
||||
attr_line_t overlay_line;
|
||||
unsigned long width, wrap_width;
|
||||
struct line_range lr;
|
||||
|
||||
this->lv_overlay_source->list_overlay_count(*this);
|
||||
this->get_dimensions(height, width);
|
||||
wrap_width = width - (this->lv_word_wrap ? 1 : this->lv_show_scrollbar ? 1 : 0);
|
||||
|
||||
lr.lr_start = this->lv_left;
|
||||
lr.lr_end = this->lv_left + wrap_width;
|
||||
|
||||
bottom = y + height;
|
||||
while (y < bottom) {
|
||||
if (this->lv_overlay_source->list_value_for_overlay(
|
||||
*this,
|
||||
y - vis_line_t(this->lv_y),
|
||||
overlay_line)) {
|
||||
this->mvwattrline(this->lv_window, y, this->lv_x, overlay_line, lr);
|
||||
overlay_line.clear();
|
||||
}
|
||||
++y;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
listview_curses::shift_selection(int offset)
|
||||
listview_curses::shift_selection(shift_amount_t sa)
|
||||
{
|
||||
vis_line_t new_selection = this->lv_selection + vis_line_t(offset);
|
||||
vis_line_t height;
|
||||
unsigned long width;
|
||||
|
||||
if (new_selection >= 0_vl && new_selection < this->get_inner_height()) {
|
||||
this->set_selection(new_selection);
|
||||
this->get_dimensions(height, width);
|
||||
if (this->lv_focused_overlay_top > 0
|
||||
&& (sa == shift_amount_t::up_line || sa == shift_amount_t::up_page))
|
||||
{
|
||||
switch (sa) {
|
||||
case shift_amount_t::up_line:
|
||||
this->lv_focused_overlay_top -= 1_vl;
|
||||
break;
|
||||
case shift_amount_t::up_page: {
|
||||
std::vector<attr_line_t> overlay_content;
|
||||
|
||||
this->lv_overlay_source->list_value_for_overlay(
|
||||
*this, this->get_selection(), overlay_content);
|
||||
auto overlay_height
|
||||
= this->get_overlay_height(overlay_content.size(), height);
|
||||
if (this->lv_focused_overlay_top > overlay_height) {
|
||||
this->lv_focused_overlay_top
|
||||
-= vis_line_t{static_cast<int>(overlay_height - 1)};
|
||||
} else {
|
||||
this->lv_focused_overlay_top = 0_vl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this->set_needs_update();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->get_selection() > 0 && this->lv_overlay_source != nullptr) {
|
||||
vis_line_t focused = this->get_selection();
|
||||
std::vector<attr_line_t> overlay_content;
|
||||
bool is_up = false;
|
||||
|
||||
switch (sa) {
|
||||
case shift_amount_t::up_line:
|
||||
case shift_amount_t::up_page:
|
||||
focused -= 1_vl;
|
||||
is_up = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this->lv_overlay_source->list_value_for_overlay(
|
||||
*this, focused, overlay_content);
|
||||
if (!overlay_content.empty()) {
|
||||
auto overlay_height
|
||||
= this->get_overlay_height(overlay_content.size(), height);
|
||||
auto ov_top_for_last = vis_line_t{
|
||||
static_cast<int>(overlay_content.size() - overlay_height)};
|
||||
|
||||
if (is_up) {
|
||||
this->set_selection(focused);
|
||||
this->lv_focused_overlay_top = ov_top_for_last;
|
||||
this->set_needs_update();
|
||||
return;
|
||||
}
|
||||
if (this->lv_focused_overlay_top + 1 + overlay_height
|
||||
<= overlay_content.size())
|
||||
{
|
||||
switch (sa) {
|
||||
case shift_amount_t::down_line:
|
||||
this->lv_focused_overlay_top += 1_vl;
|
||||
break;
|
||||
case shift_amount_t::down_page: {
|
||||
if (this->lv_focused_overlay_top + overlay_height - 1
|
||||
>= ov_top_for_last)
|
||||
{
|
||||
this->lv_focused_overlay_top = ov_top_for_last;
|
||||
} else {
|
||||
this->lv_focused_overlay_top += vis_line_t{
|
||||
static_cast<int>(overlay_height - 1)};
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this->set_needs_update();
|
||||
return;
|
||||
}
|
||||
|
||||
if (overlay_height < overlay_content.size()) {
|
||||
sa = shift_amount_t::down_line;
|
||||
}
|
||||
}
|
||||
this->lv_focused_overlay_top = 0_vl;
|
||||
}
|
||||
|
||||
auto offset = 0_vl;
|
||||
switch (sa) {
|
||||
case shift_amount_t::up_line:
|
||||
offset = -1_vl;
|
||||
break;
|
||||
case shift_amount_t::up_page:
|
||||
offset = -(height - 1_vl);
|
||||
break;
|
||||
case shift_amount_t::down_line:
|
||||
offset = 1_vl;
|
||||
break;
|
||||
case shift_amount_t::down_page:
|
||||
offset = height - 1_vl;
|
||||
break;
|
||||
}
|
||||
if (this->is_selectable()) {
|
||||
auto new_selection = this->lv_selection + vis_line_t(offset);
|
||||
|
||||
if (new_selection >= 0_vl && new_selection < this->get_inner_height()) {
|
||||
this->set_selection(new_selection);
|
||||
}
|
||||
} else {
|
||||
this->shift_top(vis_line_t{offset});
|
||||
}
|
||||
}
|
||||
|
||||
@ -577,6 +778,7 @@ listview_curses::set_top(vis_line_t top, bool suppress_flash)
|
||||
} else if (this->lv_top != top) {
|
||||
auto old_top = this->lv_top;
|
||||
this->lv_top = top;
|
||||
this->lv_focused_overlay_top = 0_vl;
|
||||
if (this->lv_selectable) {
|
||||
if (this->lv_selection < 0_vl) {
|
||||
} else if (this->lv_selection < top) {
|
||||
@ -665,6 +867,7 @@ listview_curses::set_selection(vis_line_t sel)
|
||||
}
|
||||
if (sel == -1_vl) {
|
||||
this->lv_selection = sel;
|
||||
this->lv_focused_overlay_top = 0_vl;
|
||||
this->lv_source->listview_selection_changed(*this);
|
||||
this->set_needs_update();
|
||||
this->invoke_scroll();
|
||||
@ -700,6 +903,7 @@ listview_curses::set_selection(vis_line_t sel)
|
||||
if (this->lv_sync_selection_and_top) {
|
||||
this->lv_top = sel;
|
||||
}
|
||||
this->lv_focused_overlay_top = 0_vl;
|
||||
this->lv_source->listview_selection_changed(*this);
|
||||
this->set_needs_update();
|
||||
this->invoke_scroll();
|
||||
@ -732,3 +936,23 @@ listview_curses::get_top_for_last_row()
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
vis_line_t
|
||||
listview_curses::shift_top(vis_line_t offset, bool suppress_flash)
|
||||
{
|
||||
if (offset < 0 && this->lv_top == 0) {
|
||||
if (suppress_flash == false) {
|
||||
alerter::singleton().chime("the top of the view has been reached");
|
||||
}
|
||||
} else {
|
||||
this->set_top(std::max(0_vl, this->lv_top + offset), suppress_flash);
|
||||
}
|
||||
|
||||
return this->lv_top;
|
||||
}
|
||||
|
||||
size_t
|
||||
listview_curses::get_overlay_height(size_t total, vis_line_t view_height)
|
||||
{
|
||||
return std::min(total, static_cast<size_t>(2 * (view_height / 3)));
|
||||
}
|
||||
|
@ -107,12 +107,25 @@ public:
|
||||
|
||||
virtual void reset() {}
|
||||
|
||||
virtual bool list_value_for_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
virtual bool list_static_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
attr_line_t& value_out)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual nonstd::optional<attr_line_t> list_header_for_overlay(
|
||||
const listview_curses& lv, vis_line_t line)
|
||||
{
|
||||
return nonstd::nullopt;
|
||||
}
|
||||
|
||||
virtual void list_value_for_overlay(const listview_curses& lv,
|
||||
vis_line_t line,
|
||||
attr_line_t& value_out)
|
||||
= 0;
|
||||
std::vector<attr_line_t>& value_out)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class list_input_delegate {
|
||||
@ -209,7 +222,14 @@ public:
|
||||
|
||||
void set_selection(vis_line_t sel);
|
||||
|
||||
void shift_selection(int offset);
|
||||
enum class shift_amount_t {
|
||||
up_line,
|
||||
up_page,
|
||||
down_line,
|
||||
down_page,
|
||||
};
|
||||
|
||||
void shift_selection(shift_amount_t sa);
|
||||
|
||||
vis_line_t get_selection() const
|
||||
{
|
||||
@ -332,20 +352,7 @@ public:
|
||||
* @param suppress_flash Don't call flash() if the offset is out-of-bounds.
|
||||
* @return The final value of top.
|
||||
*/
|
||||
vis_line_t shift_top(vis_line_t offset, bool suppress_flash = false)
|
||||
{
|
||||
if (offset < 0 && this->lv_top == 0) {
|
||||
if (suppress_flash == false) {
|
||||
alerter::singleton().chime(
|
||||
"the top of the view has been reached");
|
||||
}
|
||||
} else {
|
||||
this->set_top(std::max(0_vl, this->lv_top + offset),
|
||||
suppress_flash);
|
||||
}
|
||||
|
||||
return this->lv_top;
|
||||
}
|
||||
vis_line_t shift_top(vis_line_t offset, bool suppress_flash = false);
|
||||
|
||||
/**
|
||||
* Set the column number to be displayed at the left of the view. If the
|
||||
@ -529,6 +536,9 @@ protected:
|
||||
|
||||
void update_top_from_selection();
|
||||
|
||||
vis_line_t get_overlay_top(vis_line_t row, size_t count, size_t total);
|
||||
size_t get_overlay_height(size_t total, vis_line_t view_height);
|
||||
|
||||
enum class lv_mode_t {
|
||||
NONE,
|
||||
DOWN,
|
||||
@ -549,6 +559,7 @@ protected:
|
||||
vis_line_t lv_top{0}; /*< The line at the top of the view. */
|
||||
unsigned int lv_left{0}; /*< The column at the left of the view. */
|
||||
vis_line_t lv_height{0}; /*< The abs/rel height of the view. */
|
||||
vis_line_t lv_focused_overlay_top{0};
|
||||
int lv_history_position{0};
|
||||
bool lv_overlay_needs_update{true};
|
||||
bool lv_show_scrollbar{true}; /*< Draw the scrollbar in the view. */
|
||||
|
88
src/lnav.cc
88
src/lnav.cc
@ -1993,36 +1993,40 @@ looper()
|
||||
if (lnav_data.ld_view_stack.empty()) {
|
||||
lnav_data.ld_looping = false;
|
||||
} else {
|
||||
textview_curses* tc = *lnav_data.ld_view_stack.top();
|
||||
std::vector<attr_line_t> rows(1);
|
||||
auto* tc = *lnav_data.ld_view_stack.top();
|
||||
|
||||
tc->get_data_source()->listview_value_for_rows(
|
||||
*tc, tc->get_selection(), rows);
|
||||
string_attrs_t& sa = rows[0].get_attrs();
|
||||
auto line_attr_opt = get_string_attr(sa, logline::L_FILE);
|
||||
bool found = false;
|
||||
if (line_attr_opt) {
|
||||
auto lf = line_attr_opt.value().get();
|
||||
if (tc->get_inner_height() > 0_vl) {
|
||||
std::vector<attr_line_t> rows(1);
|
||||
|
||||
log_debug("file name when SIGINT: %s",
|
||||
lf->get_filename().c_str());
|
||||
for (auto& cp : lnav_data.ld_child_pollers) {
|
||||
auto cp_name = cp.get_filename();
|
||||
tc->get_data_source()->listview_value_for_rows(
|
||||
*tc, tc->get_selection(), rows);
|
||||
auto& sa = rows[0].get_attrs();
|
||||
auto line_attr_opt
|
||||
= get_string_attr(sa, logline::L_FILE);
|
||||
bool found = false;
|
||||
if (line_attr_opt) {
|
||||
auto lf = line_attr_opt.value().get();
|
||||
|
||||
if (!cp_name) {
|
||||
log_debug("no child_poller");
|
||||
continue;
|
||||
}
|
||||
log_debug("file name when SIGINT: %s",
|
||||
lf->get_filename().c_str());
|
||||
for (auto& cp : lnav_data.ld_child_pollers) {
|
||||
auto cp_name = cp.get_filename();
|
||||
|
||||
if (lf->get_filename() == cp_name.value()) {
|
||||
log_debug("found it, sending signal!");
|
||||
cp.send_sigint();
|
||||
found = true;
|
||||
if (!cp_name) {
|
||||
log_debug("no child_poller");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lf->get_filename() == cp_name.value()) {
|
||||
log_debug("found it, sending signal!");
|
||||
cp.send_sigint();
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
lnav_data.ld_looping = false;
|
||||
if (!found) {
|
||||
lnav_data.ld_looping = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3325,21 +3329,19 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
|
||||
}
|
||||
|
||||
auto* los = tc->get_overlay_source();
|
||||
attr_line_t ov_al;
|
||||
while (los != nullptr && tc->get_inner_height() > 0_vl
|
||||
&& los->list_static_overlay(
|
||||
*tc, y, tc->get_inner_height(), ov_al))
|
||||
{
|
||||
write_line_to(stdout, ov_al);
|
||||
++y;
|
||||
}
|
||||
|
||||
vis_line_t vl;
|
||||
for (vl = tc->get_top(); vl < tc->get_inner_height();
|
||||
++vl, ++y)
|
||||
{
|
||||
attr_line_t al;
|
||||
|
||||
while (los != nullptr
|
||||
&& los->list_value_for_overlay(
|
||||
*tc, y, tc->get_inner_height(), vl, al))
|
||||
{
|
||||
write_line_to(stdout, al);
|
||||
++y;
|
||||
}
|
||||
|
||||
std::vector<attr_line_t> rows(1);
|
||||
tc->listview_value_for_rows(*tc, vl, rows);
|
||||
if (suppress_empty_lines && rows[0].empty()) {
|
||||
@ -3347,17 +3349,15 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
|
||||
}
|
||||
|
||||
write_line_to(stdout, rows[0]);
|
||||
}
|
||||
{
|
||||
attr_line_t al;
|
||||
|
||||
while (los != nullptr
|
||||
&& los->list_value_for_overlay(
|
||||
*tc, y, tc->get_inner_height(), vl, al)
|
||||
&& !al.empty())
|
||||
{
|
||||
write_line_to(stdout, al);
|
||||
++y;
|
||||
std::vector<attr_line_t> row_overlay_content;
|
||||
if (los != nullptr) {
|
||||
los->list_value_for_overlay(
|
||||
*tc, vl, row_overlay_content);
|
||||
for (const auto& ov_row : row_overlay_content) {
|
||||
write_line_to(stdout, ov_row);
|
||||
++y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1318,15 +1318,15 @@ com_save_to(exec_context& ec,
|
||||
attr_line_t ov_al;
|
||||
|
||||
auto* los = tc->get_overlay_source();
|
||||
while (
|
||||
los != nullptr
|
||||
&& los->list_static_overlay(*tc, y, tc->get_inner_height(), ov_al))
|
||||
{
|
||||
write_line_to(outfile, ov_al);
|
||||
++y;
|
||||
}
|
||||
tc->listview_value_for_rows(*tc, top, rows);
|
||||
for (auto& al : rows) {
|
||||
while (los != nullptr
|
||||
&& los->list_value_for_overlay(
|
||||
*tc, y, tc->get_inner_height(), top, ov_al))
|
||||
{
|
||||
write_line_to(outfile, ov_al);
|
||||
++y;
|
||||
}
|
||||
wrapped_count += vis_line_t((al.length() - 1) / (dim.second - 2));
|
||||
if (anonymize) {
|
||||
al.al_attrs.clear();
|
||||
@ -1334,17 +1334,18 @@ com_save_to(exec_context& ec,
|
||||
}
|
||||
write_line_to(outfile, al);
|
||||
|
||||
++y;
|
||||
std::vector<attr_line_t> row_overlay_content;
|
||||
if (los != nullptr) {
|
||||
los->list_value_for_overlay(*tc, top, row_overlay_content);
|
||||
for (const auto& ov_row : row_overlay_content) {
|
||||
write_line_to(outfile, ov_row);
|
||||
line_count += 1;
|
||||
++y;
|
||||
}
|
||||
}
|
||||
line_count += 1;
|
||||
++top;
|
||||
++y;
|
||||
}
|
||||
while (los != nullptr
|
||||
&& los->list_value_for_overlay(
|
||||
*tc, y, tc->get_inner_height(), top, ov_al)
|
||||
&& !ov_al.empty())
|
||||
{
|
||||
write_line_to(outfile, ov_al);
|
||||
++y;
|
||||
}
|
||||
|
||||
tc->set_word_wrap(wrapped);
|
||||
@ -1467,37 +1468,37 @@ com_save_to(exec_context& ec,
|
||||
});
|
||||
}
|
||||
|
||||
los->reset();
|
||||
auto y = 0_vl;
|
||||
while (
|
||||
los != nullptr
|
||||
&& los->list_static_overlay(*tc, y, tc->get_inner_height(), ov_al))
|
||||
{
|
||||
write_line_to(outfile, ov_al);
|
||||
++y;
|
||||
}
|
||||
for (auto iter = all_user_marks.begin(); iter != all_user_marks.end();
|
||||
iter++, count++)
|
||||
{
|
||||
if (ec.ec_dry_run && count > 10) {
|
||||
break;
|
||||
}
|
||||
auto y = 0_vl;
|
||||
while (los != nullptr
|
||||
&& los->list_value_for_overlay(
|
||||
*tc, y, tc->get_inner_height(), *iter, ov_al))
|
||||
{
|
||||
write_line_to(outfile, ov_al);
|
||||
++y;
|
||||
}
|
||||
tc->listview_value_for_rows(*tc, *iter, rows);
|
||||
++y;
|
||||
if (anonymize) {
|
||||
rows[0].al_attrs.clear();
|
||||
rows[0].al_string = ta.next(rows[0].al_string);
|
||||
}
|
||||
write_line_to(outfile, rows[0]);
|
||||
|
||||
while (los != nullptr
|
||||
&& los->list_value_for_overlay(
|
||||
*tc, y, tc->get_inner_height(), *iter, ov_al))
|
||||
{
|
||||
write_line_to(outfile, ov_al);
|
||||
++y;
|
||||
y = 0_vl;
|
||||
std::vector<attr_line_t> row_overlay_content;
|
||||
if (los != nullptr) {
|
||||
los->list_value_for_overlay(*tc, (*iter), row_overlay_content);
|
||||
for (const auto& ov_row : row_overlay_content) {
|
||||
write_line_to(outfile, ov_row);
|
||||
line_count += 1;
|
||||
++y;
|
||||
}
|
||||
}
|
||||
|
||||
line_count += 1;
|
||||
}
|
||||
|
||||
|
@ -393,11 +393,10 @@ apply(vis_line_t vl, std::vector<intern_string_t> annos)
|
||||
lnav_data.ld_views[LNV_LOG].set_needs_update();
|
||||
};
|
||||
|
||||
lnav_data.ld_child_pollers.emplace_back(child_poller{
|
||||
lnav_data.ld_child_pollers.emplace_back(
|
||||
(*ld)->get_file_ptr()->get_filename(),
|
||||
std::move(child),
|
||||
std::move(finalizer),
|
||||
});
|
||||
std::move(finalizer));
|
||||
}
|
||||
lf->get_bookmark_metadata()[line_number].bm_annotations = la;
|
||||
return Ok();
|
||||
|
@ -3353,6 +3353,10 @@ external_log_format::get_pattern_name(uint64_t line_number) const
|
||||
int
|
||||
log_format::pattern_index_for_line(uint64_t line_number) const
|
||||
{
|
||||
if (this->lf_pattern_locks.empty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto iter = lower_bound(this->lf_pattern_locks.cbegin(),
|
||||
this->lf_pattern_locks.cend(),
|
||||
line_number,
|
||||
@ -3380,7 +3384,9 @@ log_format::get_pattern_name(uint64_t line_number) const
|
||||
char pat_str[128];
|
||||
|
||||
int pat_index = this->pattern_index_for_line(line_number);
|
||||
snprintf(pat_str, sizeof(pat_str), "builtin (%d)", pat_index);
|
||||
auto to_n_res = fmt::format_to_n(
|
||||
pat_str, sizeof(pat_str) - 1, FMT_STRING("builtin ({})"), pat_index);
|
||||
pat_str[to_n_res.size] = '\0';
|
||||
return intern_string::lookup(pat_str);
|
||||
}
|
||||
|
||||
|
@ -518,10 +518,6 @@ load_time_bookmarks()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (part_name == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!dts.scan(log_time,
|
||||
strlen(log_time),
|
||||
nullptr,
|
||||
@ -532,13 +528,11 @@ load_time_bookmarks()
|
||||
}
|
||||
|
||||
auto line_iter
|
||||
= lower_bound(lf->begin(), lf->end(), log_tv);
|
||||
= std::lower_bound(lf->begin(), lf->end(), log_tv);
|
||||
while (line_iter != lf->end()) {
|
||||
struct timeval line_tv = line_iter->get_timeval();
|
||||
|
||||
if ((line_tv.tv_sec != log_tv.tv_sec)
|
||||
|| (line_tv.tv_usec != log_tv.tv_usec))
|
||||
{
|
||||
if (line_tv != log_tv) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -90,17 +90,14 @@ public:
|
||||
});
|
||||
}
|
||||
|
||||
bool list_value_for_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
void list_value_for_overlay(const listview_curses& lv,
|
||||
vis_line_t line,
|
||||
attr_line_t& value_out) override
|
||||
std::vector<attr_line_t>& value_out) override
|
||||
{
|
||||
if (this->fss_overlay_delegate != nullptr) {
|
||||
return this->fss_overlay_delegate->list_value_for_overlay(
|
||||
lv, y, bottom, line, value_out);
|
||||
this->fss_overlay_delegate->list_value_for_overlay(
|
||||
lv, line, value_out);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
text_sub_source* fss_delegate;
|
||||
|
@ -176,12 +176,10 @@ spectrogram_source::list_input_handle_key(listview_curses& lv, int ch)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
spectrogram_source::list_value_for_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
vis_line_t row,
|
||||
attr_line_t& value_out)
|
||||
std::vector<attr_line_t>& value_out)
|
||||
{
|
||||
vis_line_t height;
|
||||
unsigned long width;
|
||||
@ -189,140 +187,81 @@ spectrogram_source::list_value_for_overlay(const listview_curses& lv,
|
||||
lv.get_dimensions(height, width);
|
||||
width -= 2;
|
||||
|
||||
if (y > 0) {
|
||||
auto sel = lv.get_selection();
|
||||
auto selected_y = sel - lv.get_top() + 2;
|
||||
auto sel = lv.get_selection();
|
||||
|
||||
if (y == selected_y && this->ss_cursor_column) {
|
||||
const auto& s_row = this->load_row(lv, sel);
|
||||
const auto& bucket
|
||||
= s_row.sr_values[this->ss_cursor_column.value()];
|
||||
auto& sb = this->ss_cached_bounds;
|
||||
spectrogram_request sr(sb);
|
||||
if (row == sel && this->ss_cursor_column) {
|
||||
const auto& s_row = this->load_row(lv, sel);
|
||||
const auto& bucket = s_row.sr_values[this->ss_cursor_column.value()];
|
||||
auto& sb = this->ss_cached_bounds;
|
||||
spectrogram_request sr(sb);
|
||||
attr_line_t retval;
|
||||
|
||||
auto sel_time = rounddown(sb.sb_begin_time, this->ss_granularity)
|
||||
+ sel * this->ss_granularity;
|
||||
sr.sr_width = width;
|
||||
sr.sr_begin_time = sel_time;
|
||||
sr.sr_end_time = sel_time + this->ss_granularity;
|
||||
sr.sr_column_size = (sb.sb_max_value_out - sb.sb_min_value_out)
|
||||
/ (double) (width - 1);
|
||||
auto range_min = sb.sb_min_value_out
|
||||
+ this->ss_cursor_column.value() * sr.sr_column_size;
|
||||
auto range_max = range_min + sr.sr_column_size;
|
||||
auto sel_time = rounddown(sb.sb_begin_time, this->ss_granularity)
|
||||
+ sel * this->ss_granularity;
|
||||
sr.sr_width = width;
|
||||
sr.sr_begin_time = sel_time;
|
||||
sr.sr_end_time = sel_time + this->ss_granularity;
|
||||
sr.sr_column_size = (sb.sb_max_value_out - sb.sb_min_value_out)
|
||||
/ (double) (width - 1);
|
||||
auto range_min = sb.sb_min_value_out
|
||||
+ this->ss_cursor_column.value() * sr.sr_column_size;
|
||||
auto range_max = range_min + sr.sr_column_size;
|
||||
|
||||
auto desc
|
||||
= attr_line_t()
|
||||
.append(lnav::roles::number(
|
||||
fmt::to_string(bucket.rb_counter)))
|
||||
.append(fmt::format(FMT_STRING(" value{} in the range "),
|
||||
bucket.rb_counter == 1 ? "" : "s"))
|
||||
.append(lnav::roles::number(
|
||||
fmt::format(FMT_STRING("{:.2Lf}"), range_min)))
|
||||
.append("-")
|
||||
.append(lnav::roles::number(
|
||||
fmt::format(FMT_STRING("{:.2Lf}"), range_max)))
|
||||
.append(" ");
|
||||
auto mark_offset = this->ss_cursor_column.value();
|
||||
auto mark_is_before = true;
|
||||
auto desc
|
||||
= attr_line_t()
|
||||
.append(
|
||||
lnav::roles::number(fmt::to_string(bucket.rb_counter)))
|
||||
.append(fmt::format(FMT_STRING(" value{} in the range "),
|
||||
bucket.rb_counter == 1 ? "" : "s"))
|
||||
.append(lnav::roles::number(
|
||||
fmt::format(FMT_STRING("{:.2Lf}"), range_min)))
|
||||
.append("-")
|
||||
.append(lnav::roles::number(
|
||||
fmt::format(FMT_STRING("{:.2Lf}"), range_max)))
|
||||
.append(" ");
|
||||
auto mark_offset = this->ss_cursor_column.value();
|
||||
auto mark_is_before = true;
|
||||
|
||||
value_out.al_attrs.emplace_back(
|
||||
line_range{0, -1}, VC_ROLE.value(role_t::VCR_STATUS_INFO));
|
||||
if (desc.length() + 8 > width) {
|
||||
desc.clear();
|
||||
}
|
||||
|
||||
if (this->ss_cursor_column.value() + desc.length() + 1 > width) {
|
||||
mark_offset -= desc.length();
|
||||
mark_is_before = false;
|
||||
}
|
||||
value_out.append(mark_offset, ' ');
|
||||
if (mark_is_before) {
|
||||
value_out.append("\u25b2 ");
|
||||
}
|
||||
value_out.append(desc);
|
||||
if (!mark_is_before) {
|
||||
value_out.append("\u25b2 ");
|
||||
}
|
||||
|
||||
if (this->ss_details_view != nullptr) {
|
||||
if (s_row.sr_details_source_provider) {
|
||||
auto row_details_source = s_row.sr_details_source_provider(
|
||||
sr, range_min, range_max);
|
||||
|
||||
this->ss_details_view->set_sub_source(
|
||||
row_details_source.get());
|
||||
this->ss_details_source = std::move(row_details_source);
|
||||
auto* overlay_source = dynamic_cast<list_overlay_source*>(
|
||||
this->ss_details_source.get());
|
||||
if (overlay_source != nullptr) {
|
||||
this->ss_details_view->set_overlay_source(
|
||||
overlay_source);
|
||||
}
|
||||
} else {
|
||||
this->ss_details_view->set_sub_source(
|
||||
this->ss_no_details_source);
|
||||
this->ss_details_view->set_overlay_source(nullptr);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
retval.al_attrs.emplace_back(line_range{0, -1},
|
||||
VC_ROLE.value(role_t::VCR_STATUS_INFO));
|
||||
if (desc.length() + 8 > width) {
|
||||
desc.clear();
|
||||
}
|
||||
|
||||
return false;
|
||||
if (this->ss_cursor_column.value() + desc.length() + 1 > width) {
|
||||
mark_offset -= desc.length();
|
||||
mark_is_before = false;
|
||||
}
|
||||
retval.append(mark_offset, ' ');
|
||||
if (mark_is_before) {
|
||||
retval.append("\u25b2 ");
|
||||
}
|
||||
retval.append(desc);
|
||||
if (!mark_is_before) {
|
||||
retval.append("\u25b2 ");
|
||||
}
|
||||
|
||||
if (this->ss_details_view != nullptr) {
|
||||
if (s_row.sr_details_source_provider) {
|
||||
auto row_details_source = s_row.sr_details_source_provider(
|
||||
sr, range_min, range_max);
|
||||
|
||||
this->ss_details_view->set_sub_source(row_details_source.get());
|
||||
this->ss_details_source = std::move(row_details_source);
|
||||
auto* overlay_source = dynamic_cast<list_overlay_source*>(
|
||||
this->ss_details_source.get());
|
||||
if (overlay_source != nullptr) {
|
||||
this->ss_details_view->set_overlay_source(overlay_source);
|
||||
}
|
||||
} else {
|
||||
this->ss_details_view->set_sub_source(
|
||||
this->ss_no_details_source);
|
||||
this->ss_details_view->set_overlay_source(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
value_out.emplace_back(retval);
|
||||
}
|
||||
|
||||
auto& line = value_out.get_string();
|
||||
char buf[128];
|
||||
|
||||
this->cache_bounds();
|
||||
|
||||
if (this->ss_cached_line_count == 0) {
|
||||
value_out
|
||||
.append(lnav::roles::error("error: no data available, use the "))
|
||||
.append_quoted(lnav::roles::keyword(":spectrogram"))
|
||||
.append(lnav::roles::error(" command to visualize numeric data"));
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& sb = this->ss_cached_bounds;
|
||||
auto& st = this->ss_cached_thresholds;
|
||||
|
||||
snprintf(buf, sizeof(buf), "Min: %'.10lg", sb.sb_min_value_out);
|
||||
line = buf;
|
||||
|
||||
snprintf(buf,
|
||||
sizeof(buf),
|
||||
ANSI_ROLE(" ") " 1-%'d " ANSI_ROLE(" ") " %'d-%'d " ANSI_ROLE(
|
||||
" ") " %'d+",
|
||||
role_t::VCR_LOW_THRESHOLD,
|
||||
st.st_green_threshold - 1,
|
||||
role_t::VCR_MED_THRESHOLD,
|
||||
st.st_green_threshold,
|
||||
st.st_yellow_threshold - 1,
|
||||
role_t::VCR_HIGH_THRESHOLD,
|
||||
st.st_yellow_threshold);
|
||||
auto buflen = strlen(buf);
|
||||
if (line.length() + buflen + 20 < width) {
|
||||
line.append(width / 2 - buflen / 3 - line.length(), ' ');
|
||||
} else {
|
||||
line.append(" ");
|
||||
}
|
||||
line.append(buf);
|
||||
scrub_ansi_string(line, &value_out.get_attrs());
|
||||
|
||||
snprintf(buf, sizeof(buf), "Max: %'.10lg", sb.sb_max_value_out);
|
||||
buflen = strlen(buf);
|
||||
if (line.length() + buflen + 4 < width) {
|
||||
line.append(width - buflen - line.length() - 2, ' ');
|
||||
} else {
|
||||
line.append(" ");
|
||||
}
|
||||
line.append(buf);
|
||||
|
||||
value_out.with_attr(string_attr(line_range(0, -1),
|
||||
VC_STYLE.value(text_attrs{A_UNDERLINE})));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
@ -590,6 +529,75 @@ spectrogram_source::text_selection_changed(textview_curses& tc)
|
||||
= s_row.nearest_column(this->ss_cursor_column.value_or(0));
|
||||
}
|
||||
|
||||
bool
|
||||
spectrogram_source::list_static_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
attr_line_t& value_out)
|
||||
{
|
||||
if (y != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& line = value_out.get_string();
|
||||
vis_line_t height;
|
||||
unsigned long width;
|
||||
char buf[128];
|
||||
|
||||
lv.get_dimensions(height, width);
|
||||
width -= 2;
|
||||
|
||||
this->cache_bounds();
|
||||
|
||||
if (this->ss_cached_line_count == 0) {
|
||||
value_out
|
||||
.append(lnav::roles::error("error: no data available, use the "))
|
||||
.append_quoted(lnav::roles::keyword(":spectrogram"))
|
||||
.append(lnav::roles::error(" command to visualize numeric data"));
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& sb = this->ss_cached_bounds;
|
||||
auto& st = this->ss_cached_thresholds;
|
||||
|
||||
snprintf(buf, sizeof(buf), "Min: %'.10lg", sb.sb_min_value_out);
|
||||
line = buf;
|
||||
|
||||
snprintf(buf,
|
||||
sizeof(buf),
|
||||
ANSI_ROLE(" ") " 1-%'d " ANSI_ROLE(" ") " %'d-%'d " ANSI_ROLE(
|
||||
" ") " %'d+",
|
||||
role_t::VCR_LOW_THRESHOLD,
|
||||
st.st_green_threshold - 1,
|
||||
role_t::VCR_MED_THRESHOLD,
|
||||
st.st_green_threshold,
|
||||
st.st_yellow_threshold - 1,
|
||||
role_t::VCR_HIGH_THRESHOLD,
|
||||
st.st_yellow_threshold);
|
||||
auto buflen = strlen(buf);
|
||||
if (line.length() + buflen + 20 < width) {
|
||||
line.append(width / 2 - buflen / 3 - line.length(), ' ');
|
||||
} else {
|
||||
line.append(" ");
|
||||
}
|
||||
line.append(buf);
|
||||
scrub_ansi_string(line, &value_out.get_attrs());
|
||||
|
||||
snprintf(buf, sizeof(buf), "Max: %'.10lg", sb.sb_max_value_out);
|
||||
buflen = strlen(buf);
|
||||
if (line.length() + buflen + 4 < width) {
|
||||
line.append(width - buflen - line.length() - 2, ' ');
|
||||
} else {
|
||||
line.append(" ");
|
||||
}
|
||||
line.append(buf);
|
||||
|
||||
value_out.with_attr(string_attr(line_range(0, -1),
|
||||
VC_STYLE.value(text_attrs{A_UNDERLINE})));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
spectro_status_source::spectro_status_source()
|
||||
{
|
||||
this->sss_fields[F_TITLE].set_width(9);
|
||||
|
@ -130,11 +130,14 @@ public:
|
||||
|
||||
bool list_input_handle_key(listview_curses& lv, int ch) override;
|
||||
|
||||
bool list_value_for_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
bool list_static_overlay(const listview_curses& lv,
|
||||
int y,
|
||||
int bottom,
|
||||
attr_line_t& value_out) override;
|
||||
|
||||
void list_value_for_overlay(const listview_curses& lv,
|
||||
vis_line_t row,
|
||||
attr_line_t& value_out) override;
|
||||
std::vector<attr_line_t>& value_out) override;
|
||||
|
||||
size_t text_line_count() override;
|
||||
|
||||
|
@ -850,7 +850,7 @@ execute_examples()
|
||||
result.append(dls.dls_rows[0][0]);
|
||||
} else {
|
||||
attr_line_t al;
|
||||
dos.list_value_for_overlay(db_tc, 0, 1, 0_vl, al);
|
||||
dos.list_static_overlay(db_tc, 0, 1, al);
|
||||
result.append(al);
|
||||
for (int lpc = 0; lpc < (int) dls.text_line_count();
|
||||
lpc++)
|
||||
|
@ -2,6 +2,6 @@
|
||||
[32m ├ org.lnav.test:[0m
|
||||
[32m ╰ [0mHello, [31mWorld[0m!
|
||||
[31m192.168.202.254[0m[31m - [0m[31m-[0m[31m [[0m[31m20/Jul/2009:22:59:29 +0000[0m[31m] "[0m[31mGET[0m[31m [0m[31m/vmw/vSphere/default/vmkboot.gz[0m[31m [0m[31mHTTP/1.0[0m[31m" 404 46210 "[0m[31m-[0m[31m" "[0m[31mgPXE/0.9.7[0m[31m"[0m
|
||||
📝 Annotations available, use [37m[40m:annotate[0m to apply them to this line
|
||||
[32m 📝 Annotations available, use [0m[32m[40m:annotate[0m[32m to apply them to this line[0m
|
||||
192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
|
||||
📝 Annotations available, use [37m[40m:annotate[0m to apply them to this line
|
||||
[32m 📝 Annotations available, use [0m[32m[40m:annotate[0m[32m to apply them to this line[0m
|
||||
|
@ -1,4 +1,4 @@
|
||||
192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
|
||||
└ #foo
|
||||
[31m192.168.202.254[0m[31m - [0m[31m-[0m[31m [[0m[31m20/Jul/2009:22:59:29 +0000[0m[31m] "[0m[31mGET[0m[31m [0m[31m/vmw/vSphere/default/vmkboot.gz[0m[31m [0m[31mHTTP/1.0[0m[31m" 404 46210 "[0m[31m-[0m[31m" "[0m[31mgPXE/0.9.7[0m[31m"[0m
|
||||
192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
|
||||
[7m192.168.202.254[0m[7m - [0m[7m-[0m[7m [[0m[7m20/Jul/2009:22:59:29 +0000[0m[7m] "[0m[7mGET[0m[7m [0m[7m/vmw/vSphere/default/vmkernel.gz[0m[7m [0m[7mHTTP/1.0[0m[7m" 200 78929 "[0m[7m-[0m[7m" "[0m[7mgPXE/0.9.7[0m[7m"[0m
|
||||
|
@ -1,4 +1,4 @@
|
||||
192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
|
||||
└ [32mHello, World![0m
|
||||
[31m192.168.202.254[0m[31m - [0m[31m-[0m[31m [[0m[31m20/Jul/2009:22:59:29 +0000[0m[31m] "[0m[31mGET[0m[31m [0m[31m/vmw/vSphere/default/vmkboot.gz[0m[31m [0m[31mHTTP/1.0[0m[31m" 404 46210 "[0m[31m-[0m[31m" "[0m[31mgPXE/0.9.7[0m[31m"[0m
|
||||
192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
|
||||
[7m192.168.202.254[0m[7m - [0m[7m-[0m[7m [[0m[7m20/Jul/2009:22:59:29 +0000[0m[7m] "[0m[7mGET[0m[7m [0m[7m/vmw/vSphere/default/vmkernel.gz[0m[7m [0m[7mHTTP/1.0[0m[7m" 200 78929 "[0m[7m-[0m[7m" "[0m[7mgPXE/0.9.7[0m[7m"[0m
|
||||
|
Loading…
Reference in New Issue
Block a user