summaryrefslogtreecommitdiffstats
path: root/src/view_helpers.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/view_helpers.cc724
1 files changed, 552 insertions, 172 deletions
diff --git a/src/view_helpers.cc b/src/view_helpers.cc
index 465f9e3..d79f774 100644
--- a/src/view_helpers.cc
+++ b/src/view_helpers.cc
@@ -29,12 +29,13 @@
#include "view_helpers.hh"
-#include "base/humanize.hh"
#include "base/itertools.hh"
+#include "bound_tags.hh"
#include "config.h"
#include "document.sections.hh"
#include "environ_vtab.hh"
#include "filter_sub_source.hh"
+#include "gantt_source.hh"
#include "help-md.h"
#include "intervaltree/IntervalTree.h"
#include "lnav.hh"
@@ -63,6 +64,7 @@ const char* lnav_view_strings[LNV__MAX + 1] = {
"schema",
"pretty",
"spectro",
+ "gantt",
nullptr,
};
@@ -76,6 +78,7 @@ const char* lnav_view_titles[LNV__MAX] = {
"SCHEMA",
"PRETTY",
"SPECTRO",
+ "GANTT",
};
nonstd::optional<lnav_view_t>
@@ -124,8 +127,29 @@ open_schema_view()
schema_tc->redo_search();
}
+static void
+open_gantt_view()
+{
+ auto* gantt_tc = &lnav_data.ld_views[LNV_GANTT];
+ auto* gantt_src = dynamic_cast<gantt_source*>(gantt_tc->get_sub_source());
+
+ gantt_src->rebuild_indexes();
+ gantt_tc->reload_data();
+ gantt_tc->redo_search();
+}
+
class pretty_sub_source : public plain_text_source {
public:
+ void set_indents(std::set<size_t>&& indents)
+ {
+ this->tds_doc_sections.m_indents = std::move(indents);
+ }
+
+ void set_sections_root(std::unique_ptr<lnav::document::hier_node>&& hn)
+ {
+ this->tds_doc_sections.m_sections_root = std::move(hn);
+ }
+
void text_crumbs_for_line(int line,
std::vector<breadcrumb::crumb>& crumbs) override
{
@@ -189,7 +213,7 @@ public:
sib_iter->second->hn_start)
| [](const auto new_top) {
lnav_data.ld_views[LNV_PRETTY]
- .set_top(new_top);
+ .set_selection(new_top);
};
}
},
@@ -201,8 +225,8 @@ public:
= parent_node->hn_children[index].get();
this->line_for_offset(sib->hn_start) |
[](const auto new_top) {
- lnav_data.ld_views[LNV_PRETTY].set_top(
- new_top);
+ lnav_data.ld_views[LNV_PRETTY]
+ .set_selection(new_top);
};
});
};
@@ -253,8 +277,8 @@ public:
if (child_iter != curr_node->hn_named_children.end()) {
this->line_for_offset(child_iter->second->hn_start)
| [](const auto new_top) {
- lnav_data.ld_views[LNV_PRETTY].set_top(
- new_top);
+ lnav_data.ld_views[LNV_PRETTY]
+ .set_selection(new_top);
};
}
},
@@ -262,7 +286,8 @@ public:
auto* child = curr_node->hn_children[index].get();
this->line_for_offset(child->hn_start) |
[](const auto new_top) {
- lnav_data.ld_views[LNV_PRETTY].set_top(new_top);
+ lnav_data.ld_views[LNV_PRETTY].set_selection(
+ new_top);
};
});
};
@@ -280,8 +305,8 @@ public:
= interval_tree::Interval<file_off_t, lnav::document::hier_node*>;
std::shared_ptr<lnav::document::sections_tree_t> pss_interval_tree;
- std::vector<std::unique_ptr<lnav::document::hier_node>> pss_hier_nods;
std::shared_ptr<hier_tree_t> pss_hier_tree;
+ std::unique_ptr<lnav::document::hier_node> pss_root_node;
};
static void
@@ -293,6 +318,18 @@ open_pretty_view()
auto* pretty_tc = &lnav_data.ld_views[LNV_PRETTY];
auto* log_tc = &lnav_data.ld_views[LNV_LOG];
auto* text_tc = &lnav_data.ld_views[LNV_TEXT];
+
+ if (top_tc == log_tc && log_tc->get_inner_height() == 0
+ && text_tc->get_inner_height() > 0)
+ {
+ lnav_data.ld_view_stack.push_back(text_tc);
+ top_tc = text_tc;
+ }
+
+ if (top_tc != log_tc && top_tc != text_tc) {
+ return;
+ }
+
attr_line_t full_text;
delete pretty_tc->get_sub_source();
@@ -305,9 +342,11 @@ open_pretty_view()
std::vector<lnav::document::section_interval_t> all_intervals;
std::vector<std::unique_ptr<lnav::document::hier_node>> hier_nodes;
std::vector<pretty_sub_source::hier_interval_t> hier_tree_vec;
+ std::set<size_t> pretty_indents;
if (top_tc == log_tc) {
auto& lss = lnav_data.ld_log_source;
bool first_line = true;
+ auto start_off = size_t{0};
for (auto vl = log_tc->get_top(); vl <= log_tc->get_bottom(); ++vl) {
content_line_t cl = lss.at(vl);
@@ -328,6 +367,11 @@ open_pretty_view()
al.get_string(),
text_sub_source::RF_FULL | text_sub_source::RF_REWRITE);
lss.text_attrs_for_line(*log_tc, vl, al.get_attrs());
+ {
+ const auto orig_lr
+ = find_string_attr_range(al.get_attrs(), &SA_ORIGINAL_LINE);
+ require(orig_lr.is_valid());
+ }
scrub_ansi_string(al.get_string(), &al.get_attrs());
if (log_tc->get_hide_fields()) {
al.apply_hide();
@@ -335,6 +379,7 @@ open_pretty_view()
const auto orig_lr
= find_string_attr_range(al.get_attrs(), &SA_ORIGINAL_LINE);
+ require(orig_lr.is_valid());
const auto body_lr
= find_string_attr_range(al.get_attrs(), &SA_BODY);
auto orig_al = al.subline(orig_lr.lr_start, orig_lr.length());
@@ -346,7 +391,6 @@ open_pretty_view()
? body_lr.lr_start - orig_lr.lr_start
: orig_lr.lr_start);
pretty_printer pp(&ds, orig_al.get_attrs());
- auto start_off = full_text.length();
if (body_lr.is_valid()) {
// TODO: dump more details of the line in the output.
@@ -356,9 +400,14 @@ open_pretty_view()
}
pretty_al.split_lines(pretty_lines);
+ auto prefix_len = prefix_al.length();
auto curr_intervals = pp.take_intervals();
auto line_hier_root = pp.take_hier_root();
+ auto curr_indents = pp.take_indents()
+ | lnav::itertools::map([&prefix_len](const auto& elem) {
+ return elem + prefix_len;
+ });
auto line_off = 0;
for (auto& pretty_line : pretty_lines) {
if (pretty_line.empty() && &pretty_line == &pretty_lines.back())
@@ -366,24 +415,24 @@ open_pretty_view()
break;
}
pretty_line.insert(0, prefix_al);
- pretty_line.append("\n");
for (auto& interval : curr_intervals) {
if (line_off <= interval.start) {
- interval.start += prefix_al.length();
- interval.stop += prefix_al.length();
+ interval.start += prefix_len;
+ interval.stop += prefix_len;
} else if (line_off < interval.stop) {
- interval.stop += prefix_al.length();
+ interval.stop += prefix_len;
}
}
lnav::document::hier_node::depth_first(
line_hier_root.get(),
- [line_off, prefix_len = prefix_al.length()](auto* hn) {
+ [line_off, prefix_len = prefix_len](auto* hn) {
if (line_off <= hn->hn_start) {
hn->hn_start += prefix_len;
}
});
- line_off += pretty_line.length();
+ line_off += pretty_line.get_string().length();
full_text.append(pretty_line);
+ full_text.append("\n");
}
first_line = false;
@@ -396,15 +445,14 @@ open_pretty_view()
[start_off](auto* hn) { hn->hn_start += start_off; });
hier_nodes.emplace_back(std::move(line_hier_root));
hier_tree_vec.emplace_back(
- start_off, full_text.length(), hier_nodes.back().get());
+ start_off, start_off + line_off, hier_nodes.back().get());
all_intervals.insert(
all_intervals.end(),
std::make_move_iterator(curr_intervals.begin()),
std::make_move_iterator(curr_intervals.end()));
- }
+ pretty_indents.insert(curr_indents.begin(), curr_indents.end());
- if (!full_text.empty()) {
- full_text.erase(full_text.length() - 1, 1);
+ start_off += line_off;
}
} else if (top_tc == text_tc) {
if (text_tc->listview_rows(*text_tc)) {
@@ -414,28 +462,46 @@ open_pretty_view()
*text_tc, text_tc->get_top(), rows);
attr_line_t orig_al;
- for (const auto& row : rows) {
+ for (auto& row : rows) {
+ remove_string_attr(row.get_attrs(), &VC_BLOCK_ELEM);
+ for (auto& attr : row.get_attrs()) {
+ if (attr.sa_type == &VC_ROLE) {
+ auto role = attr.sa_value.get<role_t>();
+
+ if (role == text_tc->tc_cursor_role
+ || role == text_tc->tc_disabled_cursor_role)
+ {
+ attr.sa_range.lr_end = attr.sa_range.lr_start;
+ }
+ }
+ }
orig_al.append(row);
}
data_scanner ds(orig_al.get_string());
- string_attrs_t sa;
pretty_printer pp(&ds, orig_al.get_attrs());
pp.append_to(full_text);
+
all_intervals = pp.take_intervals();
hier_nodes.emplace_back(pp.take_hier_root());
hier_tree_vec.emplace_back(
0, full_text.length(), hier_nodes.back().get());
+ pretty_indents = pp.take_indents();
}
}
auto* pts = new pretty_sub_source();
pts->pss_interval_tree = std::make_shared<lnav::document::sections_tree_t>(
std::move(all_intervals));
- pts->pss_hier_nods = std::move(hier_nodes);
+ auto root_node = std::make_unique<lnav::document::hier_node>();
+ root_node->hn_children = std::move(hier_nodes);
pts->pss_hier_tree = std::make_shared<pretty_sub_source::hier_tree_t>(
std::move(hier_tree_vec));
- pts->replace_with(full_text);
+ pts->pss_root_node = std::move(root_node);
+ pts->set_indents(std::move(pretty_indents));
+
+ pts->replace_with_mutable(full_text,
+ top_tc->get_sub_source()->get_text_format());
pretty_tc->set_sub_source(pts);
if (lnav_data.ld_last_pretty_print_top != log_tc->get_top()) {
pretty_tc->set_top(0_vl);
@@ -444,12 +510,6 @@ open_pretty_view()
pretty_tc->redo_search();
}
-template<typename T>
-static void
-ignore_case(const T&)
-{
-}
-
static void
build_all_help_text()
{
@@ -461,14 +521,15 @@ build_all_help_text()
std::string sub_help_text;
lexer.with_ignore_quotes(true).eval(
- sub_help_text, lnav_data.ld_exec_context.ec_global_vars);
+ sub_help_text,
+ scoped_resolver{&lnav_data.ld_exec_context.ec_global_vars});
md2attr_line mdal;
auto parse_res = md4cpp::parse(sub_help_text, mdal);
attr_line_t all_help_text = parse_res.unwrap();
- std::map<std::string, help_text*> sql_funcs;
- std::map<std::string, help_text*> sql_keywords;
+ std::map<std::string, const help_text*> sql_funcs;
+ std::map<std::string, const help_text*> sql_keywords;
for (const auto& iter : sqlite_function_help) {
switch (iter.second->ht_context) {
@@ -556,6 +617,7 @@ handle_winch()
lnav_data.ld_filter_view.set_needs_update();
lnav_data.ld_files_view.set_needs_update();
lnav_data.ld_spectro_details_view.set_needs_update();
+ lnav_data.ld_gantt_details_view.set_needs_update();
lnav_data.ld_user_message_view.set_needs_update();
return true;
@@ -564,27 +626,32 @@ handle_winch()
void
layout_views()
{
- unsigned long width, height;
-
+ static auto* breadcrumb_view = injector::get<breadcrumb_curses*>();
+ int width, height;
getmaxyx(lnav_data.ld_window, height, width);
+
int doc_height;
bool doc_side_by_side = width > (90 + 60);
- bool preview_status_open
- = !lnav_data.ld_preview_status_source.get_description().empty();
- bool filter_status_open = false;
+ bool preview_open0
+ = !lnav_data.ld_preview_status_source[0].get_description().empty();
+ bool preview_open1
+ = !lnav_data.ld_preview_status_source[1].get_description().empty();
+ bool filters_supported = false;
auto is_spectro = false;
+ auto is_gantt = false;
lnav_data.ld_view_stack.top() | [&](auto tc) {
is_spectro = (tc == &lnav_data.ld_views[LNV_SPECTRO]);
+ is_gantt = (tc == &lnav_data.ld_views[LNV_GANTT]);
- text_sub_source* tss = tc->get_sub_source();
+ auto* tss = tc->get_sub_source();
if (tss == nullptr) {
return;
}
if (tss->tss_supports_filtering) {
- filter_status_open = true;
+ filters_supported = true;
}
};
@@ -596,12 +663,25 @@ layout_views()
+ lnav_data.ld_example_source.text_line_count();
}
- int preview_height = lnav_data.ld_preview_hidden
+ int preview_height0 = lnav_data.ld_preview_hidden
? 0
- : lnav_data.ld_preview_source.text_line_count();
- int match_rows = lnav_data.ld_match_source.text_line_count();
- int match_height = std::min((unsigned long) match_rows, (height - 4) / 2);
+ : lnav_data.ld_preview_view[0].get_inner_height();
+ if (!lnav_data.ld_preview_hidden
+ && lnav_data.ld_preview_view[0].get_overlay_source() != nullptr)
+ {
+ preview_height0 = 6; // XXX extra height for db overlay
+ }
+ int preview_height1 = lnav_data.ld_preview_hidden
+ ? 0
+ : lnav_data.ld_preview_view[1].get_inner_height();
+ if (!lnav_data.ld_preview_hidden
+ && lnav_data.ld_preview_view[1].get_overlay_source() != nullptr)
+ {
+ preview_height1 = 6; // XXX extra height for db overlay
+ }
+ int match_rows = lnav_data.ld_match_source.text_line_count();
+ int match_height = std::min(match_rows, (height - 4) / 2);
lnav_data.ld_match_view.set_height(vis_line_t(match_height));
int um_rows = lnav_data.ld_user_message_source.text_line_count();
@@ -612,105 +692,150 @@ layout_views()
lnav_data.ld_user_message_source.clear();
um_rows = 0;
}
- int um_height = std::min((unsigned long) um_rows, (height - 4) / 2);
-
+ auto um_height = std::min(um_rows, (height - 4) / 2);
lnav_data.ld_user_message_view.set_height(vis_line_t(um_height));
- if (doc_height + 14
- > ((int) height - match_height - um_height - preview_height - 2))
- {
- preview_height = 0;
- preview_status_open = false;
- }
-
- if (doc_height + 14 > ((int) height - match_height - um_height - 2)) {
- doc_height = lnav_data.ld_doc_source.text_line_count();
- if (doc_height + 14 > ((int) height - match_height - um_height - 2)) {
- doc_height = 0;
- }
- }
+ auto config_panel_open = (lnav_data.ld_mode == ln_mode_t::FILTER
+ || lnav_data.ld_mode == ln_mode_t::FILES
+ || lnav_data.ld_mode == ln_mode_t::SEARCH_FILTERS
+ || lnav_data.ld_mode == ln_mode_t::SEARCH_FILES);
+ auto filters_open = (lnav_data.ld_mode == ln_mode_t::FILTER
+ || lnav_data.ld_mode == ln_mode_t::SEARCH_FILTERS);
+ auto files_open = (lnav_data.ld_mode == ln_mode_t::FILES
+ || lnav_data.ld_mode == ln_mode_t::SEARCH_FILES);
+ int filter_height = config_panel_open ? 5 : 0;
- bool doc_open = doc_height > 0;
- bool filters_open = (lnav_data.ld_mode == ln_mode_t::FILTER
- || lnav_data.ld_mode == ln_mode_t::FILES
- || lnav_data.ld_mode == ln_mode_t::SEARCH_FILTERS
- || lnav_data.ld_mode == ln_mode_t::SEARCH_FILES)
- && !preview_status_open && !doc_open;
bool breadcrumb_open = (lnav_data.ld_mode == ln_mode_t::BREADCRUMBS);
- int filter_height = filters_open ? 5 : 0;
- int bottom_height = (doc_open ? 1 : 0) + doc_height
- + (preview_status_open ? 1 : 0) + preview_height + 1 // bottom status
- + match_height + um_height + lnav_data.ld_rl_view->get_height()
- + (is_spectro && !doc_open ? 5 : 0);
+ auto bottom_min = std::min(2 + 3, height);
+ auto bottom = clamped<int>::from(height, bottom_min, height);
- for (auto& tc : lnav_data.ld_views) {
- tc.set_height(vis_line_t(-(bottom_height + (filter_status_open ? 1 : 0)
- + (filters_open ? 1 : 0) + filter_height)));
- }
- lnav_data.ld_status[LNS_FILTER].set_visible(filter_status_open);
- lnav_data.ld_status[LNS_FILTER].set_enabled(filters_open);
- lnav_data.ld_status[LNS_FILTER].set_top(
- -(bottom_height + filter_height + 1 + (filters_open ? 1 : 0)));
- lnav_data.ld_status[LNS_FILTER_HELP].set_visible(filters_open);
- lnav_data.ld_status[LNS_FILTER_HELP].set_top(
- -(bottom_height + filter_height + 1));
- lnav_data.ld_status[LNS_BOTTOM].set_top(-(match_height + um_height + 2));
- lnav_data.ld_status[LNS_BOTTOM].set_enabled(!filters_open
+ lnav_data.ld_rl_view->set_y(height - 1);
+ bottom -= lnav_data.ld_rl_view->get_height();
+ lnav_data.ld_rl_view->set_width(width);
+
+ breadcrumb_view->set_width(width);
+
+ bool vis;
+ vis = bottom.try_consume(lnav_data.ld_match_view.get_height());
+ lnav_data.ld_match_view.set_y(bottom);
+ lnav_data.ld_match_view.set_visible(vis);
+
+ vis = bottom.try_consume(um_height);
+ lnav_data.ld_user_message_view.set_y(bottom);
+ lnav_data.ld_user_message_view.set_visible(vis);
+
+ bottom -= 1;
+ lnav_data.ld_status[LNS_BOTTOM].set_y(bottom);
+ lnav_data.ld_status[LNS_BOTTOM].set_width(width);
+ lnav_data.ld_status[LNS_BOTTOM].set_enabled(!config_panel_open
&& !breadcrumb_open);
- lnav_data.ld_status[LNS_DOC].set_top(height - bottom_height);
- lnav_data.ld_status[LNS_DOC].set_visible(doc_open);
- lnav_data.ld_status[LNS_PREVIEW].set_top(height - bottom_height
- + (doc_open ? 1 : 0) + doc_height);
- lnav_data.ld_status[LNS_PREVIEW].set_visible(preview_status_open);
- lnav_data.ld_status[LNS_SPECTRO].set_top(height - bottom_height - 1);
- lnav_data.ld_status[LNS_SPECTRO].set_visible(is_spectro);
- lnav_data.ld_status[LNS_SPECTRO].set_enabled(lnav_data.ld_mode
- == ln_mode_t::SPECTRO_DETAILS);
- if (!doc_open || doc_side_by_side) {
- lnav_data.ld_doc_view.set_height(vis_line_t(doc_height));
+ vis = preview_open1 && bottom.try_consume(preview_height1 + 1);
+ lnav_data.ld_preview_view[1].set_height(vis_line_t(preview_height1));
+ lnav_data.ld_preview_view[1].set_y(bottom + 1);
+ lnav_data.ld_preview_view[1].set_visible(vis);
+
+ lnav_data.ld_status[LNS_PREVIEW1].set_y(bottom);
+ lnav_data.ld_status[LNS_PREVIEW1].set_width(width);
+ lnav_data.ld_status[LNS_PREVIEW1].set_visible(vis);
+
+ vis = preview_open0 && bottom.try_consume(preview_height0 + 1);
+ lnav_data.ld_preview_view[0].set_height(vis_line_t(preview_height0));
+ lnav_data.ld_preview_view[0].set_y(bottom + 1);
+ lnav_data.ld_preview_view[0].set_visible(vis);
+
+ lnav_data.ld_status[LNS_PREVIEW0].set_y(bottom);
+ lnav_data.ld_status[LNS_PREVIEW0].set_width(width);
+ lnav_data.ld_status[LNS_PREVIEW0].set_visible(vis);
+
+ if (doc_side_by_side && doc_height > 0) {
+ vis = bottom.try_consume(doc_height + 1);
+ lnav_data.ld_example_view.set_height(vis_line_t(doc_height));
+ lnav_data.ld_example_view.set_x(90);
+ lnav_data.ld_example_view.set_y(bottom + 1);
+ } else if (doc_height > 0 && bottom.available_to_consume(doc_height + 1)) {
+ lnav_data.ld_example_view.set_height(
+ vis_line_t(lnav_data.ld_example_source.text_line_count()));
+ vis = bottom.try_consume(lnav_data.ld_example_view.get_height());
+ lnav_data.ld_example_view.set_x(0);
+ lnav_data.ld_example_view.set_y(bottom);
} else {
+ vis = false;
+ lnav_data.ld_example_view.set_height(0_vl);
+ }
+ lnav_data.ld_example_view.set_visible(vis);
+
+ if (doc_side_by_side) {
+ lnav_data.ld_doc_view.set_height(vis_line_t(doc_height));
+ lnav_data.ld_doc_view.set_y(bottom + 1);
+ } else if (doc_height > 0) {
lnav_data.ld_doc_view.set_height(
vis_line_t(lnav_data.ld_doc_source.text_line_count()));
+ vis = bottom.try_consume(lnav_data.ld_doc_view.get_height() + 1);
+ lnav_data.ld_doc_view.set_y(bottom + 1);
+ } else {
+ vis = false;
}
- lnav_data.ld_doc_view.set_y(height - bottom_height + 1);
+ lnav_data.ld_doc_view.set_visible(vis);
- if (!doc_open || doc_side_by_side) {
- lnav_data.ld_example_view.set_height(vis_line_t(doc_height));
- lnav_data.ld_example_view.set_x(doc_open ? 90 : 0);
- lnav_data.ld_example_view.set_y(height - bottom_height + 1);
+ auto has_doc = lnav_data.ld_example_view.get_height() > 0_vl
+ || lnav_data.ld_doc_view.get_height() > 0_vl;
+ lnav_data.ld_status[LNS_DOC].set_y(bottom);
+ lnav_data.ld_status[LNS_DOC].set_width(width);
+ lnav_data.ld_status[LNS_DOC].set_visible(has_doc && vis);
+
+ if (is_gantt) {
+ vis = bottom.try_consume(lnav_data.ld_gantt_details_view.get_height()
+ + 1);
} else {
- lnav_data.ld_example_view.set_height(
- vis_line_t(lnav_data.ld_example_source.text_line_count()));
- lnav_data.ld_example_view.set_x(0);
- lnav_data.ld_example_view.set_y(
- height - bottom_height + lnav_data.ld_doc_view.get_height() + 1);
+ vis = false;
}
+ lnav_data.ld_gantt_details_view.set_y(bottom + 1);
+ lnav_data.ld_gantt_details_view.set_width(width);
+ lnav_data.ld_gantt_details_view.set_visible(vis);
+ lnav_data.ld_status[LNS_GANTT].set_y(bottom);
+ lnav_data.ld_status[LNS_GANTT].set_width(width);
+ lnav_data.ld_status[LNS_GANTT].set_visible(vis);
+
+ vis = bottom.try_consume(filter_height + (config_panel_open ? 1 : 0)
+ + (filters_supported ? 1 : 0));
lnav_data.ld_filter_view.set_height(vis_line_t(filter_height));
- lnav_data.ld_filter_view.set_y(height - bottom_height - filter_height);
+ lnav_data.ld_filter_view.set_y(bottom + 2);
lnav_data.ld_filter_view.set_width(width);
+ lnav_data.ld_filter_view.set_visible(filters_open && vis);
lnav_data.ld_files_view.set_height(vis_line_t(filter_height));
- lnav_data.ld_files_view.set_y(height - bottom_height - filter_height);
+ lnav_data.ld_files_view.set_y(bottom + 2);
lnav_data.ld_files_view.set_width(width);
+ lnav_data.ld_files_view.set_visible(files_open && vis);
+
+ lnav_data.ld_status[LNS_FILTER_HELP].set_visible(config_panel_open && vis);
+ lnav_data.ld_status[LNS_FILTER_HELP].set_y(bottom + 1);
+ lnav_data.ld_status[LNS_FILTER_HELP].set_width(width);
- lnav_data.ld_preview_view.set_height(vis_line_t(preview_height));
- lnav_data.ld_preview_view.set_y(height - bottom_height + 1
- + (doc_open ? 1 : 0) + doc_height);
- lnav_data.ld_user_message_view.set_y(
- height - lnav_data.ld_rl_view->get_height() - match_height - um_height);
+ lnav_data.ld_status[LNS_FILTER].set_visible(vis);
+ lnav_data.ld_status[LNS_FILTER].set_enabled(config_panel_open);
+ lnav_data.ld_status[LNS_FILTER].set_y(bottom);
+ lnav_data.ld_status[LNS_FILTER].set_width(width);
- lnav_data.ld_spectro_details_view.set_y(height - bottom_height);
- lnav_data.ld_spectro_details_view.set_height(
- is_spectro && !doc_open ? 5_vl : 0_vl);
+ vis = is_spectro && bottom.try_consume(5 + 1);
+ lnav_data.ld_spectro_details_view.set_y(bottom + 1);
+ lnav_data.ld_spectro_details_view.set_height(5_vl);
lnav_data.ld_spectro_details_view.set_width(width);
- lnav_data.ld_spectro_details_view.set_title("spectro-details");
+ lnav_data.ld_spectro_details_view.set_visible(vis);
- lnav_data.ld_match_view.set_y(height - lnav_data.ld_rl_view->get_height()
- - match_height);
- lnav_data.ld_rl_view->set_width(width);
+ lnav_data.ld_status[LNS_SPECTRO].set_y(bottom);
+ lnav_data.ld_status[LNS_SPECTRO].set_width(width);
+ lnav_data.ld_status[LNS_SPECTRO].set_visible(vis);
+ lnav_data.ld_status[LNS_SPECTRO].set_enabled(lnav_data.ld_mode
+ == ln_mode_t::SPECTRO_DETAILS);
+
+ auto bottom_used = bottom - height;
+ for (auto& tc : lnav_data.ld_views) {
+ tc.set_height(vis_line_t(bottom_used));
+ }
}
void
@@ -731,7 +856,7 @@ update_hits(textview_curses* tc)
int preview_count = 0;
- vis_bookmarks& bm = tc->get_bookmarks();
+ auto& bm = tc->get_bookmarks();
const auto& bv = bm[&textview_curses::BM_SEARCH];
auto vl = tc->get_top();
unsigned long width;
@@ -803,11 +928,15 @@ update_hits(textview_curses* tc)
}
if (preview_count > 0) {
- lnav_data.ld_preview_status_source.get_description().set_value(
- "Matching lines for search");
- lnav_data.ld_preview_source.replace_with(all_matches)
+ lnav_data.ld_preview_status_source[0]
+ .get_description()
+ .set_value("Matching lines for search");
+ lnav_data.ld_preview_view[0].set_sub_source(
+ &lnav_data.ld_preview_source[0]);
+ lnav_data.ld_preview_source[0]
+ .replace_with(all_matches)
.set_text_format(text_format_t::TF_UNKNOWN);
- lnav_data.ld_preview_view.set_needs_update();
+ lnav_data.ld_preview_view[0].set_needs_update();
}
}
}
@@ -815,68 +944,112 @@ update_hits(textview_curses* tc)
static std::unordered_map<std::string, attr_line_t> EXAMPLE_RESULTS;
-void
-execute_examples()
+static void
+execute_example(const help_text& ht)
{
- db_label_source& dls = lnav_data.ld_db_row_source;
- db_overlay_source& dos = lnav_data.ld_db_overlay;
- textview_curses& db_tc = lnav_data.ld_views[LNV_DB];
+ static const std::set<std::string> IGNORED_NAMES = {"ATTACH"};
- for (auto& help_iter : sqlite_function_help) {
- struct help_text& ht = *(help_iter.second);
+ if (IGNORED_NAMES.count(ht.ht_name)) {
+ return;
+ }
- for (auto& ex : ht.ht_example) {
- std::string alt_msg;
- attr_line_t result;
+ auto& dls = lnav_data.ld_db_row_source;
+ auto& dos = lnav_data.ld_db_overlay;
+ auto& db_tc = lnav_data.ld_views[LNV_DB];
- if (!ex.he_cmd) {
- continue;
- }
+ for (const auto& ex : ht.ht_example) {
+ std::string alt_msg;
+ attr_line_t result;
- switch (ht.ht_context) {
- case help_context_t::HC_SQL_KEYWORD:
- case help_context_t::HC_SQL_INFIX:
- case help_context_t::HC_SQL_FUNCTION:
- case help_context_t::HC_SQL_TABLE_VALUED_FUNCTION: {
- exec_context ec;
+ if (!ex.he_cmd) {
+ continue;
+ }
+
+ if (EXAMPLE_RESULTS.count(ex.he_cmd)) {
+ continue;
+ }
+
+ switch (ht.ht_context) {
+ case help_context_t::HC_SQL_KEYWORD:
+ case help_context_t::HC_SQL_INFIX:
+ case help_context_t::HC_SQL_FUNCTION:
+ case help_context_t::HC_SQL_TABLE_VALUED_FUNCTION:
+ case help_context_t::HC_PRQL_TRANSFORM:
+ case help_context_t::HC_PRQL_FUNCTION: {
+ exec_context ec;
+
+ ec.ec_label_source_stack.push_back(&dls);
- execute_sql(ec, ex.he_cmd, alt_msg);
+ auto exec_res = execute_sql(ec, ex.he_cmd, alt_msg);
- if (dls.dls_rows.size() == 1 && dls.dls_rows[0].size() == 1)
+ if (exec_res.isErr()) {
+ auto um = exec_res.unwrapErr();
+ result.append(um.to_attr_line());
+ } else if (dls.dls_rows.size() == 1
+ && dls.dls_rows[0].size() == 1)
+ {
+ result.append(dls.dls_rows[0][0]);
+ } else {
+ attr_line_t al;
+ dos.list_static_overlay(db_tc, 0, 1, al);
+ result.append(al);
+ for (int lpc = 0; lpc < (int) dls.text_line_count(); lpc++)
{
- result.append(dls.dls_rows[0][0]);
- } else {
- attr_line_t al;
- dos.list_value_for_overlay(db_tc, 0, 1, 0_vl, al);
- result.append(al);
- for (int lpc = 0; lpc < (int) dls.text_line_count();
- lpc++)
- {
- al.clear();
- dls.text_value_for_line(
- db_tc, lpc, al.get_string(), false);
- dls.text_attrs_for_line(db_tc, lpc, al.get_attrs());
- std::replace(al.get_string().begin(),
- al.get_string().end(),
- '\n',
- ' ');
- result.append("\n").append(al);
- }
+ al.clear();
+ dls.text_value_for_line(
+ db_tc, lpc, al.get_string(), false);
+ dls.text_attrs_for_line(db_tc, lpc, al.get_attrs());
+ std::replace(al.get_string().begin(),
+ al.get_string().end(),
+ '\n',
+ ' ');
+ result.append("\n").append(al);
}
+ }
- EXAMPLE_RESULTS[ex.he_cmd] = result;
+ EXAMPLE_RESULTS[ex.he_cmd] = result;
- log_debug("example: %s", ex.he_cmd);
- log_debug("example result: %s",
- result.get_string().c_str());
- break;
- }
- default:
- log_warning("Not executing example: %s", ex.he_cmd);
- break;
+ log_trace("example: %s", ex.he_cmd);
+ log_trace("example result: %s", result.get_string().c_str());
+ break;
}
+ default:
+ log_warning("Not executing example: %s", ex.he_cmd);
+ break;
+ }
+ }
+}
+
+void
+execute_examples()
+{
+ static const auto* sql_cmd_map
+ = injector::get<readline_context::command_map_t*, sql_cmd_map_tag>();
+
+ auto& dls = lnav_data.ld_db_row_source;
+
+ auto old_width = dls.dls_max_column_width;
+ dls.dls_max_column_width = 15;
+ for (auto help_pair : sqlite_function_help) {
+ execute_example(*help_pair.second);
+ }
+ for (auto help_pair : lnav::sql::prql_functions) {
+ if (help_pair.second->ht_context != help_context_t::HC_PRQL_FUNCTION) {
+ continue;
}
+ execute_example(*help_pair.second);
}
+ for (auto cmd_pair : *sql_cmd_map) {
+ if (cmd_pair.second->c_help.ht_context
+ != help_context_t::HC_PRQL_TRANSFORM
+ && cmd_pair.second->c_help.ht_context
+ != help_context_t::HC_PRQL_FUNCTION)
+ {
+ continue;
+ }
+ execute_example(cmd_pair.second->c_help);
+ }
+ dls.dls_max_column_width = old_width;
dls.clear();
}
@@ -903,12 +1076,27 @@ toggle_view(textview_curses* toggle_tc)
require(toggle_tc >= &lnav_data.ld_views[0]);
require(toggle_tc < &lnav_data.ld_views[LNV__MAX]);
+ lnav_data.ld_preview_view[0].set_sub_source(
+ &lnav_data.ld_preview_source[0]);
+ lnav_data.ld_preview_source[0].clear();
+ lnav_data.ld_preview_status_source[0].get_description().clear();
+ lnav_data.ld_preview_view[1].set_sub_source(nullptr);
+ lnav_data.ld_preview_status_source[1].get_description().clear();
+
if (tc == toggle_tc) {
if (lnav_data.ld_view_stack.size() == 1) {
return false;
}
lnav_data.ld_last_view = tc;
lnav_data.ld_view_stack.pop_back();
+ lnav_data.ld_view_stack.top() | [](auto* tc) {
+ // XXX
+ if (tc == &lnav_data.ld_views[LNV_GANTT]) {
+ auto tss = tc->get_sub_source();
+ tss->text_filters_changed();
+ tc->reload_data();
+ }
+ };
} else {
if (toggle_tc == &lnav_data.ld_views[LNV_LOG]
|| toggle_tc == &lnav_data.ld_views[LNV_TEXT])
@@ -919,6 +1107,8 @@ toggle_view(textview_curses* toggle_tc)
open_schema_view();
} else if (toggle_tc == &lnav_data.ld_views[LNV_PRETTY]) {
open_pretty_view();
+ } else if (toggle_tc == &lnav_data.ld_views[LNV_GANTT]) {
+ open_gantt_view();
} else if (toggle_tc == &lnav_data.ld_views[LNV_HISTOGRAM]) {
// Rebuild to reflect changes in marks.
rebuild_hist();
@@ -946,7 +1136,7 @@ toggle_view(textview_curses* toggle_tc)
bool
ensure_view(textview_curses* expected_tc)
{
- textview_curses* tc = lnav_data.ld_view_stack.top().value_or(nullptr);
+ auto* tc = lnav_data.ld_view_stack.top().value_or(nullptr);
bool retval = true;
if (tc != expected_tc) {
@@ -1211,4 +1401,194 @@ lnav_crumb_source()
}
return retval;
-} \ No newline at end of file
+}
+
+void
+clear_preview()
+{
+ for (size_t lpc = 0; lpc < 2; lpc++) {
+ lnav_data.ld_preview_source[lpc].clear();
+ lnav_data.ld_preview_status_source[lpc]
+ .get_description()
+ .set_cylon(false)
+ .clear();
+ lnav_data.ld_db_preview_source[lpc].clear();
+ lnav_data.ld_preview_view[lpc].set_sub_source(nullptr);
+ lnav_data.ld_preview_view[lpc].set_overlay_source(nullptr);
+ }
+}
+
+void
+set_view_mode(ln_mode_t mode)
+{
+ if (mode == lnav_data.ld_mode) {
+ return;
+ }
+
+ static auto* breadcrumb_view = injector::get<breadcrumb_curses*>();
+
+ switch (lnav_data.ld_mode) {
+ case ln_mode_t::BREADCRUMBS: {
+ breadcrumb_view->blur();
+ break;
+ }
+ default:
+ break;
+ }
+ switch (mode) {
+ case ln_mode_t::BREADCRUMBS: {
+ breadcrumb_view->focus();
+ break;
+ }
+ default:
+ break;
+ }
+ lnav_data.ld_mode = mode;
+}
+
+static std::vector<view_curses*>
+all_views()
+{
+ static auto* breadcrumb_view = injector::get<breadcrumb_curses*>();
+
+ std::vector<view_curses*> retval;
+
+ retval.push_back(breadcrumb_view);
+ for (auto& sc : lnav_data.ld_status) {
+ retval.push_back(&sc);
+ }
+ retval.push_back(&lnav_data.ld_doc_view);
+ retval.push_back(&lnav_data.ld_example_view);
+ retval.push_back(&lnav_data.ld_preview_view[0]);
+ retval.push_back(&lnav_data.ld_preview_view[1]);
+ retval.push_back(&lnav_data.ld_files_view);
+ retval.push_back(&lnav_data.ld_filter_view);
+ retval.push_back(&lnav_data.ld_user_message_view);
+ retval.push_back(&lnav_data.ld_spectro_details_view);
+ retval.push_back(&lnav_data.ld_gantt_details_view);
+ retval.push_back(lnav_data.ld_rl_view);
+
+ return retval;
+}
+
+void
+lnav_behavior::mouse_event(int button, bool release, int x, int y)
+{
+ static auto* breadcrumb_view = injector::get<breadcrumb_curses*>();
+ static const std::vector<view_curses*> VIEWS = all_views();
+ static const auto CLICK_INTERVAL
+ = std::chrono::milliseconds(mouseinterval(-1) * 2);
+
+ struct mouse_event me;
+
+ switch (button & xterm_mouse::XT_BUTTON__MASK) {
+ case xterm_mouse::XT_BUTTON1:
+ me.me_button = mouse_button_t::BUTTON_LEFT;
+ break;
+ case xterm_mouse::XT_BUTTON2:
+ me.me_button = mouse_button_t::BUTTON_MIDDLE;
+ break;
+ case xterm_mouse::XT_BUTTON3:
+ me.me_button = mouse_button_t::BUTTON_RIGHT;
+ break;
+ case xterm_mouse::XT_SCROLL_UP:
+ me.me_button = mouse_button_t::BUTTON_SCROLL_UP;
+ break;
+ case xterm_mouse::XT_SCROLL_DOWN:
+ me.me_button = mouse_button_t::BUTTON_SCROLL_DOWN;
+ break;
+ }
+
+ gettimeofday(&me.me_time, nullptr);
+ me.me_modifiers = button & xterm_mouse::XT_MODIFIER_MASK;
+
+ if (release
+ && (to_mstime(me.me_time)
+ - to_mstime(this->lb_last_release_event.me_time))
+ < CLICK_INTERVAL.count())
+ {
+ me.me_state = mouse_button_state_t::BUTTON_STATE_DOUBLE_CLICK;
+ } else if (button & xterm_mouse::XT_DRAG_FLAG) {
+ me.me_state = mouse_button_state_t::BUTTON_STATE_DRAGGED;
+ } else if (release) {
+ me.me_state = mouse_button_state_t::BUTTON_STATE_RELEASED;
+ } else {
+ me.me_state = mouse_button_state_t::BUTTON_STATE_PRESSED;
+ }
+
+ auto width = getmaxx(lnav_data.ld_window);
+
+ me.me_press_x = this->lb_last_event.me_press_x;
+ me.me_press_y = this->lb_last_event.me_press_y;
+ me.me_x = x - 1;
+ if (me.me_x >= width) {
+ me.me_x = width - 1;
+ }
+ me.me_y = y - 1;
+
+ switch (me.me_state) {
+ case mouse_button_state_t::BUTTON_STATE_PRESSED:
+ case mouse_button_state_t::BUTTON_STATE_DOUBLE_CLICK: {
+ if (lnav_data.ld_mode == ln_mode_t::BREADCRUMBS) {
+ if (breadcrumb_view->contains(me.me_x, me.me_y)) {
+ this->lb_last_view = breadcrumb_view;
+ break;
+ } else {
+ set_view_mode(ln_mode_t::PAGING);
+ lnav_data.ld_view_stack.set_needs_update();
+ }
+ }
+
+ auto* tc = *(lnav_data.ld_view_stack.top());
+ if (tc->contains(me.me_x, me.me_y)) {
+ me.me_press_y = me.me_y - tc->get_y();
+ me.me_press_x = me.me_x - tc->get_x();
+ this->lb_last_view = tc;
+
+ switch (lnav_data.ld_mode) {
+ case ln_mode_t::PAGING:
+ break;
+ case ln_mode_t::FILES:
+ case ln_mode_t::FILTER:
+ // Clicking on the main view when the config panels are
+ // open should return us to paging.
+ set_view_mode(ln_mode_t::PAGING);
+ break;
+ default:
+ break;
+ }
+ } else {
+ for (auto* vc : VIEWS) {
+ if (vc->contains(me.me_x, me.me_y)) {
+ this->lb_last_view = vc;
+ me.me_press_y = me.me_y - vc->get_y();
+ me.me_press_x = me.me_x - vc->get_x();
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case mouse_button_state_t::BUTTON_STATE_DRAGGED: {
+ break;
+ }
+ case mouse_button_state_t::BUTTON_STATE_RELEASED: {
+ this->lb_last_release_event = me;
+ break;
+ }
+ }
+
+ if (this->lb_last_view != nullptr) {
+ me.me_y -= this->lb_last_view->get_y();
+ me.me_x -= this->lb_last_view->get_x();
+ this->lb_last_view->handle_mouse(me);
+ }
+ this->lb_last_event = me;
+ if (me.me_state == mouse_button_state_t::BUTTON_STATE_RELEASED
+ || me.me_state == mouse_button_state_t::BUTTON_STATE_DOUBLE_CLICK
+ || me.me_button == mouse_button_t::BUTTON_SCROLL_UP
+ || me.me_button == mouse_button_t::BUTTON_SCROLL_DOWN)
+ {
+ this->lb_last_view = nullptr;
+ }
+}