summaryrefslogtreecommitdiffstats
path: root/src/hotkeys.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/hotkeys.cc')
-rw-r--r--src/hotkeys.cc305
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;