mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Add -W and -T flags to command-prompt to only complete a window and a
target, also complete aliases.
This commit is contained in:
		@@ -40,8 +40,8 @@ const struct cmd_entry cmd_command_prompt_entry = {
 | 
				
			|||||||
	.name = "command-prompt",
 | 
						.name = "command-prompt",
 | 
				
			||||||
	.alias = NULL,
 | 
						.alias = NULL,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.args = { "1kiI:Np:t:", 0, 1 },
 | 
						.args = { "1kiI:Np:Tt:W", 0, 1 },
 | 
				
			||||||
	.usage = "[-1kiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
 | 
						.usage = "[-1kiNTW] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
 | 
				
			||||||
		 "[template]",
 | 
							 "[template]",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.flags = CMD_CLIENT_TFLAG,
 | 
						.flags = CMD_CLIENT_TFLAG,
 | 
				
			||||||
@@ -121,6 +121,10 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
		cdata->flags |= PROMPT_INCREMENTAL;
 | 
							cdata->flags |= PROMPT_INCREMENTAL;
 | 
				
			||||||
	else if (args_has(args, 'k'))
 | 
						else if (args_has(args, 'k'))
 | 
				
			||||||
		cdata->flags |= PROMPT_KEY;
 | 
							cdata->flags |= PROMPT_KEY;
 | 
				
			||||||
 | 
						else if (args_has(args, 'W'))
 | 
				
			||||||
 | 
							cdata->flags |= PROMPT_WINDOW;
 | 
				
			||||||
 | 
						else if (args_has(args, 'T'))
 | 
				
			||||||
 | 
							cdata->flags |= PROMPT_TARGET;
 | 
				
			||||||
	status_prompt_set(tc, prompt, input, cmd_command_prompt_callback,
 | 
						status_prompt_set(tc, prompt, input, cmd_command_prompt_callback,
 | 
				
			||||||
	    cmd_command_prompt_free, cdata, cdata->flags);
 | 
						    cmd_command_prompt_free, cdata, cdata->flags);
 | 
				
			||||||
	free(prompt);
 | 
						free(prompt);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -243,12 +243,12 @@ key_bindings_init(void)
 | 
				
			|||||||
		"bind -N 'Rename current session' '$' command-prompt -I'#S' \"rename-session -- '%%'\"",
 | 
							"bind -N 'Rename current session' '$' command-prompt -I'#S' \"rename-session -- '%%'\"",
 | 
				
			||||||
		"bind -N 'Split window horizontally' % split-window -h",
 | 
							"bind -N 'Split window horizontally' % split-window -h",
 | 
				
			||||||
		"bind -N 'Kill current window' & confirm-before -p\"kill-window #W? (y/n)\" kill-window",
 | 
							"bind -N 'Kill current window' & confirm-before -p\"kill-window #W? (y/n)\" kill-window",
 | 
				
			||||||
		"bind -N 'Prompt for window index to select' \"'\" command-prompt -pindex \"select-window -t ':%%'\"",
 | 
							"bind -N 'Prompt for window index to select' \"'\" command-prompt -Wpindex \"select-window -t ':%%'\"",
 | 
				
			||||||
		"bind -N 'Switch to previous client' ( switch-client -p",
 | 
							"bind -N 'Switch to previous client' ( switch-client -p",
 | 
				
			||||||
		"bind -N 'Switch to next client' ) switch-client -n",
 | 
							"bind -N 'Switch to next client' ) switch-client -n",
 | 
				
			||||||
		"bind -N 'Rename current window' , command-prompt -I'#W' \"rename-window -- '%%'\"",
 | 
							"bind -N 'Rename current window' , command-prompt -I'#W' \"rename-window -- '%%'\"",
 | 
				
			||||||
		"bind -N 'Delete the most recent paste buffer' - delete-buffer",
 | 
							"bind -N 'Delete the most recent paste buffer' - delete-buffer",
 | 
				
			||||||
		"bind -N 'Move the current window' . command-prompt \"move-window -t '%%'\"",
 | 
							"bind -N 'Move the current window' . command-prompt -T \"move-window -t '%%'\"",
 | 
				
			||||||
		"bind -N 'Describe key binding' '/' command-prompt -kpkey 'list-keys -1N \"%%%\"'",
 | 
							"bind -N 'Describe key binding' '/' command-prompt -kpkey 'list-keys -1N \"%%%\"'",
 | 
				
			||||||
		"bind -N 'Select window 0' 0 select-window -t:=0",
 | 
							"bind -N 'Select window 0' 0 select-window -t:=0",
 | 
				
			||||||
		"bind -N 'Select window 1' 1 select-window -t:=1",
 | 
							"bind -N 'Select window 1' 1 select-window -t:=1",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										112
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								status.c
									
									
									
									
									
								
							@@ -38,6 +38,8 @@ static const char *status_prompt_down_history(u_int *);
 | 
				
			|||||||
static void	 status_prompt_add_history(const char *);
 | 
					static void	 status_prompt_add_history(const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char	*status_prompt_complete(struct client *, const char *, u_int);
 | 
					static char	*status_prompt_complete(struct client *, const char *, u_int);
 | 
				
			||||||
 | 
					static char	*status_prompt_complete_window_menu(struct client *,
 | 
				
			||||||
 | 
							     struct session *, u_int, char);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct status_prompt_menu {
 | 
					struct status_prompt_menu {
 | 
				
			||||||
	struct client	 *c;
 | 
						struct client	 *c;
 | 
				
			||||||
@@ -933,13 +935,11 @@ status_prompt_replace_complete(struct client *c, const char *s)
 | 
				
			|||||||
	size_t			 size, n, off, idx, used;
 | 
						size_t			 size, n, off, idx, used;
 | 
				
			||||||
	struct utf8_data	*first, *last, *ud;
 | 
						struct utf8_data	*first, *last, *ud;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c->prompt_buffer[0].size == 0)
 | 
						/* Work out where the cursor currently is. */
 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	size = utf8_strlen(c->prompt_buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	idx = c->prompt_index;
 | 
						idx = c->prompt_index;
 | 
				
			||||||
	if (idx != 0)
 | 
						if (idx != 0)
 | 
				
			||||||
		idx--;
 | 
							idx--;
 | 
				
			||||||
 | 
						size = utf8_strlen(c->prompt_buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Find the word we are in. */
 | 
						/* Find the word we are in. */
 | 
				
			||||||
	first = &c->prompt_buffer[idx];
 | 
						first = &c->prompt_buffer[idx];
 | 
				
			||||||
@@ -954,7 +954,7 @@ status_prompt_replace_complete(struct client *c, const char *s)
 | 
				
			|||||||
		last--;
 | 
							last--;
 | 
				
			||||||
	if (last->size != 0)
 | 
						if (last->size != 0)
 | 
				
			||||||
		last++;
 | 
							last++;
 | 
				
			||||||
	if (last <= first)
 | 
						if (last < first)
 | 
				
			||||||
		return (0);
 | 
							return (0);
 | 
				
			||||||
	if (s == NULL) {
 | 
						if (s == NULL) {
 | 
				
			||||||
		used = 0;
 | 
							used = 0;
 | 
				
			||||||
@@ -1071,7 +1071,15 @@ process_key:
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case '\011': /* Tab */
 | 
						case '\011': /* Tab */
 | 
				
			||||||
		if (status_prompt_replace_complete(c, NULL))
 | 
							if (c->prompt_flags & PROMPT_WINDOW) {
 | 
				
			||||||
 | 
								s = status_prompt_complete_window_menu(c, c->session,
 | 
				
			||||||
 | 
								    0, '\0');
 | 
				
			||||||
 | 
								if (s != NULL) {
 | 
				
			||||||
 | 
									free(c->prompt_buffer);
 | 
				
			||||||
 | 
									c->prompt_buffer = utf8_fromcstr(s);
 | 
				
			||||||
 | 
									c->prompt_index = utf8_strlen(c->prompt_buffer);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if (status_prompt_replace_complete(c, NULL))
 | 
				
			||||||
			goto changed;
 | 
								goto changed;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case KEYC_BSPACE:
 | 
						case KEYC_BSPACE:
 | 
				
			||||||
@@ -1376,6 +1384,11 @@ status_prompt_complete_list(u_int *size, const char *s, int at_start)
 | 
				
			|||||||
			list = xreallocarray(list, (*size) + 1, sizeof *list);
 | 
								list = xreallocarray(list, (*size) + 1, sizeof *list);
 | 
				
			||||||
			list[(*size)++] = xstrdup((*cmdent)->name);
 | 
								list[(*size)++] = xstrdup((*cmdent)->name);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if ((*cmdent)->alias != NULL &&
 | 
				
			||||||
 | 
							    strncmp((*cmdent)->alias, s, slen) == 0) {
 | 
				
			||||||
 | 
								list = xreallocarray(list, (*size) + 1, sizeof *list);
 | 
				
			||||||
 | 
								list[(*size)++] = xstrdup((*cmdent)->alias);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	o = options_get_only(global_options, "command-alias");
 | 
						o = options_get_only(global_options, "command-alias");
 | 
				
			||||||
	if (o != NULL) {
 | 
						if (o != NULL) {
 | 
				
			||||||
@@ -1450,7 +1463,12 @@ status_prompt_menu_callback(__unused struct menu *menu, u_int idx, key_code key,
 | 
				
			|||||||
			s = xstrdup(spm->list[idx]);
 | 
								s = xstrdup(spm->list[idx]);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			xasprintf(&s, "-%c%s", spm->flag, spm->list[idx]);
 | 
								xasprintf(&s, "-%c%s", spm->flag, spm->list[idx]);
 | 
				
			||||||
		if (status_prompt_replace_complete(c, s))
 | 
							if (c->prompt_flags & PROMPT_WINDOW) {
 | 
				
			||||||
 | 
								free(c->prompt_buffer);
 | 
				
			||||||
 | 
								c->prompt_buffer = utf8_fromcstr(s);
 | 
				
			||||||
 | 
								c->prompt_index = utf8_strlen(c->prompt_buffer);
 | 
				
			||||||
 | 
								c->flags |= CLIENT_REDRAWSTATUS;
 | 
				
			||||||
 | 
							} else if (status_prompt_replace_complete(c, s))
 | 
				
			||||||
			c->flags |= CLIENT_REDRAWSTATUS;
 | 
								c->flags |= CLIENT_REDRAWSTATUS;
 | 
				
			||||||
		free(s);
 | 
							free(s);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1544,10 +1562,14 @@ status_prompt_complete_window_menu(struct client *c, struct session *s,
 | 
				
			|||||||
	menu = menu_create("");
 | 
						menu = menu_create("");
 | 
				
			||||||
	RB_FOREACH(wl, winlinks, &s->windows) {
 | 
						RB_FOREACH(wl, winlinks, &s->windows) {
 | 
				
			||||||
		list = xreallocarray(list, size + 1, sizeof *list);
 | 
							list = xreallocarray(list, size + 1, sizeof *list);
 | 
				
			||||||
		xasprintf(&list[size++], "%s:%d", s->name, wl->idx);
 | 
							if (c->prompt_flags & PROMPT_WINDOW) {
 | 
				
			||||||
 | 
								xasprintf(&tmp, "%d (%s)", wl->idx, wl->window->name);
 | 
				
			||||||
		xasprintf(&tmp, "%s:%d (%s)", s->name, wl->idx,
 | 
								xasprintf(&list[size++], "%d", wl->idx);
 | 
				
			||||||
		    wl->window->name);
 | 
							} else {
 | 
				
			||||||
 | 
								xasprintf(&tmp, "%s:%d (%s)", s->name, wl->idx,
 | 
				
			||||||
 | 
								    wl->window->name);
 | 
				
			||||||
 | 
								xasprintf(&list[size++], "%s:%d", s->name, wl->idx);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		item.name = tmp;
 | 
							item.name = tmp;
 | 
				
			||||||
		item.key = '0' + size - 1;
 | 
							item.key = '0' + size - 1;
 | 
				
			||||||
		item.command = NULL;
 | 
							item.command = NULL;
 | 
				
			||||||
@@ -1559,8 +1581,11 @@ status_prompt_complete_window_menu(struct client *c, struct session *s,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	if (size == 1) {
 | 
						if (size == 1) {
 | 
				
			||||||
		menu_free(menu);
 | 
							menu_free(menu);
 | 
				
			||||||
		xasprintf(&tmp, "-%c%s", flag, list[0]);
 | 
							if (flag != '\0') {
 | 
				
			||||||
		free(list[0]);
 | 
								xasprintf(&tmp, "-%c%s", flag, list[0]);
 | 
				
			||||||
 | 
								free(list[0]);
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								tmp = list[0];
 | 
				
			||||||
		free(list);
 | 
							free(list);
 | 
				
			||||||
		return (tmp);
 | 
							return (tmp);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1598,21 +1623,45 @@ status_prompt_complete_sort(const void *a, const void *b)
 | 
				
			|||||||
	return (strcmp(*aa, *bb));
 | 
						return (strcmp(*aa, *bb));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Complete a session. */
 | 
				
			||||||
 | 
					static char *
 | 
				
			||||||
 | 
					status_prompt_complete_session(char ***list, u_int *size, const char *s,
 | 
				
			||||||
 | 
					    char flag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct session	*loop;
 | 
				
			||||||
 | 
						char		*out, *tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						RB_FOREACH(loop, sessions, &sessions) {
 | 
				
			||||||
 | 
							if (*s != '\0' && strncmp(loop->name, s, strlen(s)) != 0)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							*list = xreallocarray(*list, (*size) + 2, sizeof **list);
 | 
				
			||||||
 | 
							xasprintf(&(*list)[(*size)++], "%s:", loop->name);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out = status_prompt_complete_prefix(*list, *size);
 | 
				
			||||||
 | 
						if (out != NULL && flag != '\0') {
 | 
				
			||||||
 | 
							xasprintf(&tmp, "-%c%s", flag, out);
 | 
				
			||||||
 | 
							free(out);
 | 
				
			||||||
 | 
							out = tmp;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return (out);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Complete word. */
 | 
					/* Complete word. */
 | 
				
			||||||
static char *
 | 
					static char *
 | 
				
			||||||
status_prompt_complete(struct client *c, const char *word, u_int offset)
 | 
					status_prompt_complete(struct client *c, const char *word, u_int offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct session   *session, *loop;
 | 
						struct session   *session;
 | 
				
			||||||
	const char	 *s, *colon;
 | 
						const char	 *s, *colon;
 | 
				
			||||||
	size_t		  slen;
 | 
						char		**list = NULL, *copy = NULL, *out = NULL;
 | 
				
			||||||
	char		**list = NULL, *copy = NULL, *out = NULL, *tmp;
 | 
					 | 
				
			||||||
	char		  flag = '\0';
 | 
						char		  flag = '\0';
 | 
				
			||||||
	u_int		  size = 0, i;
 | 
						u_int		  size = 0, i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (*word == '\0')
 | 
						if (*word == '\0' && (~c->prompt_flags & PROMPT_TARGET))
 | 
				
			||||||
		return (NULL);
 | 
							return (NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (strncmp(word, "-t", 2) != 0 && strncmp(word, "-s", 2) != 0) {
 | 
						if ((~c->prompt_flags & PROMPT_TARGET) &&
 | 
				
			||||||
 | 
						    strncmp(word, "-t", 2) != 0 &&
 | 
				
			||||||
 | 
						    strncmp(word, "-s", 2) != 0) {
 | 
				
			||||||
		list = status_prompt_complete_list(&size, word, offset == 0);
 | 
							list = status_prompt_complete_list(&size, word, offset == 0);
 | 
				
			||||||
		if (size == 0)
 | 
							if (size == 0)
 | 
				
			||||||
			out = NULL;
 | 
								out = NULL;
 | 
				
			||||||
@@ -1623,28 +1672,19 @@ status_prompt_complete(struct client *c, const char *word, u_int offset)
 | 
				
			|||||||
		goto found;
 | 
							goto found;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s = word + 2;
 | 
						if (c->prompt_flags & PROMPT_TARGET) {
 | 
				
			||||||
	slen = strlen(s);
 | 
							s = word;
 | 
				
			||||||
 | 
							flag = '\0';
 | 
				
			||||||
	flag = word[1];
 | 
						} else {
 | 
				
			||||||
	offset += 2;
 | 
							s = word + 2;
 | 
				
			||||||
 | 
							flag = word[1];
 | 
				
			||||||
 | 
							offset += 2;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	colon = strchr(s, ':');
 | 
						colon = strchr(s, ':');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* If there is no colon, complete as a session. */
 | 
						/* If there is no colon, complete as a session. */
 | 
				
			||||||
	if (colon == NULL) {
 | 
						if (colon == NULL) {
 | 
				
			||||||
		RB_FOREACH(loop, sessions, &sessions) {
 | 
							out = status_prompt_complete_session(&list, &size, s, flag);
 | 
				
			||||||
			if (strncmp(loop->name, s, strlen(s)) != 0)
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			list = xreallocarray(list, size + 2, sizeof *list);
 | 
					 | 
				
			||||||
			xasprintf(&list[size++], "%s:", loop->name);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		out = status_prompt_complete_prefix(list, size);
 | 
					 | 
				
			||||||
		if (out != NULL) {
 | 
					 | 
				
			||||||
			xasprintf(&tmp, "-%c%s", flag, out);
 | 
					 | 
				
			||||||
			free(out);
 | 
					 | 
				
			||||||
			out = tmp;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		goto found;
 | 
							goto found;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								tmux.1
									
									
									
									
									
								
							@@ -4969,7 +4969,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 1ikN
 | 
					.Op Fl 1ikNTW
 | 
				
			||||||
.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
 | 
				
			||||||
@@ -5028,6 +5028,14 @@ makes the prompt only accept numeric key presses.
 | 
				
			|||||||
.Fl i
 | 
					.Fl i
 | 
				
			||||||
executes the command every time the prompt input changes instead of when the
 | 
					executes the command every time the prompt input changes instead of when the
 | 
				
			||||||
user exits the command prompt.
 | 
					user exits the command prompt.
 | 
				
			||||||
 | 
					.Fl T
 | 
				
			||||||
 | 
					tells
 | 
				
			||||||
 | 
					.Nm
 | 
				
			||||||
 | 
					that the prompt is for a target which affects what completions are offered when
 | 
				
			||||||
 | 
					.Em Tab
 | 
				
			||||||
 | 
					is pressed;
 | 
				
			||||||
 | 
					.Fl W
 | 
				
			||||||
 | 
					is similar but indicates the prompt is for a window.
 | 
				
			||||||
.Pp
 | 
					.Pp
 | 
				
			||||||
The following keys have a special meaning in the command prompt, depending
 | 
					The following keys have a special meaning in the command prompt, depending
 | 
				
			||||||
on the value of the
 | 
					on the value of the
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1602,6 +1602,8 @@ struct client {
 | 
				
			|||||||
#define PROMPT_INCREMENTAL 0x4
 | 
					#define PROMPT_INCREMENTAL 0x4
 | 
				
			||||||
#define PROMPT_NOFORMAT 0x8
 | 
					#define PROMPT_NOFORMAT 0x8
 | 
				
			||||||
#define PROMPT_KEY 0x10
 | 
					#define PROMPT_KEY 0x10
 | 
				
			||||||
 | 
					#define PROMPT_WINDOW 0x20
 | 
				
			||||||
 | 
					#define PROMPT_TARGET 0x40
 | 
				
			||||||
	int		 prompt_flags;
 | 
						int		 prompt_flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct session	*session;
 | 
						struct session	*session;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user