mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 01:34:18 +00:00 
			
		
		
		
	The repeat prompt in both emacs and vi (and the old one in tmux) doesn't
support line editing and instead executes a command as soon as a non-number key is pressed. Add a -N flag to command-prompt for the same in copy mode. Reported by Theo Buehler.
This commit is contained in:
		@@ -38,8 +38,8 @@ const struct cmd_entry cmd_command_prompt_entry = {
 | 
				
			|||||||
	.name = "command-prompt",
 | 
						.name = "command-prompt",
 | 
				
			||||||
	.alias = NULL,
 | 
						.alias = NULL,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.args = { "1I:p:t:", 0, 1 },
 | 
						.args = { "1I:Np:t:", 0, 1 },
 | 
				
			||||||
	.usage = "[-1] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
 | 
						.usage = "[-1N] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
 | 
				
			||||||
		 "[template]",
 | 
							 "[template]",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.tflag = CMD_CLIENT,
 | 
						.tflag = CMD_CLIENT,
 | 
				
			||||||
@@ -112,6 +112,8 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			|||||||
	flags = 0;
 | 
						flags = 0;
 | 
				
			||||||
	if (args_has(args, '1'))
 | 
						if (args_has(args, '1'))
 | 
				
			||||||
		flags |= PROMPT_SINGLE;
 | 
							flags |= PROMPT_SINGLE;
 | 
				
			||||||
 | 
						else if (args_has(args, 'N'))
 | 
				
			||||||
 | 
							flags |= PROMPT_NUMERIC;
 | 
				
			||||||
	status_prompt_set(c, prompt, input, cmd_command_prompt_callback,
 | 
						status_prompt_set(c, prompt, input, cmd_command_prompt_callback,
 | 
				
			||||||
	    cmd_command_prompt_free, cdata, flags);
 | 
						    cmd_command_prompt_free, cdata, flags);
 | 
				
			||||||
	free(prompt);
 | 
						free(prompt);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -271,15 +271,15 @@ key_bindings_init(void)
 | 
				
			|||||||
		"bind -Tcopy-mode Down send -X cursor-down",
 | 
							"bind -Tcopy-mode Down send -X cursor-down",
 | 
				
			||||||
		"bind -Tcopy-mode Left send -X cursor-left",
 | 
							"bind -Tcopy-mode Left send -X cursor-left",
 | 
				
			||||||
		"bind -Tcopy-mode Right send -X cursor-right",
 | 
							"bind -Tcopy-mode Right send -X cursor-right",
 | 
				
			||||||
		"bind -Tcopy-mode M-1 command-prompt -p'repeat' -I1 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode M-1 command-prompt -Np'repeat' -I1 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode M-2 command-prompt -p'repeat' -I2 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode M-2 command-prompt -Np'repeat' -I2 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode M-3 command-prompt -p'repeat' -I3 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode M-3 command-prompt -Np'repeat' -I3 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode M-4 command-prompt -p'repeat' -I4 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode M-4 command-prompt -Np'repeat' -I4 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode M-5 command-prompt -p'repeat' -I5 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode M-5 command-prompt -Np'repeat' -I5 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode M-6 command-prompt -p'repeat' -I6 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode M-6 command-prompt -Np'repeat' -I6 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode M-7 command-prompt -p'repeat' -I7 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode M-7 command-prompt -Np'repeat' -I7 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode M-8 command-prompt -p'repeat' -I8 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode M-8 command-prompt -Np'repeat' -I8 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode M-9 command-prompt -p'repeat' -I9 \"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-top",
 | 
				
			||||||
		"bind -Tcopy-mode M-> send -X history-bottom",
 | 
							"bind -Tcopy-mode M-> send -X history-bottom",
 | 
				
			||||||
		"bind -Tcopy-mode M-R send -X top-line",
 | 
							"bind -Tcopy-mode M-R send -X top-line",
 | 
				
			||||||
@@ -313,17 +313,17 @@ key_bindings_init(void)
 | 
				
			|||||||
		"bind -Tcopy-mode-vi , send -X jump-reverse",
 | 
							"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 0 send -X start-of-line",
 | 
				
			||||||
		"bind -Tcopy-mode-vi 1 command-prompt -p'repeat' -I1 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode-vi 1 command-prompt -Np'repeat' -I1 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode-vi 2 command-prompt -p'repeat' -I2 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode-vi 2 command-prompt -Np'repeat' -I2 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode-vi 3 command-prompt -p'repeat' -I3 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode-vi 3 command-prompt -Np'repeat' -I3 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode-vi 4 command-prompt -p'repeat' -I4 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode-vi 4 command-prompt -Np'repeat' -I4 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode-vi 5 command-prompt -p'repeat' -I5 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode-vi 5 command-prompt -Np'repeat' -I5 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode-vi 6 command-prompt -p'repeat' -I6 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode-vi 6 command-prompt -Np'repeat' -I6 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode-vi 7 command-prompt -p'repeat' -I7 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode-vi 7 command-prompt -Np'repeat' -I7 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode-vi 8 command-prompt -p'repeat' -I8 \"send -N '%%'\"",
 | 
							"bind -Tcopy-mode-vi 8 command-prompt -Np'repeat' -I8 \"send -N '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode-vi 9 command-prompt -p'repeat' -I9 \"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 : command-prompt -p'goto line' \"send -X goto-line '%%'\"",
 | 
				
			||||||
		"bind -Tcopy-mode-vi \\; send -X jump-again"
 | 
							"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 A send -X append-selection-and-cancel",
 | 
				
			||||||
		"bind -Tcopy-mode-vi B send -X previous-space",
 | 
							"bind -Tcopy-mode-vi B send -X previous-space",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -727,9 +727,10 @@ server_client_handle_key(struct client *c, key_code key)
 | 
				
			|||||||
		server_clear_identify(c, NULL);
 | 
							server_clear_identify(c, NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (c->prompt_string != NULL) {
 | 
						if (c->prompt_string != NULL) {
 | 
				
			||||||
		if (!(c->flags & CLIENT_READONLY))
 | 
							if (c->flags & CLIENT_READONLY)
 | 
				
			||||||
			status_prompt_key(c, key);
 | 
								return;
 | 
				
			||||||
		return;
 | 
							if (status_prompt_key(c, key) == 0)
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Check for mouse keys. */
 | 
						/* Check for mouse keys. */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										80
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										80
									
								
								status.c
									
									
									
									
									
								
							@@ -855,7 +855,7 @@ status_prompt_space(const struct utf8_data *ud)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Handle keys in prompt. */
 | 
					/* Handle keys in prompt. */
 | 
				
			||||||
void
 | 
					int
 | 
				
			||||||
status_prompt_key(struct client *c, key_code key)
 | 
					status_prompt_key(struct client *c, key_code key)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct options		*oo = c->session->options;
 | 
						struct options		*oo = c->session->options;
 | 
				
			||||||
@@ -867,6 +867,17 @@ status_prompt_key(struct client *c, key_code key)
 | 
				
			|||||||
	struct utf8_data	 tmp, *first, *last, *ud;
 | 
						struct utf8_data	 tmp, *first, *last, *ud;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	size = utf8_strlen(c->prompt_buffer);
 | 
						size = utf8_strlen(c->prompt_buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (c->prompt_flags & PROMPT_NUMERIC) {
 | 
				
			||||||
 | 
							if (key >= '0' && key <= '9')
 | 
				
			||||||
 | 
								goto append_key;
 | 
				
			||||||
 | 
							s = utf8_tocstr(c->prompt_buffer);
 | 
				
			||||||
 | 
							c->prompt_callbackfn(c->prompt_data, s);
 | 
				
			||||||
 | 
							status_prompt_clear(c);
 | 
				
			||||||
 | 
							free(s);
 | 
				
			||||||
 | 
							return (1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (mode_key_lookup(&c->prompt_mdata, key)) {
 | 
						switch (mode_key_lookup(&c->prompt_mdata, key)) {
 | 
				
			||||||
	case MODEKEYEDIT_CURSORLEFT:
 | 
						case MODEKEYEDIT_CURSORLEFT:
 | 
				
			||||||
		if (c->prompt_index > 0) {
 | 
							if (c->prompt_index > 0) {
 | 
				
			||||||
@@ -1185,41 +1196,44 @@ status_prompt_key(struct client *c, key_code key)
 | 
				
			|||||||
			status_prompt_clear(c);
 | 
								status_prompt_clear(c);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case MODEKEY_OTHER:
 | 
						case MODEKEY_OTHER:
 | 
				
			||||||
		if (key <= 0x1f || key >= KEYC_BASE)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		if (utf8_split(key, &tmp) != UTF8_DONE)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		c->prompt_buffer = xreallocarray(c->prompt_buffer, size + 2,
 | 
					 | 
				
			||||||
		    sizeof *c->prompt_buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (c->prompt_index == size) {
 | 
					 | 
				
			||||||
			utf8_copy(&c->prompt_buffer[c->prompt_index], &tmp);
 | 
					 | 
				
			||||||
			c->prompt_index++;
 | 
					 | 
				
			||||||
			c->prompt_buffer[c->prompt_index].size = 0;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			memmove(c->prompt_buffer + c->prompt_index + 1,
 | 
					 | 
				
			||||||
			    c->prompt_buffer + c->prompt_index,
 | 
					 | 
				
			||||||
			    (size + 1 - c->prompt_index) *
 | 
					 | 
				
			||||||
			    sizeof *c->prompt_buffer);
 | 
					 | 
				
			||||||
			utf8_copy(&c->prompt_buffer[c->prompt_index], &tmp);
 | 
					 | 
				
			||||||
			c->prompt_index++;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (c->prompt_flags & PROMPT_SINGLE) {
 | 
					 | 
				
			||||||
			s = utf8_tocstr(c->prompt_buffer);
 | 
					 | 
				
			||||||
			if (strlen(s) != 1)
 | 
					 | 
				
			||||||
				status_prompt_clear(c);
 | 
					 | 
				
			||||||
			else if (c->prompt_callbackfn(c->prompt_data, s) == 0)
 | 
					 | 
				
			||||||
				status_prompt_clear(c);
 | 
					 | 
				
			||||||
			free(s);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		c->flags |= CLIENT_STATUS;
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		break;
 | 
							return (0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					append_key:
 | 
				
			||||||
 | 
						if (key <= 0x1f || key >= KEYC_BASE)
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
						if (utf8_split(key, &tmp) != UTF8_DONE)
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c->prompt_buffer = xreallocarray(c->prompt_buffer, size + 2,
 | 
				
			||||||
 | 
						    sizeof *c->prompt_buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (c->prompt_index == size) {
 | 
				
			||||||
 | 
							utf8_copy(&c->prompt_buffer[c->prompt_index], &tmp);
 | 
				
			||||||
 | 
							c->prompt_index++;
 | 
				
			||||||
 | 
							c->prompt_buffer[c->prompt_index].size = 0;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							memmove(c->prompt_buffer + c->prompt_index + 1,
 | 
				
			||||||
 | 
							    c->prompt_buffer + c->prompt_index,
 | 
				
			||||||
 | 
							    (size + 1 - c->prompt_index) *
 | 
				
			||||||
 | 
							    sizeof *c->prompt_buffer);
 | 
				
			||||||
 | 
							utf8_copy(&c->prompt_buffer[c->prompt_index], &tmp);
 | 
				
			||||||
 | 
							c->prompt_index++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (c->prompt_flags & PROMPT_SINGLE) {
 | 
				
			||||||
 | 
							s = utf8_tocstr(c->prompt_buffer);
 | 
				
			||||||
 | 
							if (strlen(s) != 1)
 | 
				
			||||||
 | 
								status_prompt_clear(c);
 | 
				
			||||||
 | 
							else if (c->prompt_callbackfn(c->prompt_data, s) == 0)
 | 
				
			||||||
 | 
								status_prompt_clear(c);
 | 
				
			||||||
 | 
							free(s);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c->flags |= CLIENT_STATUS;
 | 
				
			||||||
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Get previous line from the history. */
 | 
					/* Get previous line from the history. */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								tmux.1
									
									
									
									
									
								
							@@ -3748,7 +3748,7 @@ session option.
 | 
				
			|||||||
Commands related to the status line are as follows:
 | 
					Commands related to the status line are as follows:
 | 
				
			||||||
.Bl -tag -width Ds
 | 
					.Bl -tag -width Ds
 | 
				
			||||||
.It Xo Ic command-prompt
 | 
					.It Xo Ic command-prompt
 | 
				
			||||||
.Op Fl 1
 | 
					.Op Fl 1N
 | 
				
			||||||
.Op Fl I Ar inputs
 | 
					.Op Fl I Ar inputs
 | 
				
			||||||
.Op Fl p Ar prompts
 | 
					.Op Fl p Ar prompts
 | 
				
			||||||
.Op Fl t Ar target-client
 | 
					.Op Fl t Ar target-client
 | 
				
			||||||
@@ -3802,6 +3802,8 @@ to
 | 
				
			|||||||
.Fl 1
 | 
					.Fl 1
 | 
				
			||||||
makes the prompt only accept one key press, in this case the resulting input
 | 
					makes the prompt only accept one key press, in this case the resulting input
 | 
				
			||||||
is a single character.
 | 
					is a single character.
 | 
				
			||||||
 | 
					.Fl N
 | 
				
			||||||
 | 
					accepts only numbers and exit the prompt on any other key press.
 | 
				
			||||||
.It Xo Ic confirm-before
 | 
					.It Xo Ic confirm-before
 | 
				
			||||||
.Op Fl p Ar prompt
 | 
					.Op Fl p Ar prompt
 | 
				
			||||||
.Op Fl t Ar target-client
 | 
					.Op Fl t Ar target-client
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1269,6 +1269,7 @@ struct client {
 | 
				
			|||||||
	u_int		 prompt_hindex;
 | 
						u_int		 prompt_hindex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PROMPT_SINGLE 0x1
 | 
					#define PROMPT_SINGLE 0x1
 | 
				
			||||||
 | 
					#define PROMPT_NUMERIC 0x2
 | 
				
			||||||
	int		 prompt_flags;
 | 
						int		 prompt_flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct mode_key_data prompt_mdata;
 | 
						struct mode_key_data prompt_mdata;
 | 
				
			||||||
@@ -1920,7 +1921,7 @@ void	 status_prompt_set(struct client *, const char *, const char *,
 | 
				
			|||||||
	     int (*)(void *, const char *), void (*)(void *), void *, int);
 | 
						     int (*)(void *, const char *), void (*)(void *), void *, int);
 | 
				
			||||||
void	 status_prompt_clear(struct client *);
 | 
					void	 status_prompt_clear(struct client *);
 | 
				
			||||||
int	 status_prompt_redraw(struct client *);
 | 
					int	 status_prompt_redraw(struct client *);
 | 
				
			||||||
void	 status_prompt_key(struct client *, key_code);
 | 
					int	 status_prompt_key(struct client *, key_code);
 | 
				
			||||||
void	 status_prompt_update(struct client *, const char *, const char *);
 | 
					void	 status_prompt_update(struct client *, const char *, const char *);
 | 
				
			||||||
void	 status_prompt_load_history(void);
 | 
					void	 status_prompt_load_history(void);
 | 
				
			||||||
void	 status_prompt_save_history(void);
 | 
					void	 status_prompt_save_history(void);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user