[hotkey] the n/N keys will now move to the next cluster of search hits, up to a screenful

Defect Number:
    Reviewed By:
   Testing Done:
This commit is contained in:
Timothy Stack 2016-11-25 15:44:36 -08:00
parent 95fe6f0d73
commit 02bfd5846b
6 changed files with 104 additions and 15 deletions

4
NEWS
View File

@ -21,7 +21,9 @@ lnav v0.8.2:
users.
* Pressing 'n'/'N' to move through the next/previous search hit will now
skip adjacent lines, up to the vertical size of the view. This should
make scanning through clusters of hits much faster.
make scanning through clusters of hits much faster. Repeatedly
pressing these keys within a short time will also accelerate scanning
by moving the view at least a full page at a time.
Breaking Changes:
* The captured timestamp text in log files must fully match a known format

View File

@ -196,7 +196,10 @@ Spatial Navigation
e/E Move to the next/previous error.
w/W Move to the next/previous warning.
n/N Move to the next/previous search hit.
n/N Move to the next/previous search hit. When pressed
repeatedly within a short time, the view will move at
least a full page at a time instead of moving to the
next hit.
f/F Move to the next/previous file. In the log view, this
moves to the next line from a different file. In the
text view, this rotates the view to the next file.

View File

@ -332,21 +332,19 @@ void handle_paging_key(int ch)
case 'n':
moveto_cluster(&bookmark_vector<vis_line_t>::next,
&textview_curses::BM_SEARCH,
tc->get_top());
search_forward_from(tc));
lnav_data.ld_bottom_source.grep_error("");
lnav_data.ld_rl_view->set_alt_value(
"Press '" ANSI_BOLD(">") "' or '" ANSI_BOLD("<")
"' to scroll horizontally to a search result");
"Press '" ANSI_BOLD(">") "' or '" ANSI_BOLD("<")
"' to scroll horizontally to a search result");
break;
case 'N':
moveto_cluster(&bookmark_vector<vis_line_t>::prev,
&textview_curses::BM_SEARCH,
tc->get_top());
previous_cluster(&textview_curses::BM_SEARCH, tc);
lnav_data.ld_bottom_source.grep_error("");
lnav_data.ld_rl_view->set_alt_value(
"Press '" ANSI_BOLD(">") "' or '" ANSI_BOLD("<")
"' to scroll horizontally to a search result");
"Press '" ANSI_BOLD(">") "' or '" ANSI_BOLD("<")
"' to scroll horizontally to a search result");
break;
case 'y':

View File

@ -892,8 +892,8 @@ vis_line_t next_cluster(
}
bool moveto_cluster(vis_line_t(bookmark_vector<vis_line_t>::*f) (vis_line_t),
bookmark_type_t *bt,
vis_line_t top)
bookmark_type_t *bt,
vis_line_t top)
{
textview_curses *tc = lnav_data.ld_view_stack.top();
vis_line_t new_top;
@ -909,6 +909,48 @@ bool moveto_cluster(vis_line_t(bookmark_vector<vis_line_t>::*f) (vis_line_t),
return false;
}
void previous_cluster(bookmark_type_t *bt, textview_curses *tc)
{
key_repeat_history &krh = lnav_data.ld_key_repeat_history;
vis_line_t height, new_top, initial_top = tc->get_top();
unsigned long width;
new_top = next_cluster(&bookmark_vector<vis_line_t>::prev,
bt,
initial_top);
tc->get_dimensions(height, width);
if (krh.krh_count > 1 &&
initial_top < (krh.krh_start_line - (1.5 * height)) &&
(initial_top - new_top) < height) {
bookmark_vector<vis_line_t> &bv = tc->get_bookmarks()[bt];
new_top = bv.next(std::max(vis_line_t(0), initial_top - height));
}
if (new_top != -1) {
tc->set_top(new_top);
}
else {
alerter::singleton().chime();
}
}
vis_line_t search_forward_from(textview_curses *tc)
{
vis_line_t height, retval = tc->get_top();
key_repeat_history &krh = lnav_data.ld_key_repeat_history;
unsigned long width;
tc->get_dimensions(height, width);
if (krh.krh_count > 1 &&
retval > (krh.krh_start_line + (1.5 * height))) {
retval += vis_line_t(0.90 * height);
}
return retval;
}
static void handle_rl_key(int ch)
{
switch (ch) {
@ -1898,6 +1940,10 @@ static void looper(void)
escape_index = 0;
continue;
}
lnav_data.ld_key_repeat_history.update(
ch, lnav_data.ld_view_stack.top()->get_top());
switch (ch) {
case CEOF:
case KEY_RESIZE:

View File

@ -174,6 +174,40 @@ private:
size_t ist_index;
};
struct key_repeat_history {
key_repeat_history()
: krh_key(0),
krh_count(0) {
this->krh_last_press_time.tv_sec = 0;
this->krh_last_press_time.tv_usec = 0;
}
int krh_key;
int krh_count;
vis_line_t krh_start_line;
struct timeval krh_last_press_time;
void update(int ch, vis_line_t top) {
struct timeval now, diff;
gettimeofday(&now, NULL);
timersub(&now, &this->krh_last_press_time, &diff);
if (diff.tv_sec >= 1 || diff.tv_usec > (750 * 1000)) {
this->krh_key = 0;
this->krh_count = 0;
}
this->krh_last_press_time = now;
if (this->krh_key == ch) {
this->krh_count += 1;
} else {
this->krh_key = ch;
this->krh_count = 1;
this->krh_start_line = top;
}
};
};
struct _lnav_data {
std::string ld_session_id;
time_t ld_session_time;
@ -264,6 +298,8 @@ struct _lnav_data {
std::map<std::string, std::vector<script_metadata> > ld_scripts;
int ld_fifo_counter;
struct key_repeat_history ld_key_repeat_history;
};
extern struct _lnav_data lnav_data;
@ -298,7 +334,9 @@ vis_line_t next_cluster(
bookmark_type_t *bt,
vis_line_t top);
bool moveto_cluster(vis_line_t(bookmark_vector<vis_line_t>::*f) (vis_line_t),
bookmark_type_t *bt,
vis_line_t top);
bookmark_type_t *bt,
vis_line_t top);
void previous_cluster(bookmark_type_t *bt, textview_curses *tc);
vis_line_t search_forward_from(textview_curses *tc);
#endif

View File

@ -638,7 +638,9 @@ public:
if (first_hit > 0) {
--first_hit;
}
this->set_top(first_hit);
if (first_hit > this->get_top()) {
this->set_top(first_hit);
}
}
}
}