diff options
Diffstat (limited to '')
-rw-r--r-- | src/hotkeys.cc | 305 |
1 files changed, 136 insertions, 169 deletions
diff --git a/src/hotkeys.cc b/src/hotkeys.cc index dd3af90..742998f 100644 --- a/src/hotkeys.cc +++ b/src/hotkeys.cc @@ -38,18 +38,12 @@ #include "bound_tags.hh" #include "command_executor.hh" #include "config.h" -#include "environ_vtab.hh" #include "field_overlay_source.hh" #include "lnav.hh" #include "lnav_config.hh" -#include "lnav_util.hh" -#include "log_data_helper.hh" -#include "plain_text_source.hh" -#include "readline_highlighters.hh" #include "shlex.hh" #include "sql_util.hh" -#include "sysclip.hh" -#include "termios_guard.hh" +#include "sqlitepp.client.hh" #include "xterm_mouse.hh" using namespace lnav::roles::literals; @@ -151,8 +145,7 @@ key_sql_callback(exec_context& ec, sqlite3_stmt* stmt) bool handle_keyseq(const char* keyseq) { - key_map& km = lnav_config.lc_active_keymap; - + const auto& km = lnav_config.lc_active_keymap; const auto& iter = km.km_seq_to_cmd.find(keyseq); if (iter == km.km_seq_to_cmd.end()) { return false; @@ -162,16 +155,23 @@ handle_keyseq(const char* keyseq) exec_context ec(&values, key_sql_callback, pipe_callback); auto& var_stack = ec.ec_local_vars; + ec.ec_label_source_stack.push_back(&lnav_data.ld_db_row_source); ec.ec_global_vars = lnav_data.ld_exec_context.ec_global_vars; ec.ec_error_callback_stack = lnav_data.ld_exec_context.ec_error_callback_stack; var_stack.push(std::map<std::string, scoped_value_t>()); + // XXX push another so it doesn't look like interactive use + var_stack.push(std::map<std::string, scoped_value_t>()); auto& vars = var_stack.top(); vars["keyseq"] = keyseq; const auto& kc = iter->second; - log_debug("executing key sequence %s: %s", keyseq, kc.kc_cmd.c_str()); - auto result = execute_any(ec, kc.kc_cmd); + log_debug( + "executing key sequence %s: %s", keyseq, kc.kc_cmd.pp_value.c_str()); + auto sg = ec.enter_source(kc.kc_cmd.pp_location.sl_source, + kc.kc_cmd.pp_location.sl_line_number, + kc.kc_cmd.pp_value); + auto result = execute_any(ec, kc.kc_cmd.pp_value); if (result.isOk()) { lnav_data.ld_rl_view->set_value(result.unwrap()); } else { @@ -198,7 +198,7 @@ handle_keyseq(const char* keyseq) } bool -handle_paging_key(int ch) +handle_paging_key(int ch, const char* keyseq) { if (lnav_data.ld_view_stack.empty()) { return false; @@ -206,12 +206,16 @@ handle_paging_key(int ch) textview_curses* tc = *lnav_data.ld_view_stack.top(); exec_context& ec = lnav_data.ld_exec_context; - logfile_sub_source* lss = nullptr; text_sub_source* tc_tss = tc->get_sub_source(); bookmarks<vis_line_t>::type& bm = tc->get_bookmarks(); - auto keyseq = fmt::format(FMT_STRING("x{:02x}"), ch); - if (handle_keyseq(keyseq.c_str())) { + if (tc->get_overlay_selection()) { + if (tc->handle_key(ch)) { + return true; + } + } + + if (handle_keyseq(keyseq)) { return true; } @@ -219,7 +223,8 @@ handle_paging_key(int ch) return true; } - lss = dynamic_cast<logfile_sub_source*>(tc->get_sub_source()); + auto lss = dynamic_cast<logfile_sub_source*>(tc->get_sub_source()); + auto text_accel_p = dynamic_cast<text_accel_source*>(tc->get_sub_source()); /* process the command keystroke */ switch (ch) { @@ -252,8 +257,8 @@ handle_paging_key(int ch) lnav_data.ld_last_view = nullptr; if (src_view != nullptr && dst_view != nullptr) { src_view->time_for_row(top_tc->get_selection()) | - [dst_view, tc](auto top_time) { - dst_view->row_for_time(top_time) | + [dst_view, tc](auto top_ri) { + dst_view->row_for_time(top_ri.ri_time) | [tc](auto row) { tc->set_selection(row); }; }; } @@ -265,16 +270,27 @@ handle_paging_key(int ch) if (xterm_mouse::is_available()) { auto& mouse_i = injector::get<xterm_mouse&>(); mouse_i.set_enabled(!mouse_i.is_enabled()); - auto um = lnav::console::user_message::ok( - attr_line_t("mouse mode -- ") - .append(mouse_i.is_enabled() ? "enabled"_symbol - : "disabled"_symbol)); + + auto al = attr_line_t("mouse mode -- ") + .append(mouse_i.is_enabled() ? "enabled"_symbol + : "disabled"_symbol); + if (mouse_i.is_enabled() + && lnav_config.lc_mouse_mode == lnav_mouse_mode::disabled) + { + al.append(" -- enable permanently with ") + .append(":config /ui/mouse/mode enabled"_quoted_code); + + auto clear_note = prepare_stmt(lnav_data.ld_db, R"( +DELETE FROM lnav_user_notifications WHERE id = 'org.lnav.mouse-support' +)"); + clear_note.unwrap().execute(); + } + auto um = lnav::console::user_message::ok(al); lnav_data.ld_rl_view->set_attr_value(um.to_attr_line()); } else { lnav_data.ld_rl_view->set_value( "error: mouse support is not available, make sure your " - "TERM is set to " - "xterm or xterm-256color"); + "TERM is set to xterm or xterm-256color"); } break; @@ -303,7 +319,8 @@ handle_paging_key(int ch) } else { alerter::singleton().chime("no more search hits to the right"); } - } break; + break; + } case '<': if (tc->get_left() == 0) { @@ -377,36 +394,45 @@ handle_paging_key(int ch) break; case 'J': - if (lnav_data.ld_last_user_mark.find(tc) - == lnav_data.ld_last_user_mark.end() - || !tc->is_line_visible( - vis_line_t(lnav_data.ld_last_user_mark[tc]))) - { - lnav_data.ld_select_start[tc] = tc->get_selection(); - lnav_data.ld_last_user_mark[tc] = tc->get_selection(); - } else { - vis_line_t height; - unsigned long width; - - tc->get_dimensions(height, width); - if (lnav_data.ld_last_user_mark[tc] > (tc->get_bottom() - 2) - && tc->get_selection() + height < tc->get_inner_height()) - { - tc->shift_top(1_vl); + if (tc->is_selectable()) { + if (tc->get_selection() >= 0_vl) { + tc->toggle_user_mark(&textview_curses::BM_USER, + tc->get_selection()); + lnav_data.ld_select_start[tc] = tc->get_selection(); + lnav_data.ld_last_user_mark[tc] = tc->get_selection(); + if (tc->get_selection() + 1_vl < tc->get_inner_height()) { + tc->set_selection(tc->get_selection() + 1_vl); + } } - if (lnav_data.ld_last_user_mark[tc] + 1 - >= tc->get_inner_height()) + } else { + if (lnav_data.ld_last_user_mark.find(tc) + == lnav_data.ld_last_user_mark.end() + || !tc->is_line_visible( + vis_line_t(lnav_data.ld_last_user_mark[tc]))) { - break; + lnav_data.ld_select_start[tc] = tc->get_selection(); + lnav_data.ld_last_user_mark[tc] = tc->get_selection(); + } else { + vis_line_t height; + unsigned long width; + + tc->get_dimensions(height, width); + if (lnav_data.ld_last_user_mark[tc] > (tc->get_bottom() - 2) + && tc->get_selection() + height + < tc->get_inner_height()) + { + tc->shift_top(1_vl); + } + if (lnav_data.ld_last_user_mark[tc] + 1 + >= tc->get_inner_height()) + { + break; + } + lnav_data.ld_last_user_mark[tc] += 1; } - lnav_data.ld_last_user_mark[tc] += 1; - } - tc->toggle_user_mark(&textview_curses::BM_USER, - vis_line_t(lnav_data.ld_last_user_mark[tc])); - if (tc->is_selectable() - && tc->get_selection() + 1_vl < tc->get_inner_height()) - { - tc->set_selection(tc->get_selection() + 1_vl); + tc->toggle_user_mark( + &textview_curses::BM_USER, + vis_line_t(lnav_data.ld_last_user_mark[tc])); } tc->reload_data(); @@ -485,20 +511,28 @@ handle_paging_key(int ch) #endif case 's': - if (lss) { - auto next_top = tc->get_selection() + 2_vl; + if (text_accel_p && text_accel_p->is_time_offset_supported()) { + auto next_top = tc->get_selection() + 1_vl; + + if (!tc->is_selectable()) { + next_top += 1_vl; + } - if (!lss->is_time_offset_enabled()) { + if (!text_accel_p->is_time_offset_enabled()) { lnav_data.ld_rl_view->set_alt_value( HELP_MSG_1(T, "to disable elapsed-time mode")); } - lss->set_time_offset(true); + text_accel_p->set_time_offset(true); while (next_top < tc->get_inner_height()) { - if (!lss->find_line(lss->at(next_top))->is_message()) { - } else if (lss->get_line_accel_direction(next_top) + if (!text_accel_p->text_accel_get_line(next_top) + ->is_message()) + { + } else if (text_accel_p->get_line_accel_direction(next_top) == log_accel::A_DECEL) { - --next_top; + if (!tc->is_selectable()) { + --next_top; + } tc->set_selection(next_top); break; } @@ -509,20 +543,27 @@ handle_paging_key(int ch) break; case 'S': - if (lss) { + if (text_accel_p && text_accel_p->is_time_offset_supported()) { auto next_top = tc->get_selection(); - if (!lss->is_time_offset_enabled()) { + if (tc->is_selectable() && next_top > 0_vl) { + next_top -= 1_vl; + } + if (!text_accel_p->is_time_offset_enabled()) { lnav_data.ld_rl_view->set_alt_value( HELP_MSG_1(T, "to disable elapsed-time mode")); } - lss->set_time_offset(true); + text_accel_p->set_time_offset(true); while (0 <= next_top && next_top < tc->get_inner_height()) { - if (!lss->find_line(lss->at(next_top))->is_message()) { - } else if (lss->get_line_accel_direction(next_top) + if (!text_accel_p->text_accel_get_line(next_top) + ->is_message()) + { + } else if (text_accel_p->get_line_accel_direction(next_top) == log_accel::A_DECEL) { - --next_top; + if (!tc->is_selectable()) { + --next_top; + } tc->set_selection(next_top); break; } @@ -552,9 +593,9 @@ handle_paging_key(int ch) if (lss) { const int step = 24 * 60 * 60; lss->time_for_row(tc->get_selection()) | - [lss, tc](auto first_time) { + [lss, tc](auto first_ri) { lss->find_from_time( - roundup_size(first_time.tv_sec, step)) + roundup_size(first_ri.ri_time.tv_sec, step)) | [tc](auto line) { tc->set_selection(line); }; }; } @@ -563,8 +604,9 @@ handle_paging_key(int ch) case ')': if (lss) { lss->time_for_row(tc->get_selection()) | - [lss, tc](auto first_time) { - time_t day = rounddown(first_time.tv_sec, 24 * 60 * 60); + [lss, tc](auto first_ri) { + time_t day + = rounddown(first_ri.ri_time.tv_sec, 24 * 60 * 60); lss->find_from_time(day) | [tc](auto line) { if (line != 0_vl) { --line; @@ -581,9 +623,9 @@ handle_paging_key(int ch) "the top of the log has been reached"); } else if (lss) { lss->time_for_row(tc->get_selection()) | - [lss, ch, tc](auto first_time) { + [lss, ch, tc](auto first_ri) { int step = ch == 'D' ? (24 * 60 * 60) : (60 * 60); - time_t top_time = first_time.tv_sec; + time_t top_time = first_ri.ri_time.tv_sec; lss->find_from_time(top_time - step) | [tc](auto line) { if (line != 0_vl) { --line; @@ -599,9 +641,9 @@ handle_paging_key(int ch) case 'd': if (lss) { lss->time_for_row(tc->get_selection()) | - [ch, lss, tc](auto first_time) { + [ch, lss, tc](auto first_ri) { int step = ch == 'd' ? (24 * 60 * 60) : (60 * 60); - lss->find_from_time(first_time.tv_sec + step) | + lss->find_from_time(first_ri.ri_time.tv_sec + step) | [tc](auto line) { tc->set_selection(line); }; }; @@ -618,9 +660,9 @@ handle_paging_key(int ch) auto& start_line = start_helper.move_to_msg_start(); start_helper.annotate(); - struct line_range opid_range = find_string_attr_range( - start_helper.lh_string_attrs, &logline::L_OPID); - if (!opid_range.is_valid()) { + const auto& opid_opt + = start_helper.lh_line_values.lvv_opid_value; + if (!opid_opt) { alerter::singleton().chime( "Log message does not contain an opid"); lnav_data.ld_rl_view->set_attr_value( @@ -654,19 +696,10 @@ handle_paging_key(int ch) continue; } next_helper.annotate(); - struct line_range opid_next_range - = find_string_attr_range( - next_helper.lh_string_attrs, &logline::L_OPID); - const char* start_opid - = start_helper.lh_line_values.lvv_sbr.get_data_at( - opid_range.lr_start); - const char* next_opid - = next_helper.lh_line_values.lvv_sbr.get_data_at( - opid_next_range.lr_start); - if (opid_range.length() != opid_next_range.length() - || memcmp( - start_opid, next_opid, opid_range.length()) - != 0) + const auto& next_opid_opt + = next_helper.lh_line_values.lvv_opid_value; + if (next_opid_opt + && opid_opt.value() != next_opid_opt.value()) { continue; } @@ -677,14 +710,12 @@ handle_paging_key(int ch) lnav_data.ld_rl_view->set_value(""); tc->set_selection(next_helper.lh_current_line); } else { - const auto opid_str - = start_helper.to_string(opid_range); - lnav_data.ld_rl_view->set_attr_value( lnav::console::user_message::error( attr_line_t( "No more messages found with opid: ") - .append(lnav::roles::symbol(opid_str))) + .append( + lnav::roles::symbol(opid_opt.value()))) .to_attr_line()); alerter::singleton().chime( "no more messages found with opid"); @@ -693,24 +724,6 @@ handle_paging_key(int ch) } break; - case 'p': - if (tc == &lnav_data.ld_views[LNV_LOG]) { - auto* fos = dynamic_cast<field_overlay_source*>( - tc->get_overlay_source()); - auto& top_context = fos->fos_contexts.top(); - top_context.c_show = !top_context.c_show; - tc->set_sync_selection_and_top(top_context.c_show); - tc->set_needs_update(); - } else if (tc == &lnav_data.ld_views[LNV_DB]) { - auto* dos = dynamic_cast<db_overlay_source*>( - tc->get_overlay_source()); - - dos->dos_active = !dos->dos_active; - tc->set_sync_selection_and_top(dos->dos_active); - tc->set_needs_update(); - } - break; - case 't': if (lnav_data.ld_text_source.current_file() == nullptr) { alerter::singleton().chime("No text files loaded"); @@ -723,15 +736,6 @@ handle_paging_key(int ch) } break; - case 'T': - lnav_data.ld_log_source.toggle_time_offset(); - if (lss && lss->is_time_offset_enabled()) { - lnav_data.ld_rl_view->set_alt_value(HELP_MSG_2( - s, S, "to move forward/backward through slow downs")); - } - tc->reload_data(); - break; - case 'I': { auto& hist_tc = lnav_data.ld_views[LNV_HISTOGRAM]; @@ -741,12 +745,13 @@ handle_paging_key(int ch) if (src_view != nullptr) { src_view->time_for_row(tc->get_selection()) | - [](auto log_top) { - lnav_data.ld_hist_source2.row_for_time(log_top) | - [](auto row) { - lnav_data.ld_views[LNV_HISTOGRAM] - .set_selection(row); - }; + [](auto log_top_ri) { + lnav_data.ld_hist_source2.row_for_time( + log_top_ri.ri_time) + | [](auto row) { + lnav_data.ld_views[LNV_HISTOGRAM] + .set_selection(row); + }; }; } } else { @@ -761,10 +766,10 @@ handle_paging_key(int ch) auto curr_top_time_opt = dst_view->time_for_row(top_tc->get_selection()); if (hist_top_time_opt && curr_top_time_opt - && hs.row_for_time(hist_top_time_opt.value()) - != hs.row_for_time(curr_top_time_opt.value())) + && hs.row_for_time(hist_top_time_opt->ri_time) + != hs.row_for_time(curr_top_time_opt->ri_time)) { - dst_view->row_for_time(hist_top_time_opt.value()) | + dst_view->row_for_time(hist_top_time_opt->ri_time) | [top_tc](auto new_top) { top_tc->set_selection(new_top); top_tc->set_needs_update(); @@ -855,28 +860,6 @@ handle_paging_key(int ch) case '\t': case KEY_BTAB: if (tc == &lnav_data.ld_views[LNV_DB]) { - auto& chart = lnav_data.ld_db_row_source.dls_chart; - const auto& state = chart.show_next_ident( - ch == '\t' ? stacked_bar_chart_base::direction::forward - : stacked_bar_chart_base::direction::backward); - - state.match( - [&](stacked_bar_chart_base::show_none) { - lnav_data.ld_rl_view->set_value("Graphing no values"); - }, - [&](stacked_bar_chart_base::show_all) { - lnav_data.ld_rl_view->set_value("Graphing all values"); - }, - [&](stacked_bar_chart_base::show_one) { - std::string colname; - - chart.get_ident_to_show(colname); - lnav_data.ld_rl_view->set_value( - "Graphing column " ANSI_BOLD_START + colname - + ANSI_NORM); - }); - - tc->reload_data(); } else if (tc == &lnav_data.ld_views[LNV_SPECTRO]) { lnav_data.ld_mode = ln_mode_t::SPECTRO_DETAILS; } else if (tc_tss != nullptr && tc_tss->tss_supports_filtering) { @@ -909,15 +892,6 @@ handle_paging_key(int ch) } break; - case 'x': - if (tc->toggle_hide_fields()) { - lnav_data.ld_rl_view->set_value("Showing hidden fields"); - } else { - lnav_data.ld_rl_view->set_value("Hiding hidden fields"); - } - tc->set_needs_update(); - break; - case 'r': case 'R': if (lss != nullptr) { @@ -963,20 +937,13 @@ handle_paging_key(int ch) done = true; } } while (!done); - tc->set_top(vl); + tc->set_selection(vl); lnav_data.ld_rl_view->set_value(" " + rt.to_string()); } } break; - case KEY_CTRL_W: - execute_command(ec, - lnav_data.ld_views[LNV_LOG].get_word_wrap() - ? "disable-word-wrap" - : "enable-word-wrap"); - break; - - case KEY_CTRL_P: + case KEY_CTRL('p'): lnav_data.ld_preview_hidden = !lnav_data.ld_preview_hidden; break; |