Add non-regex search variants to avoid the performance cost for people

with large histories or long lines.
pull/2151/head
nicm 2020-03-31 16:53:23 +00:00
parent 2ca95840d1
commit 2624edde46
3 changed files with 116 additions and 45 deletions

24
tmux.1
View File

@ -1503,9 +1503,11 @@ The following commands are supported in copy mode:
.It Li "scroll-up" Ta "C-y" Ta "C-Up"
.It Li "search-again" Ta "n" Ta "n"
.It Li "search-backward <for>" Ta "?" Ta ""
.It Li "search-forward <for>" Ta "/" Ta ""
.It Li "search-backward-incremental <for>" Ta "" Ta "C-r"
.It Li "search-backward-text <for>" Ta "" Ta ""
.It Li "search-forward <for>" Ta "/" Ta ""
.It Li "search-forward-incremental <for>" Ta "" Ta "C-s"
.It Li "search-forward-text <for>" Ta "" Ta ""
.It Li "search-reverse" Ta "N" Ta "N"
.It Li "select-line" Ta "V" Ta ""
.It Li "select-word" Ta "" Ta ""
@ -1514,6 +1516,26 @@ The following commands are supported in copy mode:
.It Li "top-line" Ta "H" Ta "M-R"
.El
.Pp
The search commands come in several varieties:
.Ql search-forward
and
.Ql search-backward
search for a regular expression;
the
.Ql -text
variants search for a plain text string rather than a regular expression;
.Ql -incremental
perform an incremental search and expect to be used with the
.Fl i
flag to the
.Ic command-prompt
command.
.Ql search-again
repeats the last search and
.Ql search-reverse
does the same but reverses the direction (forward becomes backward and backward
becomes forward).
.Pp
Copy commands may take an optional buffer prefix argument which is used
to generate the buffer name (the default is
.Ql buffer

2
tmux.h
View File

@ -927,7 +927,9 @@ struct window_pane {
TAILQ_HEAD (, window_mode_entry) modes;
struct event modetimer;
time_t modelast;
char *searchstr;
int searchregex;
TAILQ_ENTRY(window_pane) entry;
RB_ENTRY(window_pane) tree_entry;

View File

@ -256,6 +256,7 @@ struct window_copy_mode_data {
u_int lastsx; /* size of last line w/ content */
int searchtype;
int searchregex;
char *searchstr;
bitstr_t *searchmark;
u_int searchcount;
@ -310,9 +311,11 @@ window_copy_common_init(struct window_mode_entry *wme)
if (wp->searchstr != NULL) {
data->searchtype = WINDOW_COPY_SEARCHUP;
data->searchregex = wp->searchregex;
data->searchstr = xstrdup(wp->searchstr);
} else {
data->searchtype = WINDOW_COPY_OFF;
data->searchregex = 0;
data->searchstr = NULL;
}
data->searchmark = NULL;
@ -700,6 +703,35 @@ window_copy_key_table(struct window_mode_entry *wme)
return ("copy-mode");
}
static int
window_copy_expand_search_string(struct window_copy_cmd_state *cs)
{
struct window_mode_entry *wme = cs->wme;
struct window_copy_mode_data *data = wme->data;
const char *argument;
char *expanded;
if (cs->args->argc == 2) {
argument = cs->args->argv[1];
if (*argument != '\0') {
if (args_has(cs->args, 'F')) {
expanded = format_single(NULL, argument, NULL,
NULL, NULL, wme->wp);
if (*expanded == '\0') {
free(expanded);
return (0);
}
free(data->searchstr);
data->searchstr = expanded;
} else {
free(data->searchstr);
data->searchstr = xstrdup(argument);
}
}
}
return (1);
}
static enum window_copy_cmd_action
window_copy_cmd_append_selection(struct window_copy_cmd_state *cs)
{
@ -1525,10 +1557,10 @@ window_copy_cmd_search_again(struct window_copy_cmd_state *cs)
if (data->searchtype == WINDOW_COPY_SEARCHUP) {
for (; np != 0; np--)
window_copy_search_up(wme, 1);
window_copy_search_up(wme, data->searchregex);
} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) {
for (; np != 0; np--)
window_copy_search_down(wme, 1);
window_copy_search_down(wme, data->searchregex);
}
return (WINDOW_COPY_CMD_NOTHING);
}
@ -1542,10 +1574,10 @@ window_copy_cmd_search_reverse(struct window_copy_cmd_state *cs)
if (data->searchtype == WINDOW_COPY_SEARCHUP) {
for (; np != 0; np--)
window_copy_search_down(wme, 1);
window_copy_search_down(wme, data->searchregex);
} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) {
for (; np != 0; np--)
window_copy_search_up(wme, 1);
window_copy_search_up(wme, data->searchregex);
}
return (WINDOW_COPY_CMD_NOTHING);
}
@ -1765,70 +1797,76 @@ window_copy_cmd_search_backward(struct window_copy_cmd_state *cs)
struct window_mode_entry *wme = cs->wme;
struct window_copy_mode_data *data = wme->data;
u_int np = wme->prefix;
const char *argument;
char *expanded;
if (cs->args->argc == 2) {
argument = cs->args->argv[1];
if (*argument != '\0') {
if (args_has(cs->args, 'F')) {
expanded = format_single(NULL, argument, NULL,
NULL, NULL, wme->wp);
if (*expanded == '\0') {
free(expanded);
return (WINDOW_COPY_CMD_NOTHING);
}
free(data->searchstr);
data->searchstr = expanded;
} else {
free(data->searchstr);
data->searchstr = xstrdup(argument);
}
}
}
if (!window_copy_expand_search_string(cs))
return (WINDOW_COPY_CMD_NOTHING);
if (data->searchstr != NULL) {
data->searchtype = WINDOW_COPY_SEARCHUP;
data->searchregex = 1;
for (; np != 0; np--)
window_copy_search_up(wme, 1);
}
return (WINDOW_COPY_CMD_NOTHING);
}
static enum window_copy_cmd_action
window_copy_cmd_search_backward_text(struct window_copy_cmd_state *cs)
{
struct window_mode_entry *wme = cs->wme;
struct window_copy_mode_data *data = wme->data;
u_int np = wme->prefix;
if (!window_copy_expand_search_string(cs))
return (WINDOW_COPY_CMD_NOTHING);
if (data->searchstr != NULL) {
data->searchtype = WINDOW_COPY_SEARCHUP;
data->searchregex = 0;
for (; np != 0; np--)
window_copy_search_up(wme, 0);
}
return (WINDOW_COPY_CMD_NOTHING);
}
static enum window_copy_cmd_action
window_copy_cmd_search_forward(struct window_copy_cmd_state *cs)
{
struct window_mode_entry *wme = cs->wme;
struct window_copy_mode_data *data = wme->data;
u_int np = wme->prefix;
const char *argument;
char *expanded;
if (cs->args->argc == 2) {
argument = cs->args->argv[1];
if (*argument != '\0') {
if (args_has(cs->args, 'F')) {
expanded = format_single(NULL, argument, NULL,
NULL, NULL, wme->wp);
if (*expanded == '\0') {
free(expanded);
return (WINDOW_COPY_CMD_NOTHING);
}
free(data->searchstr);
data->searchstr = expanded;
} else {
free(data->searchstr);
data->searchstr = xstrdup(argument);
}
}
}
if (!window_copy_expand_search_string(cs))
return (WINDOW_COPY_CMD_NOTHING);
if (data->searchstr != NULL) {
data->searchtype = WINDOW_COPY_SEARCHDOWN;
data->searchregex = 1;
for (; np != 0; np--)
window_copy_search_down(wme, 1);
}
return (WINDOW_COPY_CMD_NOTHING);
}
static enum window_copy_cmd_action
window_copy_cmd_search_forward_text(struct window_copy_cmd_state *cs)
{
struct window_mode_entry *wme = cs->wme;
struct window_copy_mode_data *data = wme->data;
u_int np = wme->prefix;
if (!window_copy_expand_search_string(cs))
return (WINDOW_COPY_CMD_NOTHING);
if (data->searchstr != NULL) {
data->searchtype = WINDOW_COPY_SEARCHDOWN;
data->searchregex = 0;
for (; np != 0; np--)
window_copy_search_down(wme, 0);
}
return (WINDOW_COPY_CMD_NOTHING);
}
static enum window_copy_cmd_action
window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs)
{
@ -1858,6 +1896,7 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs)
case '=':
case '-':
data->searchtype = WINDOW_COPY_SEARCHUP;
data->searchregex = 0;
free(data->searchstr);
data->searchstr = xstrdup(argument);
if (!window_copy_search_up(wme, 0)) {
@ -1867,6 +1906,7 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs)
break;
case '+':
data->searchtype = WINDOW_COPY_SEARCHDOWN;
data->searchregex = 0;
free(data->searchstr);
data->searchstr = xstrdup(argument);
if (!window_copy_search_down(wme, 0)) {
@ -1907,6 +1947,7 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs)
case '=':
case '+':
data->searchtype = WINDOW_COPY_SEARCHDOWN;
data->searchregex = 0;
free(data->searchstr);
data->searchstr = xstrdup(argument);
if (!window_copy_search_down(wme, 0)) {
@ -1916,6 +1957,7 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs)
break;
case '-':
data->searchtype = WINDOW_COPY_SEARCHUP;
data->searchregex = 0;
free(data->searchstr);
data->searchstr = xstrdup(argument);
if (!window_copy_search_up(wme, 0)) {
@ -2041,10 +2083,14 @@ static const struct {
window_copy_cmd_search_again },
{ "search-backward", 0, 1, 0,
window_copy_cmd_search_backward },
{ "search-backward-text", 0, 1, 0,
window_copy_cmd_search_backward_text },
{ "search-backward-incremental", 1, 1, 0,
window_copy_cmd_search_backward_incremental },
{ "search-forward", 0, 1, 0,
window_copy_cmd_search_forward },
{ "search-forward-text", 0, 1, 0,
window_copy_cmd_search_forward_text },
{ "search-forward-incremental", 1, 1, 0,
window_copy_cmd_search_forward_incremental },
{ "search-reverse", 0, 0, 0,
@ -2653,6 +2699,7 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex)
free(wp->searchstr);
wp->searchstr = xstrdup(data->searchstr);
wp->searchregex = regex;
fx = data->cx;
fy = screen_hsize(data->backing) - data->oy + data->cy;