From 53b0a606d62ac0ced2ddb3096739f8921ca31bb1 Mon Sep 17 00:00:00 2001 From: Tim Stack Date: Tue, 5 Mar 2024 20:32:20 -0800 Subject: [PATCH] [textview] try to preserve textview location better when reloading --- NEWS.md | 2 + src/db_sub_source.cc | 4 +- src/db_sub_source.hh | 2 +- src/gantt_source.cc | 12 +++-- src/gantt_source.hh | 2 +- src/hist_source.cc | 4 +- src/hist_source.hh | 2 +- src/hotkeys.cc | 40 ++++++++-------- src/lnav_commands.cc | 14 +++--- src/logfile_sub_source.cc | 28 +++++++++++ src/logfile_sub_source.hh | 10 +++- src/spectro_impls.cc | 2 +- src/spectro_source.cc | 14 +++--- src/spectro_source.hh | 4 +- src/state-extension-functions.cc | 6 +-- src/textfile_sub_source.cc | 46 +++++++++++++++---- src/textfile_sub_source.hh | 3 ++ src/textview_curses.cc | 40 +++++++--------- src/textview_curses.hh | 28 +++++++---- src/views_vtab.cc | 18 ++++---- test/expected/expected.am | 2 + ...6c7262f977201af36b0e69ba1a2aba130bbb06.err | 0 ...6c7262f977201af36b0e69ba1a2aba130bbb06.out | 4 ++ test/test_text_file.sh | 5 ++ test/textfile_plain.0 | 9 ++++ 25 files changed, 198 insertions(+), 103 deletions(-) create mode 100644 test/expected/test_text_file.sh_786c7262f977201af36b0e69ba1a2aba130bbb06.err create mode 100644 test/expected/test_text_file.sh_786c7262f977201af36b0e69ba1a2aba130bbb06.out create mode 100644 test/textfile_plain.0 diff --git a/NEWS.md b/NEWS.md index e5bd3d31..5b22bdfa 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,6 +12,8 @@ Interface changes: example, after typing in `:filter-in` the current search term for the view will be suggested (if one is active). +* The focused line should be preserved more reliably in + the LOG/TEXT views. ## lnav v0.12.0 diff --git a/src/db_sub_source.cc b/src/db_sub_source.cc index 4ef9c33a..45cc271d 100644 --- a/src/db_sub_source.cc +++ b/src/db_sub_source.cc @@ -300,14 +300,14 @@ db_label_source::row_for_time(struct timeval time_bucket) return nonstd::nullopt; } -nonstd::optional +nonstd::optional db_label_source::time_for_row(vis_line_t row) { if ((row < 0_vl) || (((size_t) row) >= this->dls_time_column.size())) { return nonstd::nullopt; } - return this->dls_time_column[row]; + return row_info{this->dls_time_column[row], row}; } void diff --git a/src/db_sub_source.hh b/src/db_sub_source.hh index 69356bf2..4060a9d7 100644 --- a/src/db_sub_source.hh +++ b/src/db_sub_source.hh @@ -89,7 +89,7 @@ public: nonstd::optional row_for_time( struct timeval time_bucket) override; - nonstd::optional time_for_row(vis_line_t row) override; + nonstd::optional time_for_row(vis_line_t row) override; struct header_meta { explicit header_meta(std::string name) : hm_name(std::move(name)) {} diff --git a/src/gantt_source.cc b/src/gantt_source.cc index 628a9eb0..7d9f81df 100644 --- a/src/gantt_source.cc +++ b/src/gantt_source.cc @@ -778,7 +778,7 @@ gantt_source::row_for_time(struct timeval time_bucket) return vis_line_t(std::distance(this->gs_time_order.begin(), closest_iter)); } -nonstd::optional +nonstd::optional gantt_source::time_for_row(vis_line_t row) { if (row >= this->gs_time_order.size()) { @@ -791,11 +791,17 @@ gantt_source::time_for_row(vis_line_t row) auto ov_sel = this->tss_view->get_overlay_selection(); if (ov_sel && ov_sel.value() < otr.otr_sub_ops.size()) { - return otr.otr_sub_ops[ov_sel.value()].ostr_range.tr_begin; + return row_info{ + otr.otr_sub_ops[ov_sel.value()].ostr_range.tr_begin, + row, + }; } } - return otr.otr_range.tr_begin; + return row_info{ + otr.otr_range.tr_begin, + row, + }; } size_t diff --git a/src/gantt_source.hh b/src/gantt_source.hh index 4111f3c3..f3a35246 100644 --- a/src/gantt_source.hh +++ b/src/gantt_source.hh @@ -73,7 +73,7 @@ public: nonstd::optional row_for_time( struct timeval time_bucket) override; - nonstd::optional time_for_row(vis_line_t row) override; + nonstd::optional time_for_row(vis_line_t row) override; void rebuild_indexes(); diff --git a/src/hist_source.cc b/src/hist_source.cc index cf455be4..f6477c42 100644 --- a/src/hist_source.cc +++ b/src/hist_source.cc @@ -166,7 +166,7 @@ hist_source2::end_of_row() } } -nonstd::optional +nonstd::optional hist_source2::time_for_row(vis_line_t row) { if (row < 0 || row > this->hs_line_count) { @@ -175,7 +175,7 @@ hist_source2::time_for_row(vis_line_t row) bucket_t& bucket = this->find_bucket(row); - return timeval{bucket.b_time, 0}; + return row_info{timeval{bucket.b_time, 0}, row}; } hist_source2::bucket_t& diff --git a/src/hist_source.hh b/src/hist_source.hh index 958236e6..c700b0e0 100644 --- a/src/hist_source.hh +++ b/src/hist_source.hh @@ -376,7 +376,7 @@ public: return 0; } - nonstd::optional time_for_row(vis_line_t row) override; + nonstd::optional time_for_row(vis_line_t row) override; nonstd::optional row_for_time( struct timeval tv_bucket) override; diff --git a/src/hotkeys.cc b/src/hotkeys.cc index acbda862..ab19964f 100644 --- a/src/hotkeys.cc +++ b/src/hotkeys.cc @@ -253,8 +253,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); }; }; } @@ -578,9 +578,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); }; }; } @@ -589,8 +589,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; @@ -607,9 +608,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; @@ -625,9 +626,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); }; }; @@ -729,12 +730,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 { @@ -749,10 +751,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(); diff --git a/src/lnav_commands.cc b/src/lnav_commands.cc index e208cf7e..af6b7947 100644 --- a/src/lnav_commands.cc +++ b/src/lnav_commands.cc @@ -724,7 +724,7 @@ com_goto(exec_context& ec, std::string cmdline, std::vector& args) auto top_time_opt = ttt->time_for_row(tc->get_selection()); if (top_time_opt) { - auto top_time_tv = top_time_opt.value(); + auto top_time_tv = top_time_opt.value().ri_time; struct tm top_tm; localtime_r(&top_time_tv.tv_sec, &top_tm); @@ -745,7 +745,7 @@ com_goto(exec_context& ec, std::string cmdline, std::vector& args) if (!tv_opt) { return ec.make_error("cannot get time for the top row"); } - tv = tv_opt.value(); + tv = tv_opt.value().ri_time; vis_line_t vl = tc->get_selection(), new_vl; bool done = false; @@ -4286,7 +4286,7 @@ com_zoom_to(exec_context& ec, auto old_time_opt = lnav_data.ld_hist_source2.time_for_row( lnav_data.ld_views[LNV_HISTOGRAM].get_top()); if (old_time_opt) { - old_time = old_time_opt.value(); + old_time = old_time_opt.value().ri_time; rebuild_hist(); lnav_data.ld_hist_source2.row_for_time(old_time) | [](auto new_top) { @@ -4307,7 +4307,7 @@ com_zoom_to(exec_context& ec, spectro_view.reload_data(); if (old_time_opt) { lnav_data.ld_spectro_source->row_for_time( - old_time_opt.value()) + old_time_opt.value().ri_time) | [](auto new_top) { lnav_data.ld_views[LNV_SPECTRO].set_selection( new_top); @@ -4616,9 +4616,9 @@ com_hide_line(exec_context& ec, struct exttm tm; auto vl = tc->get_selection(); - auto log_tv = ttt->time_for_row(vl); - if (log_tv) { - tm = exttm::from_tv(log_tv.value()); + auto log_vl_ri = ttt->time_for_row(vl); + if (log_vl_ri) { + tm = exttm::from_tv(log_vl_ri.value().ri_time); tv_opt = parse_res.unwrap().adjust(tm).to_timeval(); } } diff --git a/src/logfile_sub_source.cc b/src/logfile_sub_source.cc index 40ba78c5..c30997eb 100644 --- a/src/logfile_sub_source.cc +++ b/src/logfile_sub_source.cc @@ -2778,3 +2778,31 @@ logfile_sub_source::get_filtered_count_for(size_t filter_index) const return retval; } + +nonstd::optional +logfile_sub_source::row_for(const row_info& ri) +{ + auto lb = std::lower_bound(this->lss_filtered_index.begin(), + this->lss_filtered_index.end(), + ri.ri_time, + filtered_logline_cmp(*this)); + if (lb != this->lss_filtered_index.end()) { + auto first_lb = lb; + while (true) { + auto cl = this->lss_index[*lb]; + if (content_line_t(ri.ri_id) == cl) { + first_lb = lb; + break; + } + auto ll = this->find_line(cl); + if (ll->get_timeval() != ri.ri_time) { + break; + } + ++lb; + } + + return vis_line_t(first_lb - this->lss_filtered_index.begin()); + } + + return nonstd::nullopt; +} diff --git a/src/logfile_sub_source.hh b/src/logfile_sub_source.hh index 69ea265f..11ac85be 100644 --- a/src/logfile_sub_source.hh +++ b/src/logfile_sub_source.hh @@ -477,14 +477,20 @@ public: nonstd::optional find_from_content(content_line_t cl); - nonstd::optional time_for_row(vis_line_t row) + nonstd::optional time_for_row(vis_line_t row) { if (row >= 0_vl && row < (ssize_t) this->text_line_count()) { - return this->find_line(this->at(row))->get_timeval(); + auto cl = this->at(row); + return row_info{ + this->find_line(cl)->get_timeval(), + (int64_t) cl, + }; } return nonstd::nullopt; } + nonstd::optional row_for(const row_info& ri); + nonstd::optional row_for_time(struct timeval time_bucket) { return this->find_from_time(time_bucket); diff --git a/src/spectro_impls.cc b/src/spectro_impls.cc index 620ee879..d5513ed5 100644 --- a/src/spectro_impls.cc +++ b/src/spectro_impls.cc @@ -82,7 +82,7 @@ public: return this->fss_time_delegate->row_for_time(time_bucket); } - nonstd::optional time_for_row(vis_line_t row) override + nonstd::optional time_for_row(vis_line_t row) override { return this->fss_lines | lnav::itertools::nth(row) | lnav::itertools::flat_map([this](const auto row) { diff --git a/src/spectro_source.cc b/src/spectro_source.cc index 7220dba9..d892e7a9 100644 --- a/src/spectro_source.cc +++ b/src/spectro_source.cc @@ -82,7 +82,7 @@ spectrogram_source::list_input_handle_key(listview_curses& lv, int ch) return true; } auto begin_time = begin_time_opt.value(); - struct timeval end_time = begin_time; + struct timeval end_time = begin_time.ri_time; end_time.tv_sec += this->ss_granularity; double range_min, range_max, column_size; @@ -93,7 +93,7 @@ spectrogram_source::list_input_handle_key(listview_curses& lv, int ch) + this->ss_cursor_column.value_or(0) * column_size; range_max = range_min + column_size; this->ss_value_source->spectro_mark((textview_curses&) lv, - begin_time.tv_sec, + begin_time.ri_time.tv_sec, end_time.tv_sec, range_min, range_max); @@ -291,7 +291,7 @@ spectrogram_source::text_line_width(textview_curses& tc) return width; } -nonstd::optional +nonstd::optional spectrogram_source::time_for_row(vis_line_t row) { if (this->ss_details_source != nullptr) { @@ -306,7 +306,7 @@ spectrogram_source::time_for_row(vis_line_t row) return this->time_for_row_int(row); } -nonstd::optional +nonstd::optional spectrogram_source::time_for_row_int(vis_line_t row) { struct timeval retval { @@ -318,7 +318,7 @@ spectrogram_source::time_for_row_int(vis_line_t row) = rounddown(this->ss_cached_bounds.sb_begin_time, this->ss_granularity) + row * this->ss_granularity; - return retval; + return row_info{retval, row}; } nonstd::optional @@ -359,9 +359,9 @@ spectrogram_source::text_value_for_line(textview_curses& tc, value_out.clear(); return; } - auto row_time = row_time_opt.value(); + auto ri = row_time_opt.value(); - gmtime_r(&row_time.tv_sec, &tm); + gmtime_r(&ri.ri_time.tv_sec, &tm); strftime(tm_buffer, sizeof(tm_buffer), " %a %b %d %H:%M:%S", &tm); value_out = tm_buffer; diff --git a/src/spectro_source.hh b/src/spectro_source.hh index aafd17d5..9fd778c9 100644 --- a/src/spectro_source.hh +++ b/src/spectro_source.hh @@ -154,7 +154,7 @@ public: void text_selection_changed(textview_curses& tc) override; - nonstd::optional time_for_row(vis_line_t row) override; + nonstd::optional time_for_row(vis_line_t row) override; nonstd::optional row_for_time( struct timeval time_bucket) override; @@ -170,7 +170,7 @@ public: void cache_bounds(); - nonstd::optional time_for_row_int(vis_line_t row); + nonstd::optional time_for_row_int(vis_line_t row); const spectrogram_row& load_row(const listview_curses& lv, int row); diff --git a/src/state-extension-functions.cc b/src/state-extension-functions.cc index baf99576..119ca861 100644 --- a/src/state-extension-functions.cc +++ b/src/state-extension-functions.cc @@ -84,15 +84,15 @@ sql_log_top_datetime() return nonstd::nullopt; } - auto top_time = lnav_data.ld_log_source.time_for_row( + auto top_ri = lnav_data.ld_log_source.time_for_row( lnav_data.ld_views[LNV_LOG].get_selection()); - if (!top_time) { + if (!top_ri) { return nonstd::nullopt; } char buffer[64]; - sql_strftime(buffer, sizeof(buffer), top_time.value()); + sql_strftime(buffer, sizeof(buffer), top_ri->ri_time); return buffer; } diff --git a/src/textfile_sub_source.cc b/src/textfile_sub_source.cc index f1ee4a95..eafefbbf 100644 --- a/src/textfile_sub_source.cc +++ b/src/textfile_sub_source.cc @@ -429,18 +429,13 @@ textfile_sub_source::push_back(const std::shared_ptr& lf) void textfile_sub_source::text_filters_changed() { - for (auto iter = this->tss_files.begin(); iter != this->tss_files.end();) { - ++iter; - } - for (auto iter = this->tss_hidden_files.begin(); - iter != this->tss_hidden_files.end();) - { - ++iter; + auto lf = this->current_file(); + if (lf == nullptr || lf->get_text_format() == text_format_t::TF_BINARY) { + return; } - std::shared_ptr lf = this->current_file(); - - if (lf == nullptr) { + auto rend_iter = this->tss_rendered_files.find(lf->get_filename()); + if (rend_iter != this->tss_rendered_files.end()) { return; } @@ -462,6 +457,37 @@ textfile_sub_source::text_filters_changed() } this->tss_view->redo_search(); + + auto iter = std::lower_bound(lfo->lfo_filter_state.tfs_index.begin(), + lfo->lfo_filter_state.tfs_index.end(), + this->tss_content_line); + auto vl = vis_line_t( + std::distance(lfo->lfo_filter_state.tfs_index.begin(), iter)); + this->tss_view->set_selection(vl); +} + +void +textfile_sub_source::scroll_invoked(textview_curses* tc) +{ + auto lf = this->current_file(); + if (lf == nullptr || lf->get_text_format() == text_format_t::TF_BINARY) { + return; + } + + auto rend_iter = this->tss_rendered_files.find(lf->get_filename()); + if (rend_iter != this->tss_rendered_files.end()) { + return; + } + + auto line = tc->get_selection(); + auto* lfo = dynamic_cast(lf->get_logline_observer()); + if (lfo == nullptr || line < 0_vl + || line >= lfo->lfo_filter_state.tfs_index.size()) + { + return; + } + + this->tss_content_line = lfo->lfo_filter_state.tfs_index[line]; } int diff --git a/src/textfile_sub_source.hh b/src/textfile_sub_source.hh index feb12b84..138082dc 100644 --- a/src/textfile_sub_source.hh +++ b/src/textfile_sub_source.hh @@ -166,6 +166,8 @@ public: logline* text_accel_get_line(vis_line_t vl) override; + void scroll_invoked(textview_curses* tc) override; + private: void detach_observer(std::shared_ptr lf) { @@ -193,6 +195,7 @@ private: size_t tss_line_indent_size{0}; bool tss_completed_last_scan{true}; attr_line_t tss_hex_line; + int64_t tss_content_line{0}; }; class textfile_header_overlay : public list_overlay_source { diff --git a/src/textview_curses.cc b/src/textview_curses.cc index 12bbf430..c59f8fe7 100644 --- a/src/textview_curses.cc +++ b/src/textview_curses.cc @@ -822,11 +822,21 @@ textview_curses::grep_value_for_line(vis_line_t line, std::string& value_out) } void -text_time_translator::scroll_invoked(textview_curses* tc) +text_sub_source::scroll_invoked(textview_curses* tc) { - if (tc->get_inner_height() > 0) { + auto* ttt = dynamic_cast(this); + + if (ttt != nullptr) { + ttt->ttt_scroll_invoked(tc); + } +} + +void +text_time_translator::ttt_scroll_invoked(textview_curses* tc) +{ + if (tc->get_inner_height() > 0 && tc->get_selection() >= 0_vl) { this->time_for_row(tc->get_selection()) | - [this](auto new_top_time) { this->ttt_top_time = new_top_time; }; + [this](auto new_top_ri) { this->ttt_top_row_info = new_top_ri; }; } } @@ -834,29 +844,13 @@ void text_time_translator::data_reloaded(textview_curses* tc) { if (tc->get_inner_height() == 0) { + this->ttt_top_row_info = nonstd::nullopt; return; } - if (tc->get_selection() < 0_vl - || tc->get_selection() > tc->get_inner_height()) - { - if (this->ttt_top_time.tv_sec != 0) { - this->row_for_time(this->ttt_top_time) | - [tc](auto new_top) { tc->set_selection(new_top); }; - } - return; + if (this->ttt_top_row_info) { + this->row_for(this->ttt_top_row_info.value()) | + [tc](auto new_top) { tc->set_selection(new_top); }; } - this->time_for_row(tc->get_selection()) | [this, tc](auto top_time) { - if (top_time != this->ttt_top_time) { - if (this->ttt_top_time.tv_sec != 0) { - this->row_for_time(this->ttt_top_time) | - [tc](auto new_top) { tc->set_selection(new_top); }; - } - this->time_for_row(tc->get_selection()) | - [this](auto new_top_time) { - this->ttt_top_time = new_top_time; - }; - } - }; } template class bookmark_vector; diff --git a/src/textview_curses.hh b/src/textview_curses.hh index 30d2bda1..7c897721 100644 --- a/src/textview_curses.hh +++ b/src/textview_curses.hh @@ -250,22 +250,32 @@ private: class text_time_translator { public: + struct row_info { + struct timeval ri_time { + 0, 0 + }; + int64_t ri_id{-1}; + }; + virtual ~text_time_translator() = default; virtual nonstd::optional row_for_time( struct timeval time_bucket) = 0; - virtual nonstd::optional time_for_row(vis_line_t row) = 0; + virtual nonstd::optional row_for(const row_info& ri) + { + return this->row_for_time(ri.ri_time); + } - void scroll_invoked(textview_curses* tc); + virtual nonstd::optional time_for_row(vis_line_t row) = 0; void data_reloaded(textview_curses* tc); + void ttt_scroll_invoked(textview_curses* tc); + protected: - struct timeval ttt_top_time { - 0, 0 - }; + nonstd::optional ttt_top_row_info; }; class text_accel_source { @@ -496,6 +506,8 @@ public: virtual void quiesce() {} + virtual void scroll_invoked(textview_curses* tc); + bool tss_supports_filtering{false}; bool tss_apply_filters{true}; @@ -777,11 +789,7 @@ public: void invoke_scroll() { if (this->tc_sub_source != nullptr) { - auto ttt = dynamic_cast(this->tc_sub_source); - - if (ttt != nullptr) { - ttt->scroll_invoked(this); - } + this->tc_sub_source->scroll_invoked(this); } listview_curses::invoke_scroll(); diff --git a/src/views_vtab.cc b/src/views_vtab.cc index 7f5e7f9c..e069c2ac 100644 --- a/src/views_vtab.cc +++ b/src/views_vtab.cc @@ -300,15 +300,15 @@ CREATE TABLE lnav_views ( = dynamic_cast(tc.get_sub_source()); if (time_source != nullptr && tc.get_inner_height() > 0) { - auto top_time_opt + auto top_ri_opt = time_source->time_for_row(tc.get_selection()); - if (top_time_opt) { + if (top_ri_opt) { char timestamp[64]; sql_strftime(timestamp, sizeof(timestamp), - top_time_opt.value(), + top_ri_opt->ri_time, ' '); sqlite3_result_text( ctx, timestamp, -1, SQLITE_TRANSIENT); @@ -373,15 +373,15 @@ CREATE TABLE lnav_views ( top_line_meta tlm; if (time_source != nullptr) { - auto top_time_opt + auto top_ri_opt = time_source->time_for_row(tc.get_selection()); - if (top_time_opt) { + if (top_ri_opt) { char timestamp[64]; sql_strftime(timestamp, sizeof(timestamp), - top_time_opt.value(), + top_ri_opt->ri_time, ' '); tlm.tlm_time = timestamp; } @@ -530,11 +530,11 @@ CREATE TABLE lnav_views ( tc.get_title().c_str(), top_time); if (dts.convert_to_timeval(top_time, -1, nullptr, tv)) { - auto last_time_opt + auto last_ri_opt = time_source->time_for_row(tc.get_selection()); - if (last_time_opt) { - auto last_time = last_time_opt.value(); + if (last_ri_opt) { + auto last_time = last_ri_opt->ri_time; if (tv != last_time) { time_source->row_for_time(tv) | [&tc, &selection](auto row) { diff --git a/test/expected/expected.am b/test/expected/expected.am index 5f5da76c..9111efca 100644 --- a/test/expected/expected.am +++ b/test/expected/expected.am @@ -1228,6 +1228,8 @@ EXPECTED_FILES = \ $(srcdir)/%reldir%/test_text_file.sh_6a24078983cf1b7a80b6fb65d5186cd125498136.out \ $(srcdir)/%reldir%/test_text_file.sh_73f69c883f60761bff9f8874f61d21a189e92912.err \ $(srcdir)/%reldir%/test_text_file.sh_73f69c883f60761bff9f8874f61d21a189e92912.out \ + $(srcdir)/%reldir%/test_text_file.sh_786c7262f977201af36b0e69ba1a2aba130bbb06.err \ + $(srcdir)/%reldir%/test_text_file.sh_786c7262f977201af36b0e69ba1a2aba130bbb06.out \ $(srcdir)/%reldir%/test_text_file.sh_78f252288519c8f767bb2759ea32959dab2ebc46.err \ $(srcdir)/%reldir%/test_text_file.sh_78f252288519c8f767bb2759ea32959dab2ebc46.out \ $(srcdir)/%reldir%/test_text_file.sh_7b00f32a3fff7fc2d78a87045ae842e58be88480.err \ diff --git a/test/expected/test_text_file.sh_786c7262f977201af36b0e69ba1a2aba130bbb06.err b/test/expected/test_text_file.sh_786c7262f977201af36b0e69ba1a2aba130bbb06.err new file mode 100644 index 00000000..e69de29b diff --git a/test/expected/test_text_file.sh_786c7262f977201af36b0e69ba1a2aba130bbb06.out b/test/expected/test_text_file.sh_786c7262f977201af36b0e69ba1a2aba130bbb06.out new file mode 100644 index 00000000..efb5ebdb --- /dev/null +++ b/test/expected/test_text_file.sh_786c7262f977201af36b0e69ba1a2aba130bbb06.out @@ -0,0 +1,4 @@ +Duis aute irure dolor in reprehenderit in voluptate velit +esse cillum dolore eu fugiat nulla pariatur. Excepteur +sint occaecat cupidatat non proident, sunt in culpa qui +officia deserunt mollit anim id est laborum. diff --git a/test/test_text_file.sh b/test/test_text_file.sh index 4d701d19..286b4576 100644 --- a/test/test_text_file.sh +++ b/test/test_text_file.sh @@ -4,6 +4,11 @@ export TZ=UTC export YES_COLOR=1 unset XDG_CONFIG_HOME +run_cap_test ${lnav_test} -n \ + -c ':goto 5' \ + -c ':filter-out Lorem|sed' \ + ${test_dir}/textfile_plain.0 + run_cap_test ${lnav_test} -n \ ${top_srcdir}/README.md diff --git a/test/textfile_plain.0 b/test/textfile_plain.0 new file mode 100644 index 00000000..f7ad1efc --- /dev/null +++ b/test/textfile_plain.0 @@ -0,0 +1,9 @@ + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, +sed do eiusmod tempor incididunt ut labore et dolore magna +aliqua. Ut enim ad minim veniam, quis nostrud exercitation +ullamco laboris nisi ut aliquip ex ea commodo consequat. +Duis aute irure dolor in reprehenderit in voluptate velit +esse cillum dolore eu fugiat nulla pariatur. Excepteur +sint occaecat cupidatat non proident, sunt in culpa qui +officia deserunt mollit anim id est laborum.