Skip to content

Commit 410bcbc

Browse files
committed
[keymap] F5 to reload the view
Related to #1675 and #1524
1 parent ec92ef1 commit 410bcbc

18 files changed

Lines changed: 248 additions & 98 deletions

NEWS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
## lnav v0.14.1
33

44
Features:
5+
* Added the `:reload-view` command, bound to `F5`, that
6+
re-runs the operation that populated the current view.
7+
In the DB view, this re-executes the last SQL query; in
8+
the TIMELINE view, it rebuilds the index. Views that
9+
don't have a meaningful reload report an error.
510
* The DB view now shows a status bar above the bottom
611
status bar with the SQL query that populated the view,
712
the relative time when it was run, and how long it took.

docs/source/hotkeys.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ Display
313313
- Close the current text file or log file.
314314
* - :kbd:`F2`
315315
- Toggle mouse support.
316+
* - :kbd:`F5`
317+
- Reload the current view. Re-runs the SQL query for the DB view
318+
or rebuilds the index for the TIMELINE view.
316319

317320
Session
318321
-------

docs/source/ui.rst

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,8 +430,9 @@ PRQL [#]_ statement.
430430
Press :kbd:`v` to switch to the database result view.
431431

432432
A status bar above the bottom status bar shows the query that populated
433-
the view, how long ago it ran, and how long it took. Clicking
434-
the reload icon (↻) at the left of the bar re-runs the query.
433+
the view, how long ago it ran, and how long it took. Clicking the reload
434+
icon (↻) at the left of the bar — or pressing :kbd:`F5` — re-runs the
435+
query via the :code:`:reload-view` command.
435436

436437
If the query reads from log-backed tables (:code:`all_logs`,
437438
per-format tables like :code:`syslog_log`, :code:`all_opids`, etc.),
@@ -484,6 +485,10 @@ The timeline view [#]_ visualizes operations, log files, threads, tags, and
484485
partitions over time. The items are ordered top-to-bottom by their start time.
485486
So, scrolling down will move forward in time.
486487

488+
The timeline index is not refreshed automatically as new log data arrives.
489+
Press :kbd:`F5` (or run :code:`:reload-view`) to rebuild the index with the
490+
latest data.
491+
487492
An operation is identified by an ID that can come from multiple sources:
488493

489494
* If the ID is in the log message, the log format can set the

src/command_executor.cc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ bind_sql_parameters(exec_context& ec, sqlite3_stmt* stmt)
211211
std::map<std::string, scoped_value_t> retval;
212212
auto param_count = sqlite3_bind_parameter_count(stmt);
213213
for (int lpc = 0; lpc < param_count; lpc++) {
214-
std::map<std::string, std::string>::iterator ov_iter;
215214
const auto* name = sqlite3_bind_parameter_name(stmt, lpc + 1);
216215
if (name == nullptr) {
217216
auto um
@@ -479,6 +478,17 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg)
479478
if (!ec.ec_label_source_stack.empty()) {
480479
auto& dls = *ec.ec_label_source_stack.back();
481480
dls.dls_user_query = sql;
481+
if (!ec.ec_source.empty()) {
482+
dls.dls_user_query_src_loc
483+
= ec.ec_source.back().s_location;
484+
} else {
485+
dls.dls_user_query_src_loc = std::nullopt;
486+
}
487+
if (!ec.ec_local_vars.empty()) {
488+
dls.dls_user_query_vars = ec.ec_local_vars.top();
489+
} else {
490+
dls.dls_user_query_vars.clear();
491+
}
482492
dls.dls_query_start = std::chrono::system_clock::now();
483493
auto* vtab_mgr = injector::get<log_vtab_manager*>();
484494
dls.dls_query_touches_log_data

src/db_status_source.cc

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@
3131

3232
#include "base/attr_line.hh"
3333
#include "base/humanize.time.hh"
34+
#include "base/injector.hh"
3435
#include "base/intern_string.hh"
3536
#include "base/string_attr_type.hh"
3637
#include "base/time_util.hh"
3738
#include "command_executor.hh"
3839
#include "db_sub_source.hh"
3940
#include "fmt/format.h"
40-
#include "lnav.hh"
41+
#include "logfile_sub_source.hh"
4142
#include "readline_highlighters.hh"
42-
#include "sql.formatter.hh"
4343

4444
using namespace lnav::roles::literals;
4545

@@ -53,22 +53,6 @@ db_status_source::db_status_source()
5353
role_t::VCR_STATUS_STITCH_TITLE_TO_NORMAL,
5454
role_t::VCR_STATUS_STITCH_NORMAL_TO_TITLE);
5555
this->dss_fields[DSF_RELOAD].set_width(3);
56-
this->dss_fields[DSF_RELOAD].on_click = [](status_field&) {
57-
auto query = lnav_data.ld_db_row_source.dls_user_query;
58-
if (query.empty()) {
59-
return;
60-
}
61-
std::string alt_msg;
62-
auto& ec = lnav_data.ld_exec_context;
63-
auto src_guard = ec.enter_source(intern_string::lookup("db-reload"),
64-
1,
65-
fmt::format(FMT_STRING(";{}"), query));
66-
auto result = execute_sql(ec, query, alt_msg);
67-
if (result.isErr()) {
68-
auto um = result.unwrapErr();
69-
ec.ec_msg_callback_stack.back()(um);
70-
}
71-
};
7256
this->dss_fields[DSF_QUERY].set_share(3);
7357
this->dss_fields[DSF_TIMING].right_justify(true);
7458
this->dss_fields[DSF_TIMING].set_width(80);
@@ -77,7 +61,8 @@ db_status_source::db_status_source()
7761
bool
7862
db_status_source::update_from_db_source()
7963
{
80-
const auto& dls = lnav_data.ld_db_row_source;
64+
static const auto& dls = injector::get<db_label_source&>();
65+
static auto& lss = injector::get<logfile_sub_source&>();
8166
auto changed = false;
8267

8368
if (dls.dls_user_query.empty()) {
@@ -111,11 +96,9 @@ db_status_source::update_from_db_source()
11196
.to_string();
11297
timing_al.append("ran ").append(lnav::roles::time_ago(ago));
11398
if (dls.dls_query_touches_log_data) {
114-
auto& lss = lnav_data.ld_log_source;
11599
bool is_stale
116100
= lss.lss_index_generation != dls.dls_log_gen_at_query
117-
|| lss.text_line_count()
118-
!= dls.dls_log_line_count_at_query;
101+
|| lss.text_line_count() != dls.dls_log_line_count_at_query;
119102
timing_al.append(" on ").append(
120103
is_stale ? lnav::roles::warning("old log data")
121104
: lnav::roles::ok("current log data"));

src/db_sub_source.cc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,18 @@
3434

3535
#include "base/ansi_scrubber.hh"
3636
#include "base/date_time_scanner.hh"
37+
#include "base/func_util.hh"
3738
#include "base/humanize.hh"
3839
#include "base/itertools.enumerate.hh"
3940
#include "base/itertools.hh"
4041
#include "base/map_util.hh"
4142
#include "base/math_util.hh"
4243
#include "base/time_util.hh"
4344
#include "base/types.hh"
45+
#include "command_executor.hh"
4446
#include "config.h"
4547
#include "hist_source_T.hh"
48+
#include "lnav_util.hh"
4649
#include "log_level.hh"
4750
#include "scn/scan.h"
4851
#include "yajlpp/json_ptr.hh"
@@ -651,6 +654,8 @@ db_label_source::clear()
651654
{
652655
this->dls_generation += 1;
653656
this->dls_user_query.clear();
657+
this->dls_user_query_src_loc = std::nullopt;
658+
this->dls_user_query_vars.clear();
654659
this->dls_query_start = std::nullopt;
655660
this->dls_query_end = std::nullopt;
656661
this->dls_query_touches_log_data = false;
@@ -837,6 +842,30 @@ db_label_source::text_row_details(const textview_curses& tc)
837842
return std::nullopt;
838843
}
839844

845+
Result<std::string, lnav::console::user_message>
846+
db_label_source::text_reload_data(exec_context& ec)
847+
{
848+
if (this->dls_user_query.empty()) {
849+
return ec.make_error("no previous query to re-run");
850+
}
851+
852+
auto prev_query = this->dls_user_query;
853+
auto prev_loc = this->dls_user_query_src_loc.value_or(INTERNAL_SRC_LOC);
854+
auto prev_vars = this->dls_user_query_vars;
855+
std::string alt_msg;
856+
857+
auto src_guard = ec.enter_source(
858+
prev_loc, fmt::format(FMT_STRING(";{}"), prev_query));
859+
auto db_guard = ec.enter_db_source(this);
860+
auto cb_guard = ec.push_callback(sql_callback);
861+
862+
ec.ec_local_vars.emplace(std::move(prev_vars));
863+
auto vars_guard
864+
= finally([&ec]() { ec.ec_local_vars.pop(); });
865+
866+
return execute_sql(ec, prev_query, alt_msg);
867+
}
868+
840869
std::optional<std::string>
841870
db_label_source::text_view_details() const
842871
{

src/db_sub_source.hh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
#include "ArenaAlloc/arenaalloc.h"
4343
#include "base/cell_container.hh"
44+
#include "base/file_range.hh"
4445
#include "base/lnav.resolver.hh"
4546
#include "digestible/digestible.h"
4647
#include "hist_source.hh"
@@ -117,6 +118,9 @@ public:
117118

118119
std::optional<std::string> text_view_details() const override;
119120

121+
Result<std::string, lnav::console::user_message> text_reload_data(
122+
exec_context& ec) override;
123+
120124
std::string get_cell_as_string(vis_line_t row, size_t col);
121125
std::optional<int64_t> get_cell_as_int64(vis_line_t row, size_t col) const;
122126
std::optional<double> get_cell_as_double(vis_line_t row, size_t col) const;
@@ -175,6 +179,8 @@ public:
175179

176180
uint32_t dls_generation{0};
177181
std::string dls_user_query;
182+
std::optional<source_location> dls_user_query_src_loc;
183+
std::map<std::string, scoped_value_t> dls_user_query_vars;
178184
std::optional<std::chrono::system_clock::time_point> dls_query_start;
179185
std::optional<std::chrono::system_clock::time_point> dls_query_end;
180186
bool dls_query_touches_log_data{false};

src/internals/cmd-ref.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,19 @@
14031403
----
14041404

14051405

1406+
.. _reload_view:
1407+
1408+
:reload-view
1409+
^^^^^^^^^^^^
1410+
1411+
Re-run the operation that populated the current view
1412+
1413+
**See Also**
1414+
1415+
1416+
----
1417+
1418+
14061419
.. _reset_config:
14071420

14081421
:reset-config *option*

src/keymaps/default-keymap.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
"f1": {
2424
"command": ":help"
2525
},
26+
"f5": {
27+
"command": ":reload-view"
28+
},
2629
"f7": {
2730
"command": "|lnav-moveto-breakpoint prev"
2831
},

src/lnav.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ static auto bound_lnav_flags
239239
static auto bound_lnav_exec_context
240240
= injector::bind<exec_context>::to_instance(&lnav_data.ld_exec_context);
241241

242+
static auto bound_db_row_source
243+
= injector::bind<db_label_source>::to_instance(&lnav_data.ld_db_row_source);
244+
242245
static auto bound_log_source
243246
= injector::bind<logfile_sub_source>::to_instance(&lnav_data.ld_log_source);
244247

@@ -1766,6 +1769,17 @@ VALUES ('org.lnav.mouse-support', -1, DATETIME('now', '+1 minute'),
17661769

17671770
execute_command(lnav_data.ld_exec_context, cmd);
17681771
};
1772+
lnav_data.ld_db_status_source
1773+
.statusview_value_for_field(db_status_source::DSF_RELOAD)
1774+
.on_click = [](status_field&) {
1775+
auto& ec = lnav_data.ld_exec_context;
1776+
auto prov_guard = ec.with_provenance(exec_context::mouse_input{});
1777+
auto res = ec.execute(INTERNAL_SRC_LOC, ":reload-view");
1778+
if (res.isErr()) {
1779+
auto um = res.unwrapErr();
1780+
ec.ec_msg_callback_stack.back()(um);
1781+
}
1782+
};
17691783

17701784
lnav_data.ld_status[LNS_TOP].set_title("top");
17711785
lnav_data.ld_status[LNS_TOP].set_y(0);

0 commit comments

Comments
 (0)