diff options
Diffstat (limited to '')
-rw-r--r-- | src/view_helpers.cc | 724 |
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; + } +} |