diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2017-01-06 11:57:04 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2017-01-06 11:57:04 +0000 |
commit | 15ce00a3a1f3aed4b9bebb412b5d36f084822230 (patch) | |
tree | b6162243bfcc81db6cdc8a99a3dcb6214c816747 | |
parent | d76db7076bfea9a334a2c1ddccb141e3f564ab78 (diff) |
Incremental search in copy mode (on for emacs keys by default) - much
the same as normal searching but updates the cursor position and marked
search terms as you type. C-r and C-s in the prompt repeat the search,
once finished searching (with Enter), N and n work as before.
-rw-r--r-- | usr.bin/tmux/cmd-command-prompt.c | 45 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-confirm-before.c | 6 | ||||
-rw-r--r-- | usr.bin/tmux/cmd.c | 4 | ||||
-rw-r--r-- | usr.bin/tmux/key-bindings.c | 66 | ||||
-rw-r--r-- | usr.bin/tmux/status.c | 84 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.1 | 17 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 7 | ||||
-rw-r--r-- | usr.bin/tmux/window-copy.c | 165 |
8 files changed, 263 insertions, 131 deletions
diff --git a/usr.bin/tmux/cmd-command-prompt.c b/usr.bin/tmux/cmd-command-prompt.c index 2de0e110fa8..b768ed59721 100644 --- a/usr.bin/tmux/cmd-command-prompt.c +++ b/usr.bin/tmux/cmd-command-prompt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-command-prompt.c,v 1.38 2016/10/16 19:04:05 nicm Exp $ */ +/* $OpenBSD: cmd-command-prompt.c,v 1.39 2017/01/06 11:57:03 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -32,15 +32,15 @@ static enum cmd_retval cmd_command_prompt_exec(struct cmd *, struct cmdq_item *); -static int cmd_command_prompt_callback(void *, const char *); +static int cmd_command_prompt_callback(void *, const char *, int); static void cmd_command_prompt_free(void *); const struct cmd_entry cmd_command_prompt_entry = { .name = "command-prompt", .alias = NULL, - .args = { "1I:Np:t:", 0, 1 }, - .usage = "[-1N] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " " + .args = { "1iI:Np:t:", 0, 1 }, + .usage = "[-1Ni] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " " "[template]", .tflag = CMD_CLIENT, @@ -51,10 +51,14 @@ const struct cmd_entry cmd_command_prompt_entry = { struct cmd_command_prompt_cdata { struct client *c; + int flags; + char *inputs; char *next_input; - char *next_prompt; + char *prompts; + char *next_prompt; + char *template; int idx; }; @@ -73,14 +77,17 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item) if (c->prompt_string != NULL) return (CMD_RETURN_NORMAL); - cdata = xmalloc(sizeof *cdata); + cdata = xcalloc(1, sizeof *cdata); cdata->c = c; - cdata->idx = 1; + cdata->inputs = NULL; cdata->next_input = NULL; - cdata->next_prompt = NULL; + cdata->prompts = NULL; + cdata->next_prompt = NULL; + cdata->template = NULL; + cdata->idx = 1; if (args->argc != 0) cdata->template = xstrdup(args->argv[0]); @@ -112,11 +119,13 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item) flags = 0; if (args_has(args, '1')) - flags |= PROMPT_SINGLE; + cdata->flags |= PROMPT_SINGLE; else if (args_has(args, 'N')) - flags |= PROMPT_NUMERIC; + cdata->flags |= PROMPT_NUMERIC; + else if (args_has(args, 'i')) + cdata->flags |= PROMPT_INCREMENTAL; status_prompt_set(c, prompt, input, cmd_command_prompt_callback, - cmd_command_prompt_free, cdata, flags); + cmd_command_prompt_free, cdata, cdata->flags); free(prompt); return (CMD_RETURN_NORMAL); @@ -134,7 +143,7 @@ cmd_command_prompt_error(struct cmdq_item *item, void *data) } static int -cmd_command_prompt_callback(void *data, const char *s) +cmd_command_prompt_callback(void *data, const char *s, int done) { struct cmd_command_prompt_cdata *cdata = data; struct client *c = cdata->c; @@ -145,16 +154,20 @@ cmd_command_prompt_callback(void *data, const char *s) if (s == NULL) return (0); + if (done && (cdata->flags & PROMPT_INCREMENTAL)) + return (0); new_template = cmd_template_replace(cdata->template, s, cdata->idx); - free(cdata->template); - cdata->template = new_template; + if (done) { + free(cdata->template); + cdata->template = new_template; + } /* * Check if there are more prompts; if so, get its respective input * and update the prompt data. */ - if ((ptr = strsep(&cdata->next_prompt, ",")) != NULL) { + if (done && (ptr = strsep(&cdata->next_prompt, ",")) != NULL) { xasprintf(&prompt, "%s ", ptr); input = strsep(&cdata->next_input, ","); status_prompt_update(c, prompt, input); @@ -178,6 +191,8 @@ cmd_command_prompt_callback(void *data, const char *s) if (new_item != NULL) cmdq_append(c, new_item); + if (!done) + free(new_template); if (c->prompt_callbackfn != (void *)&cmd_command_prompt_callback) return (1); return (0); diff --git a/usr.bin/tmux/cmd-confirm-before.c b/usr.bin/tmux/cmd-confirm-before.c index e84a654cba4..ac0fc7a7120 100644 --- a/usr.bin/tmux/cmd-confirm-before.c +++ b/usr.bin/tmux/cmd-confirm-before.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-confirm-before.c,v 1.31 2016/10/16 19:04:05 nicm Exp $ */ +/* $OpenBSD: cmd-confirm-before.c,v 1.32 2017/01/06 11:57:03 nicm Exp $ */ /* * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> @@ -31,7 +31,7 @@ static enum cmd_retval cmd_confirm_before_exec(struct cmd *, struct cmdq_item *); -static int cmd_confirm_before_callback(void *, const char *); +static int cmd_confirm_before_callback(void *, const char *, int); static void cmd_confirm_before_free(void *); const struct cmd_entry cmd_confirm_before_entry = { @@ -96,7 +96,7 @@ cmd_confirm_before_error(struct cmdq_item *item, void *data) } static int -cmd_confirm_before_callback(void *data, const char *s) +cmd_confirm_before_callback(void *data, const char *s, __unused int done) { struct cmd_confirm_before_data *cdata = data; struct client *c = cdata->client; diff --git a/usr.bin/tmux/cmd.c b/usr.bin/tmux/cmd.c index 3c6df33e091..d5f325fa0f8 100644 --- a/usr.bin/tmux/cmd.c +++ b/usr.bin/tmux/cmd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd.c,v 1.129 2016/12/28 10:34:34 nicm Exp $ */ +/* $OpenBSD: cmd.c,v 1.130 2017/01/06 11:57:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -692,7 +692,7 @@ cmd_template_replace(const char *template, const char *s, int idx) buf = xrealloc(buf, len + (strlen(s) * 2) + 1); for (cp = s; *cp != '\0'; cp++) { - if (quoted && *cp == '"') + if (quoted && (*cp == '"' || *cp == '$')) buf[len++] = '\\'; buf[len++] = *cp; } diff --git a/usr.bin/tmux/key-bindings.c b/usr.bin/tmux/key-bindings.c index 12103eacf9f..827ddb781b5 100644 --- a/usr.bin/tmux/key-bindings.c +++ b/usr.bin/tmux/key-bindings.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key-bindings.c,v 1.67 2016/12/07 09:16:13 nicm Exp $ */ +/* $OpenBSD: key-bindings.c,v 1.68 2017/01/06 11:57:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -243,23 +243,23 @@ key_bindings_init(void) "bind -Tcopy-mode C-k send -X copy-end-of-line", "bind -Tcopy-mode C-n send -X cursor-down", "bind -Tcopy-mode C-p send -X cursor-up", - "bind -Tcopy-mode C-r command-prompt -p'search up' \"send -X search-backward \\\"%%%\\\"\"", - "bind -Tcopy-mode C-s command-prompt -p'search down' \"send -X search-forward \\\"%%%\\\"\"", + "bind -Tcopy-mode C-r command-prompt -ip'search up' 'send -X search-backward-incremental \"%%%\"'", + "bind -Tcopy-mode C-s command-prompt -ip'search down' 'send -X search-forward-incremental \"%%%\"'", "bind -Tcopy-mode C-v send -X page-down", "bind -Tcopy-mode C-w send -X copy-selection-and-cancel", "bind -Tcopy-mode Escape send -X cancel", "bind -Tcopy-mode Space send -X page-down", "bind -Tcopy-mode , send -X jump-reverse", "bind -Tcopy-mode \\; send -X jump-again", - "bind -Tcopy-mode F command-prompt -1p'jump backward' \"send -X jump-backward \\\"%%%\\\"\"", + "bind -Tcopy-mode F command-prompt -1p'jump backward' 'send -X jump-backward \"%%%\"'", "bind -Tcopy-mode N send -X search-reverse", "bind -Tcopy-mode R send -X rectangle-toggle", - "bind -Tcopy-mode T command-prompt -1p'jump to backward' \"send -X jump-to-backward \\\"%%%\\\"\"", - "bind -Tcopy-mode f command-prompt -1p'jump forward' \"send -X jump-forward \\\"%%%\\\"\"", - "bind -Tcopy-mode g command-prompt -p'goto line' \"send -X goto-line '%%'\"", + "bind -Tcopy-mode T command-prompt -1p'jump to backward' 'send -X jump-to-backward \"%%%\"'", + "bind -Tcopy-mode f command-prompt -1p'jump forward' 'send -X jump-forward \"%%%\"'", + "bind -Tcopy-mode g command-prompt -p'goto line' 'send -X goto-line \"%%%\"'", "bind -Tcopy-mode n send -X search-again", "bind -Tcopy-mode q send -X cancel", - "bind -Tcopy-mode t command-prompt -1p'jump to forward' \"send -X jump-to-forward \\\"%%%\\\"\"", + "bind -Tcopy-mode t command-prompt -1p'jump to forward' 'send -X jump-to-forward \"%%%\"'", "bind -Tcopy-mode MouseDown1Pane select-pane", "bind -Tcopy-mode MouseDrag1Pane select-pane\\; send -X begin-selection", "bind -Tcopy-mode MouseDragEnd1Pane send -X copy-selection-and-cancel", @@ -273,15 +273,15 @@ key_bindings_init(void) "bind -Tcopy-mode Down send -X cursor-down", "bind -Tcopy-mode Left send -X cursor-left", "bind -Tcopy-mode Right send -X cursor-right", - "bind -Tcopy-mode M-1 command-prompt -Np'repeat' -I1 \"send -N '%%'\"", - "bind -Tcopy-mode M-2 command-prompt -Np'repeat' -I2 \"send -N '%%'\"", - "bind -Tcopy-mode M-3 command-prompt -Np'repeat' -I3 \"send -N '%%'\"", - "bind -Tcopy-mode M-4 command-prompt -Np'repeat' -I4 \"send -N '%%'\"", - "bind -Tcopy-mode M-5 command-prompt -Np'repeat' -I5 \"send -N '%%'\"", - "bind -Tcopy-mode M-6 command-prompt -Np'repeat' -I6 \"send -N '%%'\"", - "bind -Tcopy-mode M-7 command-prompt -Np'repeat' -I7 \"send -N '%%'\"", - "bind -Tcopy-mode M-8 command-prompt -Np'repeat' -I8 \"send -N '%%'\"", - "bind -Tcopy-mode M-9 command-prompt -Np'repeat' -I9 \"send -N '%%'\"", + "bind -Tcopy-mode M-1 command-prompt -Np'repeat' -I1 'send -N \"%%%\"'", + "bind -Tcopy-mode M-2 command-prompt -Np'repeat' -I2 'send -N \"%%%\"'", + "bind -Tcopy-mode M-3 command-prompt -Np'repeat' -I3 'send -N \"%%%\"'", + "bind -Tcopy-mode M-4 command-prompt -Np'repeat' -I4 'send -N \"%%%\"'", + "bind -Tcopy-mode M-5 command-prompt -Np'repeat' -I5 'send -N \"%%%\"'", + "bind -Tcopy-mode M-6 command-prompt -Np'repeat' -I6 'send -N \"%%%\"'", + "bind -Tcopy-mode M-7 command-prompt -Np'repeat' -I7 'send -N \"%%%\"'", + "bind -Tcopy-mode M-8 command-prompt -Np'repeat' -I8 'send -N \"%%%\"'", + "bind -Tcopy-mode M-9 command-prompt -Np'repeat' -I9 'send -N \"%%%\"'", "bind -Tcopy-mode M-< send -X history-top", "bind -Tcopy-mode M-> send -X history-bottom", "bind -Tcopy-mode M-R send -X top-line", @@ -313,25 +313,25 @@ key_bindings_init(void) "bind -Tcopy-mode-vi Space send -X begin-selection", "bind -Tcopy-mode-vi '$' send -X end-of-line", "bind -Tcopy-mode-vi , send -X jump-reverse", - "bind -Tcopy-mode-vi / command-prompt -p'search down' \"send -X search-forward \\\"%%%\\\"\"", + "bind -Tcopy-mode-vi / command-prompt -p'search down' 'send -X search-forward \"%%%\"'", "bind -Tcopy-mode-vi 0 send -X start-of-line", - "bind -Tcopy-mode-vi 1 command-prompt -Np'repeat' -I1 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 2 command-prompt -Np'repeat' -I2 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 3 command-prompt -Np'repeat' -I3 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 4 command-prompt -Np'repeat' -I4 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 5 command-prompt -Np'repeat' -I5 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 6 command-prompt -Np'repeat' -I6 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 7 command-prompt -Np'repeat' -I7 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 8 command-prompt -Np'repeat' -I8 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 9 command-prompt -Np'repeat' -I9 \"send -N '%%'\"", - "bind -Tcopy-mode-vi : command-prompt -p'goto line' \"send -X goto-line '%%'\"", + "bind -Tcopy-mode-vi 1 command-prompt -Np'repeat' -I1 'send -N \"%%%\"'", + "bind -Tcopy-mode-vi 2 command-prompt -Np'repeat' -I2 'send -N \"%%%\"'", + "bind -Tcopy-mode-vi 3 command-prompt -Np'repeat' -I3 'send -N \"%%%\"'", + "bind -Tcopy-mode-vi 4 command-prompt -Np'repeat' -I4 'send -N \"%%%\"'", + "bind -Tcopy-mode-vi 5 command-prompt -Np'repeat' -I5 'send -N \"%%%\"'", + "bind -Tcopy-mode-vi 6 command-prompt -Np'repeat' -I6 'send -N \"%%%\"'", + "bind -Tcopy-mode-vi 7 command-prompt -Np'repeat' -I7 'send -N \"%%%\"'", + "bind -Tcopy-mode-vi 8 command-prompt -Np'repeat' -I8 'send -N \"%%%\"'", + "bind -Tcopy-mode-vi 9 command-prompt -Np'repeat' -I9 'send -N \"%%%\"'", + "bind -Tcopy-mode-vi : command-prompt -p'goto line' 'send -X goto-line \"%%%\"'", "bind -Tcopy-mode-vi \\; send -X jump-again", - "bind -Tcopy-mode-vi ? command-prompt -p'search up' \"send -X search-backward \\\"%%%\\\"\"", + "bind -Tcopy-mode-vi ? command-prompt -p'search up' 'send -X search-backward \"%%%\"'", "bind -Tcopy-mode-vi A send -X append-selection-and-cancel", "bind -Tcopy-mode-vi B send -X previous-space", "bind -Tcopy-mode-vi D send -X copy-end-of-line", "bind -Tcopy-mode-vi E send -X next-space-end", - "bind -Tcopy-mode-vi F command-prompt -1p'jump backward' \"send -X jump-backward \\\"%%%\\\"\"", + "bind -Tcopy-mode-vi F command-prompt -1p'jump backward' 'send -X jump-backward \"%%%\"'", "bind -Tcopy-mode-vi G send -X history-bottom", "bind -Tcopy-mode-vi H send -X top-line", "bind -Tcopy-mode-vi J send -X scroll-down", @@ -339,13 +339,13 @@ key_bindings_init(void) "bind -Tcopy-mode-vi L send -X bottom-line", "bind -Tcopy-mode-vi M send -X middle-line", "bind -Tcopy-mode-vi N send -X search-reverse", - "bind -Tcopy-mode-vi T command-prompt -1p'jump to backward' \"send -X jump-to-backward \\\"%%%\\\"\"", + "bind -Tcopy-mode-vi T command-prompt -1p'jump to backward' 'send -X jump-to-backward \"%%%\"'", "bind -Tcopy-mode-vi V send -X select-line", "bind -Tcopy-mode-vi W send -X next-space", "bind -Tcopy-mode-vi ^ send -X back-to-indentation", "bind -Tcopy-mode-vi b send -X previous-word", "bind -Tcopy-mode-vi e send -X next-word-end", - "bind -Tcopy-mode-vi f command-prompt -1p'jump forward' \"send -X jump-forward \\\"%%%\\\"\"", + "bind -Tcopy-mode-vi f command-prompt -1p'jump forward' 'send -X jump-forward \"%%%\"'", "bind -Tcopy-mode-vi g send -X history-top", "bind -Tcopy-mode-vi h send -X cursor-left", "bind -Tcopy-mode-vi j send -X cursor-down", @@ -354,7 +354,7 @@ key_bindings_init(void) "bind -Tcopy-mode-vi n send -X search-again", "bind -Tcopy-mode-vi o send -X other-end", "bind -Tcopy-mode-vi q send -X cancel", - "bind -Tcopy-mode-vi t command-prompt -1p'jump to forward' \"send -X jump-to-forward \\\"%%%\\\"\"", + "bind -Tcopy-mode-vi t command-prompt -1p'jump to forward' 'send -X jump-to-forward \"%%%\"'", "bind -Tcopy-mode-vi v send -X rectangle-toggle", "bind -Tcopy-mode-vi w send -X next-word", "bind -Tcopy-mode-vi { send -X previous-paragraph", diff --git a/usr.bin/tmux/status.c b/usr.bin/tmux/status.c index f7a695d9805..2955e8b92c5 100644 --- a/usr.bin/tmux/status.c +++ b/usr.bin/tmux/status.c @@ -1,4 +1,4 @@ -/* $OpenBSD: status.c,v 1.157 2017/01/05 09:07:16 nicm Exp $ */ +/* $OpenBSD: status.c,v 1.158 2017/01/06 11:57:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -657,7 +657,7 @@ status_message_redraw(struct client *c) /* Enable status line prompt. */ void status_prompt_set(struct client *c, const char *msg, const char *input, - int (*callbackfn)(void *, const char *), void (*freefn)(void *), + int (*callbackfn)(void *, const char *, int), void (*freefn)(void *), void *data, int flags) { struct format_tree *ft; @@ -687,7 +687,8 @@ status_prompt_set(struct client *c, const char *msg, const char *input, c->prompt_flags = flags; c->prompt_mode = PROMPT_ENTRY; - c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE); + if (~flags & PROMPT_INCREMENTAL) + c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE); c->flags |= CLIENT_STATUS; free(tmp); @@ -976,7 +977,7 @@ status_prompt_key(struct client *c, key_code key) { struct options *oo = c->session->options; struct paste_buffer *pb; - char *s, word[64]; + char *s, *cp, word[64], prefix = '='; const char *histstr, *bufdata, *ws = NULL; u_char ch; size_t size, n, off, idx, bufsize, used; @@ -989,7 +990,7 @@ status_prompt_key(struct client *c, key_code key) if (key >= '0' && key <= '9') goto append_key; s = utf8_tocstr(c->prompt_buffer); - c->prompt_callbackfn(c->prompt_data, s); + c->prompt_callbackfn(c->prompt_data, s, 1); status_prompt_clear(c); free(s); return (1); @@ -1013,28 +1014,28 @@ process_key: case '\002': /* C-b */ if (c->prompt_index > 0) { c->prompt_index--; - c->flags |= CLIENT_STATUS; + break; } break; case KEYC_RIGHT: case '\006': /* C-f */ if (c->prompt_index < size) { c->prompt_index++; - c->flags |= CLIENT_STATUS; + break; } break; case KEYC_HOME: case '\001': /* C-a */ if (c->prompt_index != 0) { c->prompt_index = 0; - c->flags |= CLIENT_STATUS; + break; } break; case KEYC_END: case '\005': /* C-e */ if (c->prompt_index != size) { c->prompt_index = size; - c->flags |= CLIENT_STATUS; + break; } break; case '\011': /* Tab */ @@ -1094,8 +1095,7 @@ process_key: c->prompt_index = (first - c->prompt_buffer) + strlen(s); free(s); - c->flags |= CLIENT_STATUS; - break; + goto changed; case KEYC_BSPACE: case '\010': /* C-h */ if (c->prompt_index != 0) { @@ -1108,7 +1108,7 @@ process_key: sizeof *c->prompt_buffer); c->prompt_index--; } - c->flags |= CLIENT_STATUS; + goto changed; } break; case KEYC_DC: @@ -1118,18 +1118,17 @@ process_key: c->prompt_buffer + c->prompt_index + 1, (size + 1 - c->prompt_index) * sizeof *c->prompt_buffer); - c->flags |= CLIENT_STATUS; + goto changed; } break; case '\025': /* C-u */ c->prompt_buffer[0].size = 0; c->prompt_index = 0; - c->flags |= CLIENT_STATUS; - break; + goto changed; case '\013': /* C-k */ if (c->prompt_index < size) { c->prompt_buffer[c->prompt_index].size = 0; - c->flags |= CLIENT_STATUS; + goto changed; } break; case '\027': /* C-w */ @@ -1161,8 +1160,7 @@ process_key: '\0', (c->prompt_index - idx) * sizeof *c->prompt_buffer); c->prompt_index = idx; - c->flags |= CLIENT_STATUS; - break; + goto changed; case 'f'|KEYC_ESCAPE: ws = options_get_string(oo, "word-separators"); @@ -1185,8 +1183,7 @@ process_key: c->prompt_index != 0) c->prompt_index--; - c->flags |= CLIENT_STATUS; - break; + goto changed; case 'b'|KEYC_ESCAPE: ws = options_get_string(oo, "word-separators"); @@ -1206,9 +1203,7 @@ process_key: break; } } - - c->flags |= CLIENT_STATUS; - break; + goto changed; case KEYC_UP: case '\020': /* C-p */ histstr = status_prompt_up_history(&c->prompt_hindex); @@ -1217,8 +1212,7 @@ process_key: free(c->prompt_buffer); c->prompt_buffer = utf8_fromcstr(histstr); c->prompt_index = utf8_strlen(c->prompt_buffer); - c->flags |= CLIENT_STATUS; - break; + goto changed; case KEYC_DOWN: case '\016': /* C-n */ histstr = status_prompt_down_history(&c->prompt_hindex); @@ -1227,8 +1221,7 @@ process_key: free(c->prompt_buffer); c->prompt_buffer = utf8_fromcstr(histstr); c->prompt_index = utf8_strlen(c->prompt_buffer); - c->flags |= CLIENT_STATUS; - break; + goto changed; case '\031': /* C-y */ if ((pb = paste_get_top(NULL)) == NULL) break; @@ -1259,9 +1252,7 @@ process_key: } c->prompt_index += n; } - - c->flags |= CLIENT_STATUS; - break; + goto changed; case '\024': /* C-t */ idx = c->prompt_index; if (idx < size) @@ -1272,7 +1263,7 @@ process_key: &c->prompt_buffer[idx - 1]); utf8_copy(&c->prompt_buffer[idx - 1], &tmp); c->prompt_index = idx; - c->flags |= CLIENT_STATUS; + goto changed; } break; case '\r': @@ -1280,17 +1271,34 @@ process_key: s = utf8_tocstr(c->prompt_buffer); if (*s != '\0') status_prompt_add_history(s); - if (c->prompt_callbackfn(c->prompt_data, s) == 0) + if (c->prompt_callbackfn(c->prompt_data, s, 1) == 0) status_prompt_clear(c); free(s); break; case '\033': /* Escape */ case '\003': /* C-c */ - if (c->prompt_callbackfn(c->prompt_data, NULL) == 0) + if (c->prompt_callbackfn(c->prompt_data, NULL, 1) == 0) status_prompt_clear(c); break; + case '\022': /* C-r */ + if (c->prompt_flags & PROMPT_INCREMENTAL) { + prefix = '-'; + goto changed; + } + break; + case '\023': /* C-s */ + if (c->prompt_flags & PROMPT_INCREMENTAL) { + prefix = '+'; + goto changed; + } + break; + default: + goto append_key; } + c->flags |= CLIENT_STATUS; + return (0); + append_key: if (key <= 0x1f || key >= KEYC_BASE) return (0); @@ -1317,12 +1325,20 @@ append_key: s = utf8_tocstr(c->prompt_buffer); if (strlen(s) != 1) status_prompt_clear(c); - else if (c->prompt_callbackfn(c->prompt_data, s) == 0) + else if (c->prompt_callbackfn(c->prompt_data, s, 1) == 0) status_prompt_clear(c); free(s); } +changed: c->flags |= CLIENT_STATUS; + if (c->prompt_flags & PROMPT_INCREMENTAL) { + s = utf8_tocstr(c->prompt_buffer); + xasprintf(&cp, "%c%s", prefix, s); + c->prompt_callbackfn(c->prompt_data, cp, 0); + free(cp); + free(s); + } return (0); } diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 72bb8227b82..f78ef2a1f45 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.516 2016/11/29 12:54:46 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.517 2017/01/06 11:57:03 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> .\" @@ -14,7 +14,7 @@ .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: November 29 2016 $ +.Dd $Mdocdate: January 6 2017 $ .Dt TMUX 1 .Os .Sh NAME @@ -1020,7 +1020,7 @@ Key tables may be viewed with the command. .Pp The following commands are supported in copy mode: -.Bl -column "CommandXXXXXXXXXXXXXXXXX" "viXXXXXXXXXX" "emacs" -offset indent +.Bl -column "CommandXXXXXXXXXXXXXXXXXXXXXXXXXX" "viXXXXXXXXXX" "emacs" -offset indent .It Sy "Command" Ta Sy "vi" Ta Sy "emacs" .It Li "append-selection" Ta "" Ta "" .It Li "append-selection-and-cancel" Ta "A" Ta "" @@ -1067,8 +1067,10 @@ The following commands are supported in copy mode: .It Li "scroll-down" Ta "C-e" Ta "C-Down" .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 "C-r" -.It Li "search-forward <for>" Ta "/" Ta "C-s" +.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-forward-incremental <for>" Ta "" Ta "C-s" .It Li "search-reverse" Ta "N" Ta "N" .It Li "select-line" Ta "V" Ta "" .It Li "start-of-line" Ta "0" Ta "C-a" @@ -3730,7 +3732,7 @@ session option. Commands related to the status line are as follows: .Bl -tag -width Ds .It Xo Ic command-prompt -.Op Fl 1 +.Op Fl 1i .Op Fl I Ar inputs .Op Fl p Ar prompts .Op Fl t Ar target-client @@ -3780,6 +3782,9 @@ but any quotation marks are escaped. .Fl 1 makes the prompt only accept one key press, in this case the resulting input is a single character. +.Fl i +executes the command every time the prompt input changes instead of when the +user exits the command prompt. .Pp The following keys have a special meaning in the command prompt, depending on the value of the diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 61f50719edd..e0d6f860db6 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.683 2017/01/05 09:07:16 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.684 2017/01/06 11:57:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -1417,7 +1417,7 @@ struct client { char *prompt_string; struct utf8_data *prompt_buffer; size_t prompt_index; - int (*prompt_callbackfn)(void *, const char *); + int (*prompt_callbackfn)(void *, const char *, int); void (*prompt_freefn)(void *); void *prompt_data; u_int prompt_hindex; @@ -1425,6 +1425,7 @@ struct client { #define PROMPT_SINGLE 0x1 #define PROMPT_NUMERIC 0x2 +#define PROMPT_INCREMENTAL 0x4 int prompt_flags; struct session *session; @@ -1915,7 +1916,7 @@ void printflike(2, 3) status_message_set(struct client *, const char *, ...); void status_message_clear(struct client *); int status_message_redraw(struct client *); void status_prompt_set(struct client *, const char *, const char *, - int (*)(void *, const char *), void (*)(void *), void *, int); + int (*)(void *, const char *, int), void (*)(void *), void *, int); void status_prompt_clear(struct client *); int status_prompt_redraw(struct client *); int status_prompt_key(struct client *, key_code); diff --git a/usr.bin/tmux/window-copy.c b/usr.bin/tmux/window-copy.c index ff8850cd4b7..6554abcfec3 100644 --- a/usr.bin/tmux/window-copy.c +++ b/usr.bin/tmux/window-copy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window-copy.c,v 1.162 2017/01/05 09:07:16 nicm Exp $ */ +/* $OpenBSD: window-copy.c,v 1.163 2017/01/06 11:57:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -50,14 +50,15 @@ static int window_copy_search_lr(struct grid *, struct grid *, u_int *, static int window_copy_search_rl(struct grid *, struct grid *, u_int *, u_int, u_int, u_int, int); static int window_copy_search_marks(struct window_pane *, struct screen *); +static void window_copy_clear_marks(struct window_pane *); static void window_copy_move_left(struct screen *, u_int *, u_int *); static void window_copy_move_right(struct screen *, u_int *, u_int *); static int window_copy_is_lowercase(const char *); -static void window_copy_search_jump(struct window_pane *, struct grid *, +static int window_copy_search_jump(struct window_pane *, struct grid *, struct grid *, u_int, u_int, u_int, int, int, int); -static void window_copy_search(struct window_pane *, int, int); -static void window_copy_search_up(struct window_pane *, int); -static void window_copy_search_down(struct window_pane *, int); +static int window_copy_search(struct window_pane *, int, int); +static int window_copy_search_up(struct window_pane *, int); +static int window_copy_search_down(struct window_pane *, int); static void window_copy_goto_line(struct window_pane *, const char *); static void window_copy_update_cursor(struct window_pane *, u_int, u_int); static void window_copy_start_selection(struct window_pane *); @@ -173,6 +174,9 @@ struct window_copy_mode_data { int searchtype; char *searchstr; bitstr_t *searchmark; + int searchx; + int searchy; + int searcho; int jumptype; char jumpchar; @@ -203,6 +207,7 @@ window_copy_init(struct window_pane *wp) data->searchtype = WINDOW_COPY_OFF; data->searchstr = NULL; data->searchmark = NULL; + data->searchx = data->searchy = data->searcho = -1; if (wp->fd != -1) bufferevent_disable(wp->event, EV_READ|EV_WRITE); @@ -487,6 +492,9 @@ window_copy_resize(struct window_pane *wp, u_int sx, u_int sy) if (data->searchmark != NULL) window_copy_search_marks(wp, NULL); + data->searchx = data->cx; + data->searchy = data->cy; + data->searcho = data->oy; window_copy_redraw_screen(wp); } @@ -507,7 +515,8 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, struct screen *sn = &data->screen; const char *command, *argument, *ws; u_int np = wp->modeprefix; - int cancel = 0; + int cancel = 0, redraw = 0; + char prefix; if (args->argc == 0) return; @@ -521,13 +530,13 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, if (s != NULL) window_copy_append_selection(wp, NULL); window_copy_clear_selection(wp); - window_copy_redraw_screen(wp); + redraw = 1; } if (strcmp(command, "append-selection-and-cancel") == 0) { if (s != NULL) window_copy_append_selection(wp, NULL); window_copy_clear_selection(wp); - window_copy_redraw_screen(wp); + redraw = 1; cancel = 1; } if (strcmp(command, "back-to-indentation") == 0) @@ -538,7 +547,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, else { sn->sel.lineflag = LINE_SEL_NONE; window_copy_start_selection(wp); - window_copy_redraw_screen(wp); + redraw = 1; } } if (strcmp(command, "stop-selection") == 0) @@ -547,20 +556,20 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, data->cx = 0; data->cy = screen_size_y(sn) - 1; window_copy_update_selection(wp, 1); - window_copy_redraw_screen(wp); + redraw = 1; } if (strcmp(command, "cancel") == 0) cancel = 1; if (strcmp(command, "clear-selection") == 0) { window_copy_clear_selection(wp); - window_copy_redraw_screen(wp); + redraw = 1; } if (strcmp(command, "copy-end-of-line") == 0) { window_copy_start_selection(wp); for (; np > 1; np--) window_copy_cursor_down(wp, 0); window_copy_cursor_end_of_line(wp); - window_copy_redraw_screen(wp); + redraw = 1; if (s != NULL) { window_copy_copy_selection(wp, NULL); @@ -573,7 +582,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, for (; np > 1; np--) window_copy_cursor_down(wp, 0); window_copy_cursor_end_of_line(wp); - window_copy_redraw_screen(wp); + redraw = 1; if (s != NULL) { window_copy_copy_selection(wp, NULL); @@ -584,13 +593,13 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, if (s != NULL) window_copy_copy_selection(wp, NULL); window_copy_clear_selection(wp); - window_copy_redraw_screen(wp); + redraw = 1; } if (strcmp(command, "copy-selection-and-cancel") == 0) { if (s != NULL) window_copy_copy_selection(wp, NULL); window_copy_clear_selection(wp); - window_copy_redraw_screen(wp); + redraw = 1; cancel = 1; } if (strcmp(command, "cursor-down") == 0) { @@ -624,14 +633,14 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, data->cy = screen_size_y(sn) - 1; data->oy = 0; window_copy_update_selection(wp, 1); - window_copy_redraw_screen(wp); + redraw = 1; } if (strcmp(command, "history-top") == 0) { data->cx = 0; data->cy = 0; data->oy = screen_hsize(data->backing); window_copy_update_selection(wp, 1); - window_copy_redraw_screen(wp); + redraw = 1; } if (strcmp(command, "jump-again") == 0) { switch (data->jumptype) { @@ -677,7 +686,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, data->cx = 0; data->cy = (screen_size_y(sn) - 1) / 2; window_copy_update_selection(wp, 1); - window_copy_redraw_screen(wp); + redraw = 1; } if (strcmp(command, "next-paragraph") == 0) { for (; np != 0; np--) @@ -766,7 +775,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, for (; np > 1; np--) window_copy_cursor_down(wp, 0); window_copy_cursor_end_of_line(wp); - window_copy_redraw_screen(wp); + redraw = 1; } if (strcmp(command, "select-word") == 0) { sn->sel.lineflag = LINE_SEL_LEFT_RIGHT; @@ -775,7 +784,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, window_copy_cursor_previous_word(wp, ws); window_copy_start_selection(wp); window_copy_cursor_next_word_end(wp, ws); - window_copy_redraw_screen(wp); + redraw = 1; } if (strcmp(command, "start-of-line") == 0) window_copy_cursor_start_of_line(wp); @@ -783,7 +792,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, data->cx = 0; data->cy = 0; window_copy_update_selection(wp, 1); - window_copy_redraw_screen(wp); + redraw = 1; } } else if (args->argc == 2 && *args->argv[1] != '\0') { argument = args->argv[1]; @@ -825,26 +834,98 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, } if (strcmp(command, "search-backward") == 0) { data->searchtype = WINDOW_COPY_SEARCHUP; + free(data->searchstr); data->searchstr = xstrdup(argument); for (; np != 0; np--) window_copy_search_up(wp, 1); } if (strcmp(command, "search-forward") == 0) { data->searchtype = WINDOW_COPY_SEARCHDOWN; + free(data->searchstr); data->searchstr = xstrdup(argument); for (; np != 0; np--) window_copy_search_down(wp, 1); } + if (strcmp(command, "search-backward-incremental") == 0) { + prefix = *argument++; + if (data->searchx == -1 || data->searchy == -1) { + data->searchx = data->cx; + data->searchy = data->cy; + data->searcho = data->oy; + } else if (data->searchstr != NULL && + strcmp(argument, data->searchstr) != 0) { + data->cx = data->searchx; + data->cy = data->searchy; + data->oy = data->searcho; + redraw = 1; + } + if (*argument == '\0') { + window_copy_clear_marks(wp); + redraw = 1; + } else if (prefix == '=' || prefix == '-') { + data->searchtype = WINDOW_COPY_SEARCHUP; + free(data->searchstr); + data->searchstr = xstrdup(argument); + if (!window_copy_search_up(wp, 1)) { + window_copy_clear_marks(wp); + redraw = 1; + } + } else if (prefix == '+') { + data->searchtype = WINDOW_COPY_SEARCHDOWN; + free(data->searchstr); + data->searchstr = xstrdup(argument); + if (!window_copy_search_down(wp, 1)) { + window_copy_clear_marks(wp); + redraw = 1; + } + } + } + if (strcmp(command, "search-forward-incremental") == 0) { + prefix = *argument++; + if (data->searchx == -1 || data->searchy == -1) { + data->searchx = data->cx; + data->searchy = data->cy; + data->searcho = data->oy; + } else if (data->searchstr != NULL && + strcmp(argument, data->searchstr) != 0) { + data->cx = data->searchx; + data->cy = data->searchy; + data->oy = data->searcho; + redraw = 1; + } + if (*argument == '\0') { + window_copy_clear_marks(wp); + redraw = 1; + } else if (prefix == '=' || prefix == '+') { + data->searchtype = WINDOW_COPY_SEARCHDOWN; + free(data->searchstr); + data->searchstr = xstrdup(argument); + if (!window_copy_search_down(wp, 1)) { + window_copy_clear_marks(wp); + redraw = 1; + } + } else if (prefix == '-') { + data->searchtype = WINDOW_COPY_SEARCHUP; + free(data->searchstr); + data->searchstr = xstrdup(argument); + if (!window_copy_search_up(wp, 1)) { + window_copy_clear_marks(wp); + redraw = 1; + } + } + } } if (strncmp(command, "search-", 7) != 0 && data->searchmark != NULL) { - free(data->searchmark); - data->searchmark = NULL; - window_copy_redraw_screen(wp); + window_copy_clear_marks(wp); + redraw = 1; + data->searchx = data->searchy = -1; } if (cancel) window_pane_reset_mode(wp); + else if (redraw) + window_copy_redraw_screen(wp); wp->modeprefix = 1; } @@ -986,7 +1067,7 @@ window_copy_is_lowercase(const char *ptr) * up, down otherwise. If wrap then go to begin/end of grid and try again if * not found. */ -static void +static int window_copy_search_jump(struct window_pane *wp, struct grid *gd, struct grid *sgd, u_int fx, u_int fy, u_int endline, int cis, int wrap, int direction) @@ -1015,13 +1096,17 @@ window_copy_search_jump(struct window_pane *wp, struct grid *gd, } } - if (found) + if (found) { window_copy_scroll_to(wp, px, i); - else if (wrap) { - window_copy_search_jump(wp, gd, sgd, direction ? 0 : gd->sx - 1, + return (1); + } + if (wrap) { + return (window_copy_search_jump(wp, gd, sgd, + direction ? 0 : gd->sx - 1, direction ? 0 : gd->hsize + gd->sy - 1, fy, cis, 0, - direction); + direction)); } + return (0); } /* @@ -1029,7 +1114,7 @@ window_copy_search_jump(struct window_pane *wp, struct grid *gd, * down. If moveflag is 0 then look for string at the current cursor position * as well. */ -static void +static int window_copy_search(struct window_pane *wp, int direction, int moveflag) { struct window_copy_mode_data *data = wp->modedata; @@ -1037,7 +1122,7 @@ window_copy_search(struct window_pane *wp, int direction, int moveflag) struct screen_write_ctx ctx; struct grid *gd = s->grid; u_int fx, fy, endline; - int wrapflag, cis; + int wrapflag, cis, found; fx = data->cx; fy = screen_hsize(data->backing) - data->oy + data->cy; @@ -1062,13 +1147,14 @@ window_copy_search(struct window_pane *wp, int direction, int moveflag) endline = gd->hsize + gd->sy - 1; else endline = 0; - window_copy_search_jump(wp, gd, ss.grid, fx, fy, endline, cis, + found = window_copy_search_jump(wp, gd, ss.grid, fx, fy, endline, cis, wrapflag, direction); if (window_copy_search_marks(wp, &ss)) window_copy_redraw_screen(wp); screen_free(&ss); + return (found); } static int @@ -1119,15 +1205,24 @@ window_copy_search_marks(struct window_pane *wp, struct screen *ssp) } static void +window_copy_clear_marks(struct window_pane *wp) +{ + struct window_copy_mode_data *data = wp->modedata; + + free(data->searchmark); + data->searchmark = NULL; +} + +static int window_copy_search_up(struct window_pane *wp, int moveflag) { - window_copy_search(wp, 0, moveflag); + return (window_copy_search(wp, 0, moveflag)); } -static void +static int window_copy_search_down(struct window_pane *wp, int moveflag) { - window_copy_search(wp, 1, moveflag); + return (window_copy_search(wp, 1, moveflag)); } static void |