summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornicm <nicm>2020-03-31 16:53:23 +0000
committerNicholas Marriott <nicholas.marriott@gmail.com>2020-04-01 10:08:09 +0100
commit8dedccaa205a91a0dd57012150567403c2ac827d (patch)
tree10568cade7d592df321d9dcd3c6abb25edcf3194
parente5fd85415d89ebe8b2f69c80ce6cf80fb1442fde (diff)
Add non-regex search variants to avoid the performance cost for people
with large histories or long lines.
-rw-r--r--tmux.124
-rw-r--r--tmux.h2
-rw-r--r--window-copy.c135
3 files changed, 116 insertions, 45 deletions
diff --git a/tmux.1 b/tmux.1
index dc78abdc..03950c60 100644
--- a/tmux.1
+++ b/tmux.1
@@ -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
diff --git a/tmux.h b/tmux.h
index 222f7d43..3720beee 100644
--- a/tmux.h
+++ b/tmux.h
@@ -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;
diff --git a/window-copy.c b/window-copy.c
index 8e3f63d1..bb38e60e 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -254,6 +254,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;
@@ -307,9 +308,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;
@@ -675,6 +678,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)
{
@@ -1496,10 +1528,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);
}
@@ -1513,10 +1545,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);
}
@@ -1736,29 +1768,13 @@ 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);
}
@@ -1766,34 +1782,37 @@ window_copy_cmd_search_backward(struct window_copy_cmd_state *cs)
}
static enum window_copy_cmd_action
-window_copy_cmd_search_forward(struct window_copy_cmd_state *cs)
+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;
- 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 = 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;
+
+ 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);
}
@@ -1801,6 +1820,25 @@ window_copy_cmd_search_forward(struct window_copy_cmd_state *cs)
}
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)
{
struct window_mode_entry *wme = cs->wme;
@@ -1829,6 +1867,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)) {
@@ -1838,6 +1877,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)) {
@@ -1878,6 +1918,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)) {
@@ -1887,6 +1928,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)) {
@@ -2012,10 +2054,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,
@@ -2624,6 +2670,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;