diff --git a/src/bookmarks.cc b/src/bookmarks.cc index b4bc8e86..fdc1be07 100644 --- a/src/bookmarks.cc +++ b/src/bookmarks.cc @@ -4,11 +4,12 @@ #include "bookmarks.hh" -vis_line_t bookmark_vector::next(vis_line_t start) +template +LineType bookmark_vector::next(LineType start) { - std::vector::iterator ub; + typename bookmark_vector::iterator ub; - vis_line_t retval(-1); + LineType retval(-1); assert(start >= -1); @@ -22,11 +23,12 @@ vis_line_t bookmark_vector::next(vis_line_t start) return retval; } -vis_line_t bookmark_vector::prev(vis_line_t start) +template +LineType bookmark_vector::prev(LineType start) { - std::vector::iterator lb; + typename bookmark_vector::iterator lb; - vis_line_t retval(-1); + LineType retval(-1); assert(start >= 0); @@ -40,3 +42,6 @@ vis_line_t bookmark_vector::prev(vis_line_t start) return retval; } + +template class bookmark_vector; + diff --git a/src/bookmarks.hh b/src/bookmarks.hh index 677babfb..3b0c4f43 100644 --- a/src/bookmarks.hh +++ b/src/bookmarks.hh @@ -21,10 +21,14 @@ * value that may or may not be in the vector, find the next or * previous value that is in the vector. * + * @param LineType The type used to store line numbers. (e.g. + * vis_line_t or content_line_t) + * * @note The vector is expected to be sorted. */ +template class bookmark_vector - : public std::vector { + : public std::vector { public: /** @@ -33,9 +37,9 @@ public: * * @param vl The line to bookmark. */ - iterator insert_once(vis_line_t vl) + typename bookmark_vector::iterator insert_once(LineType vl) { - iterator lb, retval; + typename bookmark_vector::iterator lb, retval; assert(vl >= 0); @@ -58,7 +62,7 @@ public: * the next bookmark is returned. If the 'start' value is not a * bookmark, the next highest value in the vector is returned. */ - vis_line_t next(vis_line_t start); + LineType next(LineType start); /** * @param start The value to start the search for the previous @@ -67,7 +71,7 @@ public: * are no more prior bookmarks. * @see next */ - vis_line_t prev(vis_line_t start); + LineType prev(LineType start); }; /** @@ -79,6 +83,11 @@ class bookmark_type_t { }; /** * Map of bookmark types to bookmark vectors. */ -typedef std::map bookmarks; +template +struct bookmarks { + typedef std::map > type; +}; + +typedef bookmarks::type vis_bookmarks; #endif diff --git a/src/bottom_status_source.hh b/src/bottom_status_source.hh index 64c6d8ed..1a399a01 100644 --- a/src/bottom_status_source.hh +++ b/src/bottom_status_source.hh @@ -115,14 +115,14 @@ public: textview_curses *tc = static_cast(lc); status_field &sfw = this->bss_fields[BSF_WARNINGS]; status_field &sfe = this->bss_fields[BSF_ERRORS]; - bookmarks &bm = tc->get_bookmarks(); + vis_bookmarks &bm = tc->get_bookmarks(); unsigned long width; vis_line_t height; tc->get_dimensions(height, width); if (bm.find(&logfile_sub_source::BM_WARNINGS) != bm.end()) { - bookmark_vector &bv = bm[&logfile_sub_source::BM_WARNINGS]; - bookmark_vector::iterator iter; + bookmark_vector &bv = bm[&logfile_sub_source::BM_WARNINGS]; + bookmark_vector::iterator iter; iter = lower_bound(bv.begin(), bv.end(), tc->get_top() + height); sfw.set_value("%9dW", distance(iter, bv.end())); @@ -132,8 +132,8 @@ public: } if (bm.find(&logfile_sub_source::BM_ERRORS) != bm.end()) { - bookmark_vector &bv = bm[&logfile_sub_source::BM_ERRORS]; - bookmark_vector::iterator iter; + bookmark_vector &bv = bm[&logfile_sub_source::BM_ERRORS]; + bookmark_vector::iterator iter; iter = lower_bound(bv.begin(), bv.end(), tc->get_top() + height); sfe.set_value("%9dE", distance(iter, bv.end())); diff --git a/src/help.txt b/src/help.txt index 40bbb307..59753fb4 100644 --- a/src/help.txt +++ b/src/help.txt @@ -147,6 +147,8 @@ through the file. c Copy the marked text to the X selection buffer. + C Clear all marked lines. + u/U Move forward/backward through any user bookmarks you have added using the 'm' key. diff --git a/src/lnav.cc b/src/lnav.cc index aef95653..4ae343a2 100644 --- a/src/lnav.cc +++ b/src/lnav.cc @@ -710,7 +710,7 @@ static void ensure_view(textview_curses *expected_tc) } } -static void moveto_cluster(vis_line_t (bookmark_vector::*f)(vis_line_t), +static void moveto_cluster(vis_line_t (bookmark_vector::*f)(vis_line_t), bookmark_type_t *bt, vis_line_t top) { @@ -721,7 +721,7 @@ static void moveto_cluster(vis_line_t (bookmark_vector::*f)(vis_line_t), } else { logfile_sub_source &lss = lnav_data.ld_log_source; - bookmarks &bm = tc->get_bookmarks(); + vis_bookmarks &bm = tc->get_bookmarks(); vis_line_t vl(-1), last_top(top); logline::level_t last_level; @@ -779,8 +779,8 @@ static void check_for_clipboard(FILE **pfile, const char *execstr) static void copy_to_xclip(void) { textview_curses *tc = lnav_data.ld_view_stack.top(); - bookmark_vector &bv = tc->get_bookmarks()[&textview_curses::BM_USER]; - bookmark_vector::iterator iter; + bookmark_vector &bv = tc->get_bookmarks()[&textview_curses::BM_USER]; + bookmark_vector::iterator iter; FILE *pfile = NULL; string line; @@ -807,14 +807,15 @@ static void copy_to_xclip(void) static void handle_paging_key(int ch) { textview_curses *tc = lnav_data.ld_view_stack.top(); - - logfile_sub_source &lss = lnav_data.ld_log_source; - bookmarks &bm = tc->get_bookmarks(); + logfile_sub_source *lss = NULL; + vis_bookmarks &bm = tc->get_bookmarks(); if (tc->handle_key(ch)) { return; } + lss = dynamic_cast(tc->get_sub_source()); + /* process the command keystroke */ switch (ch) { case 'q': @@ -835,26 +836,33 @@ static void handle_paging_key(int ch) copy_to_xclip(); break; + case 'C': + if (lss) { + lss->get_user_bookmarks()[&textview_curses::BM_USER].clear(); + tc->reload_data(); + } + break; + case 'e': - moveto_cluster(&bookmark_vector::next, + moveto_cluster(&bookmark_vector::next, &logfile_sub_source::BM_ERRORS, tc->get_top()); break; case 'E': - moveto_cluster(&bookmark_vector::prev, + moveto_cluster(&bookmark_vector::prev, &logfile_sub_source::BM_ERRORS, tc->get_top()); break; case 'w': - moveto_cluster(&bookmark_vector::next, + moveto_cluster(&bookmark_vector::next, &logfile_sub_source::BM_WARNINGS, tc->get_top()); break; case 'W': - moveto_cluster(&bookmark_vector::prev, + moveto_cluster(&bookmark_vector::prev, &logfile_sub_source::BM_WARNINGS, tc->get_top()); break; @@ -995,16 +1003,19 @@ static void handle_paging_key(int ch) break; case 'm': - lnav_data.ld_last_user_mark[tc] = tc->get_top(); - tc->toggle_user_mark(&textview_curses::BM_USER, - lnav_data.ld_last_user_mark[tc]); - tc->reload_data(); + if (lss) { + lnav_data.ld_last_user_mark[tc] = tc->get_top(); + lss->toggle_user_mark(&textview_curses::BM_USER, + vis_line_t(lnav_data.ld_last_user_mark[tc])); + tc->reload_data(); + } break; case 'J': // TODO: if they scroll up, we should start marking again from the top. // We should also scroll down as the continue to mark stuff. If they // move somewhere else in the file, we should also start marking from // the top again. + if (lss) { if (lnav_data.ld_last_user_mark.find(tc) == lnav_data.ld_last_user_mark.end()) { lnav_data.ld_last_user_mark[tc] = tc->get_top(); } @@ -1015,27 +1026,31 @@ static void handle_paging_key(int ch) else { lnav_data.ld_last_user_mark[tc] += 1; } - tc->toggle_user_mark(&textview_curses::BM_USER, - lnav_data.ld_last_user_mark[tc]); + lss->toggle_user_mark(&textview_curses::BM_USER, + vis_line_t(lnav_data.ld_last_user_mark[tc])); tc->reload_data(); +} break; case 'K': // TODO: scroll up with the selection - if (lnav_data.ld_last_user_mark.find(tc) == lnav_data.ld_last_user_mark.end()) { - lnav_data.ld_last_user_mark[tc] = tc->get_top(); - } + if (lss) { + if (lnav_data.ld_last_user_mark.find(tc) == lnav_data.ld_last_user_mark.end()) { + lnav_data.ld_last_user_mark[tc] = tc->get_top(); + } - tc->toggle_user_mark(&textview_curses::BM_USER, - lnav_data.ld_last_user_mark[tc]); - if (lnav_data.ld_last_user_mark[tc] - 1 < 0) { - flash(); - } - else { - lnav_data.ld_last_user_mark[tc] -= 1; + lss->toggle_user_mark(&textview_curses::BM_USER, + vis_line_t(lnav_data.ld_last_user_mark[tc])); + if (lnav_data.ld_last_user_mark[tc] - 1 < 0) { + flash(); + } + else { + lnav_data.ld_last_user_mark[tc] -= 1; + } + tc->reload_data(); } - tc->reload_data(); break; case 'M': + if (lss) { if (lnav_data.ld_last_user_mark.find(tc) == lnav_data.ld_last_user_mark.end()) { flash(); } @@ -1043,10 +1058,11 @@ static void handle_paging_key(int ch) int start_line = min((int)tc->get_top(), lnav_data.ld_last_user_mark[tc] + 1); int end_line = max((int)tc->get_top(), lnav_data.ld_last_user_mark[tc] - 1); - tc->toggle_user_mark(&textview_curses::BM_USER, - start_line, end_line); + lss->toggle_user_mark(&textview_curses::BM_USER, + vis_line_t(start_line), vis_line_t(end_line)); tc->reload_data(); } +} break; case '1': @@ -1055,14 +1071,14 @@ static void handle_paging_key(int ch) case '4': case '5': case '6': - { + if (lss) { int ten_minute = (ch - '0') * 10 * 60; time_t hour = rounddown(lnav_data.ld_top_time + (60 * 60) - ten_minute + 1, 60 * 60); - vis_line_t line = lss.find_from_time(hour + ten_minute); + vis_line_t line = lss->find_from_time(hour + ten_minute); tc->set_top(line); } @@ -1093,19 +1109,19 @@ static void handle_paging_key(int ch) break; case '0': - { + if (lss) { time_t first_time = lnav_data.ld_top_time; int step = 24 * 60 * 60; - vis_line_t line = lss.find_from_time(roundup(first_time, step)); + vis_line_t line = lss->find_from_time(roundup(first_time, step)); tc->set_top(line); } break; case ')': - { + if (lss) { time_t day = rounddown(lnav_data.ld_top_time, 24 * 60 * 60); - vis_line_t line = lss.find_from_time(day); + vis_line_t line = lss->find_from_time(day); --line; tc->set_top(line); @@ -1117,10 +1133,10 @@ static void handle_paging_key(int ch) if (tc->get_top() == 0) { flash(); } - else { + else if (lss) { int step = ch == 'D' ? (24 * 60 * 60) : (60 * 60); time_t top_time = lnav_data.ld_top_time; - vis_line_t line = lss.find_from_time(top_time - step); + vis_line_t line = lss->find_from_time(top_time - step); if (line != 0) { --line; @@ -1131,9 +1147,9 @@ static void handle_paging_key(int ch) case 'd': case 'o': - { + if (lss) { int step = ch == 'd' ? (24 * 60 * 60) : (60 * 60); - vis_line_t line = lss.find_from_time(lnav_data.ld_top_time + step); + vis_line_t line = lss->find_from_time(lnav_data.ld_top_time + step); tc->set_top(line); } @@ -1184,7 +1200,8 @@ static void handle_paging_key(int ch) } else { tc = &lnav_data.ld_views[LNV_LOG]; - tc->set_top(lss.find_from_time(hist_top)); + lss = &lnav_data.ld_log_source; + tc->set_top(lss->find_from_time(hist_top)); tc->set_needs_update(); } } @@ -1258,15 +1275,17 @@ static void handle_paging_key(int ch) break; case 'x': - tc->toggle_user_mark(&BM_EXAMPLE, tc->get_top()); + if (tc == &lnav_data.ld_views[LNV_LOG]) { + lnav_data.ld_log_source.toggle_user_mark(&BM_EXAMPLE, vis_line_t(tc->get_top())); + } break; case '\\': { - bookmarks &bm = tc->get_bookmarks(); + vis_bookmarks &bm = tc->get_bookmarks(); string ex; - for (bookmark_vector::iterator iter = bm[&BM_EXAMPLE].begin(); + for (bookmark_vector::iterator iter = bm[&BM_EXAMPLE].begin(); iter != bm[&BM_EXAMPLE].end(); ++iter) { string line; @@ -1443,8 +1462,8 @@ static string com_save_to(string cmdline, vector &args) } textview_curses *tc = lnav_data.ld_view_stack.top(); - bookmark_vector &bv = tc->get_bookmarks()[&textview_curses::BM_USER]; - bookmark_vector::iterator iter; + bookmark_vector &bv = tc->get_bookmarks()[&textview_curses::BM_USER]; + bookmark_vector::iterator iter; string line; for (iter = bv.begin(); iter != bv.end(); iter++) { diff --git a/src/logfile_sub_source.cc b/src/logfile_sub_source.cc index 46a82e86..13a023ea 100644 --- a/src/logfile_sub_source.cc +++ b/src/logfile_sub_source.cc @@ -408,7 +408,7 @@ bool logfile_sub_source::rebuild_index(observer *obs, bool force) return retval; } -void logfile_sub_source::text_update_marks(bookmarks &bm) +void logfile_sub_source::text_update_marks(vis_bookmarks &bm) { logfile *last_file = NULL; vis_line_t vl; @@ -422,7 +422,7 @@ void logfile_sub_source::text_update_marks(bookmarks &bm) content_line_t cl = this->lss_index[vl]; logfile *lf; - for (user_marks_t::iterator iter = this->lss_user_marks.begin(); + for (bookmarks::type::iterator iter = this->lss_user_marks.begin(); iter != this->lss_user_marks.end(); ++iter) { if (binary_search(iter->second.begin(), iter->second.end(), cl)) { diff --git a/src/logfile_sub_source.hh b/src/logfile_sub_source.hh index 77e55163..0cd287a4 100644 --- a/src/logfile_sub_source.hh +++ b/src/logfile_sub_source.hh @@ -125,7 +125,30 @@ public: }; bool rebuild_index(observer *obs = NULL, bool force = false); - void text_update_marks(bookmarks &bm); + void text_update_marks(vis_bookmarks &bm); + + void toggle_user_mark(bookmark_type_t *bm, + vis_line_t start_line, + vis_line_t end_line = vis_line_t(-1)) + { + if (end_line == -1) + end_line = start_line; + for (vis_line_t curr_line = start_line; curr_line <= end_line; ++curr_line) { + bookmark_vector &bv = this->lss_user_marks[bm]; + bookmark_vector::iterator iter; + + iter = bv.insert_once(this->at(curr_line)); + if (iter == bv.end()) { + } + else { + bv.erase(iter); + } + } + }; + + bookmarks::type &get_user_bookmarks(void) { + return this->lss_user_marks; + }; int get_filtered_count() const { return this->lss_filtered_count; }; @@ -212,10 +235,7 @@ private: std::vector lss_index; - typedef std::map< bookmark_type_t *, - std::vector > user_marks_t; - - user_marks_t lss_user_marks; + bookmarks::type lss_user_marks; logfile *lss_token_file; std::string lss_token_value; diff --git a/src/sequence_sink.hh b/src/sequence_sink.hh index a540015a..b2482898 100644 --- a/src/sequence_sink.hh +++ b/src/sequence_sink.hh @@ -10,7 +10,7 @@ class sequence_sink : public grep_proc_sink { public: - sequence_sink(sequence_matcher &sm, bookmark_vector &bv) : + sequence_sink(sequence_matcher &sm, bookmark_vector &bv) : ss_matcher(sm), ss_bookmarks(bv) { }; @@ -55,7 +55,7 @@ public: private: sequence_matcher &ss_matcher; - bookmark_vector &ss_bookmarks; + bookmark_vector &ss_bookmarks; std::vector ss_line_values; std::map< sequence_matcher::id_t, std::vector > ss_state; }; diff --git a/src/textview_curses.cc b/src/textview_curses.cc index c956d058..d48919b4 100644 --- a/src/textview_curses.cc +++ b/src/textview_curses.cc @@ -190,7 +190,7 @@ void textview_curses::listview_value_for_row(const listview_curses &lv, vis_line_t row, attr_line_t &value_out) { - bookmark_vector &user_marks = this->tc_bookmarks[&BM_USER]; + bookmark_vector &user_marks = this->tc_bookmarks[&BM_USER]; string_attrs_t &sa = value_out.get_attrs(); string &str = value_out.get_string(); highlight_map_t::iterator iter; diff --git a/src/textview_curses.hh b/src/textview_curses.hh index abf50ddb..581cede1 100644 --- a/src/textview_curses.hh +++ b/src/textview_curses.hh @@ -31,9 +31,7 @@ public: string_attrs_t &value_out) { }; - virtual void text_update_marks(bookmarks &bm) { }; - - virtual void text_user_mark(bookmark_type_t *bm, int line, bool added) { }; + virtual void text_update_marks(vis_bookmarks &bm) { }; }; /** @@ -105,29 +103,7 @@ public: textview_curses(); virtual ~textview_curses(); - bookmarks &get_bookmarks(void) { return this->tc_bookmarks; }; - - void toggle_user_mark(bookmark_type_t *bm, - int start_line, - int end_line = -1) - { - if (end_line == -1) - end_line = start_line; - for (int curr_line = start_line; curr_line <= end_line; curr_line++) { - bookmark_vector &bv = this->tc_bookmarks[bm]; - bookmark_vector::iterator iter; - bool added = false; - - iter = bv.insert_once(vis_line_t(curr_line)); - if (iter == bv.end()) { - added = true; - } - else { - bv.erase(iter); - } - this->tc_sub_source->text_user_mark(bm, curr_line, added); - } - }; + vis_bookmarks &get_bookmarks(void) { return this->tc_bookmarks; }; void set_sub_source(text_sub_source *src) { @@ -274,7 +250,7 @@ public: protected: text_sub_source *tc_sub_source; - bookmarks tc_bookmarks; + vis_bookmarks tc_bookmarks; vis_line_t tc_lview_top; int tc_lview_left; diff --git a/src/top_status_source.hh b/src/top_status_source.hh index 5871fe49..fd3c4906 100644 --- a/src/top_status_source.hh +++ b/src/top_status_source.hh @@ -65,14 +65,14 @@ public: textview_curses *tc = dynamic_cast(lc); status_field &sfw = this->tss_fields[TSF_WARNINGS]; status_field &sfe = this->tss_fields[TSF_ERRORS]; - bookmarks &bm = tc->get_bookmarks(); + vis_bookmarks &bm = tc->get_bookmarks(); unsigned long width; vis_line_t height; tc->get_dimensions(height, width); if (bm.find(&logfile_sub_source::BM_WARNINGS) != bm.end()) { - bookmark_vector &bv = bm[&logfile_sub_source::BM_WARNINGS]; - bookmark_vector::iterator iter; + bookmark_vector &bv = bm[&logfile_sub_source::BM_WARNINGS]; + bookmark_vector::iterator iter; iter = lower_bound(bv.begin(), bv.end(), tc->get_top()); sfw.set_value("%9dW", distance(bv.begin(), iter)); @@ -82,8 +82,8 @@ public: } if (bm.find(&logfile_sub_source::BM_ERRORS) != bm.end()) { - bookmark_vector &bv = bm[&logfile_sub_source::BM_ERRORS]; - bookmark_vector::iterator iter; + bookmark_vector &bv = bm[&logfile_sub_source::BM_ERRORS]; + bookmark_vector::iterator iter; iter = lower_bound(bv.begin(), bv.end(), tc->get_top()); sfe.set_value("%9dE", distance(bv.begin(), iter)); diff --git a/test/drive_sequencer.cc b/test/drive_sequencer.cc index 1b89cab7..3ff52e53 100644 --- a/test/drive_sequencer.cc +++ b/test/drive_sequencer.cc @@ -106,7 +106,7 @@ int main(int argc, char *argv[]) static bookmark_type_t SEQUENCE; sequence_matcher sm(fc); - bookmarks bm; + vis_bookmarks bm; sequence_sink ss(sm, bm[&SEQUENCE]); FD_ZERO(&read_fds); @@ -125,7 +125,7 @@ int main(int argc, char *argv[]) gp.check_fd_set(rfds); } - for (bookmark_vector::iterator iter = bm[&SEQUENCE].begin(); + for (bookmark_vector::iterator iter = bm[&SEQUENCE].begin(); iter != bm[&SEQUENCE].end(); ++iter) { printf("%d\n", (const int)*iter); diff --git a/test/test_bookmarks.cc b/test/test_bookmarks.cc index ebee2202..bc787bfd 100644 --- a/test/test_bookmarks.cc +++ b/test/test_bookmarks.cc @@ -10,7 +10,7 @@ int main(int argc, char *argv[]) { int lpc, retval = EXIT_SUCCESS; - bookmark_vector bv, bv_cp; + bookmark_vector bv, bv_cp; bv.insert_once(vis_line_t(1)); bv.insert_once(vis_line_t(1));