mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Expand arguments to some commands where it makes sense, GitHub issue
3204 from Anindya Mukherjee.
This commit is contained in:
		
							
								
								
									
										102
									
								
								arguments.c
									
									
									
									
									
								
							
							
						
						
									
										102
									
								
								arguments.c
									
									
									
									
									
								
							@@ -848,6 +848,41 @@ args_strtonum(struct args *args, u_char flag, long long minval,
 | 
				
			|||||||
	return (ll);
 | 
						return (ll);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Convert an argument value to a number, and expand formats. */
 | 
				
			||||||
 | 
					long long
 | 
				
			||||||
 | 
					args_strtonum_and_expand(struct args *args, u_char flag, long long minval,
 | 
				
			||||||
 | 
					    long long maxval, struct cmdq_item *item, char **cause)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char		*errstr;
 | 
				
			||||||
 | 
						char			*formatted;
 | 
				
			||||||
 | 
						long long		 ll;
 | 
				
			||||||
 | 
						struct args_entry	*entry;
 | 
				
			||||||
 | 
						struct args_value	*value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((entry = args_find(args, flag)) == NULL) {
 | 
				
			||||||
 | 
							*cause = xstrdup("missing");
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						value = TAILQ_LAST(&entry->values, args_values);
 | 
				
			||||||
 | 
						if (value == NULL ||
 | 
				
			||||||
 | 
						    value->type != ARGS_STRING ||
 | 
				
			||||||
 | 
						    value->string == NULL) {
 | 
				
			||||||
 | 
							*cause = xstrdup("missing");
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						formatted = format_single_from_target(item, value->string);
 | 
				
			||||||
 | 
						ll = strtonum(formatted, minval, maxval, &errstr);
 | 
				
			||||||
 | 
						free(formatted);
 | 
				
			||||||
 | 
						if (errstr != NULL) {
 | 
				
			||||||
 | 
							*cause = xstrdup(errstr);
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*cause = NULL;
 | 
				
			||||||
 | 
						return (ll);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Convert an argument to a number which may be a percentage. */
 | 
					/* Convert an argument to a number which may be a percentage. */
 | 
				
			||||||
long long
 | 
					long long
 | 
				
			||||||
args_percentage(struct args *args, u_char flag, long long minval,
 | 
					args_percentage(struct args *args, u_char flag, long long minval,
 | 
				
			||||||
@@ -904,3 +939,70 @@ args_string_percentage(const char *value, long long minval, long long maxval,
 | 
				
			|||||||
	*cause = NULL;
 | 
						*cause = NULL;
 | 
				
			||||||
	return (ll);
 | 
						return (ll);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Convert an argument to a number which may be a percentage, and expand
 | 
				
			||||||
 | 
					 * formats.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					long long
 | 
				
			||||||
 | 
					args_percentage_and_expand(struct args *args, u_char flag, long long minval,
 | 
				
			||||||
 | 
					    long long maxval, long long curval, struct cmdq_item *item, char **cause)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char		*value;
 | 
				
			||||||
 | 
						struct args_entry	*entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((entry = args_find(args, flag)) == NULL) {
 | 
				
			||||||
 | 
							*cause = xstrdup("missing");
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						value = TAILQ_LAST(&entry->values, args_values)->string;
 | 
				
			||||||
 | 
						return (args_string_percentage_and_expand(value, minval, maxval, curval,
 | 
				
			||||||
 | 
							    item, cause));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Convert a string to a number which may be a percentage, and expand formats.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					long long
 | 
				
			||||||
 | 
					args_string_percentage_and_expand(const char *value, long long minval,
 | 
				
			||||||
 | 
					    long long maxval, long long curval, struct cmdq_item *item, char **cause)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char	*errstr;
 | 
				
			||||||
 | 
						long long	 ll;
 | 
				
			||||||
 | 
						size_t		 valuelen = strlen(value);
 | 
				
			||||||
 | 
						char		*copy, *f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (value[valuelen - 1] == '%') {
 | 
				
			||||||
 | 
							copy = xstrdup(value);
 | 
				
			||||||
 | 
							copy[valuelen - 1] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							f = format_single_from_target(item, copy);
 | 
				
			||||||
 | 
							ll = strtonum(f, 0, 100, &errstr);
 | 
				
			||||||
 | 
							free(f);
 | 
				
			||||||
 | 
							free(copy);
 | 
				
			||||||
 | 
							if (errstr != NULL) {
 | 
				
			||||||
 | 
								*cause = xstrdup(errstr);
 | 
				
			||||||
 | 
								return (0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ll = (curval * ll) / 100;
 | 
				
			||||||
 | 
							if (ll < minval) {
 | 
				
			||||||
 | 
								*cause = xstrdup("too small");
 | 
				
			||||||
 | 
								return (0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (ll > maxval) {
 | 
				
			||||||
 | 
								*cause = xstrdup("too large");
 | 
				
			||||||
 | 
								return (0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							f = format_single_from_target(item, value);
 | 
				
			||||||
 | 
							ll = strtonum(f, minval, maxval, &errstr);
 | 
				
			||||||
 | 
							free(f);
 | 
				
			||||||
 | 
							if (errstr != NULL) {
 | 
				
			||||||
 | 
								*cause = xstrdup(errstr);
 | 
				
			||||||
 | 
								return (0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*cause = NULL;
 | 
				
			||||||
 | 
						return (ll);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -133,7 +133,8 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
 | 
				
			|||||||
	if (Sflag != NULL && strcmp(Sflag, "-") == 0)
 | 
						if (Sflag != NULL && strcmp(Sflag, "-") == 0)
 | 
				
			||||||
		top = 0;
 | 
							top = 0;
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
 | 
							n = args_strtonum_and_expand(args, 'S', INT_MIN, SHRT_MAX,
 | 
				
			||||||
 | 
								item, &cause);
 | 
				
			||||||
		if (cause != NULL) {
 | 
							if (cause != NULL) {
 | 
				
			||||||
			top = gd->hsize;
 | 
								top = gd->hsize;
 | 
				
			||||||
			free(cause);
 | 
								free(cause);
 | 
				
			||||||
@@ -149,7 +150,8 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
 | 
				
			|||||||
	if (Eflag != NULL && strcmp(Eflag, "-") == 0)
 | 
						if (Eflag != NULL && strcmp(Eflag, "-") == 0)
 | 
				
			||||||
		bottom = gd->hsize + gd->sy - 1;
 | 
							bottom = gd->hsize + gd->sy - 1;
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
 | 
							n = args_strtonum_and_expand(args, 'E', INT_MIN, SHRT_MAX,
 | 
				
			||||||
 | 
								item, &cause);
 | 
				
			||||||
		if (cause != NULL) {
 | 
							if (cause != NULL) {
 | 
				
			||||||
			bottom = gd->hsize + gd->sy - 1;
 | 
								bottom = gd->hsize + gd->sy - 1;
 | 
				
			||||||
			free(cause);
 | 
								free(cause);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,10 +72,11 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
	struct window		*src_w, *dst_w;
 | 
						struct window		*src_w, *dst_w;
 | 
				
			||||||
	struct window_pane	*src_wp, *dst_wp;
 | 
						struct window_pane	*src_wp, *dst_wp;
 | 
				
			||||||
	char			*cause = NULL;
 | 
						char			*cause = NULL;
 | 
				
			||||||
	int			 size, percentage, dst_idx;
 | 
						int			 size, dst_idx;
 | 
				
			||||||
	int			 flags;
 | 
						int			 flags;
 | 
				
			||||||
	enum layout_type	 type;
 | 
						enum layout_type	 type;
 | 
				
			||||||
	struct layout_cell	*lc;
 | 
						struct layout_cell	*lc;
 | 
				
			||||||
 | 
						u_int			 curval = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dst_s = target->s;
 | 
						dst_s = target->s;
 | 
				
			||||||
	dst_wl = target->wl;
 | 
						dst_wl = target->wl;
 | 
				
			||||||
@@ -98,23 +99,30 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
	if (args_has(args, 'h'))
 | 
						if (args_has(args, 'h'))
 | 
				
			||||||
		type = LAYOUT_LEFTRIGHT;
 | 
							type = LAYOUT_LEFTRIGHT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* If the 'p' flag is dropped then this bit can be moved into 'l'. */
 | 
				
			||||||
 | 
						if (args_has(args, 'l') || args_has(args, 'p')) {
 | 
				
			||||||
 | 
							if (args_has(args, 'f')) {
 | 
				
			||||||
 | 
								if (type == LAYOUT_TOPBOTTOM)
 | 
				
			||||||
 | 
									curval = dst_w->sy;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									curval = dst_w->sx;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if (type == LAYOUT_TOPBOTTOM)
 | 
				
			||||||
 | 
									curval = dst_wp->sy;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									curval = dst_wp->sx;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	size = -1;
 | 
						size = -1;
 | 
				
			||||||
	if (args_has(args, 'l')) {
 | 
						if (args_has(args, 'l')) {
 | 
				
			||||||
		if (type == LAYOUT_TOPBOTTOM) {
 | 
							size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
 | 
				
			||||||
			size = args_percentage(args, 'l', 0, INT_MAX,
 | 
								   item, &cause);
 | 
				
			||||||
			    dst_wp->sy, &cause);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			size = args_percentage(args, 'l', 0, INT_MAX,
 | 
					 | 
				
			||||||
			    dst_wp->sx, &cause);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else if (args_has(args, 'p')) {
 | 
						} else if (args_has(args, 'p')) {
 | 
				
			||||||
		percentage = args_strtonum(args, 'p', 0, 100, &cause);
 | 
							size = args_strtonum_and_expand(args, 'l', 0, 100, item,
 | 
				
			||||||
		if (cause == NULL) {
 | 
								   &cause);
 | 
				
			||||||
			if (type == LAYOUT_TOPBOTTOM)
 | 
							if (cause == NULL)
 | 
				
			||||||
				size = (dst_wp->sy * percentage) / 100;
 | 
								size = curval * size / 100;
 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				size = (dst_wp->sx * percentage) / 100;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (cause != NULL) {
 | 
						if (cause != NULL) {
 | 
				
			||||||
		cmdq_error(item, "size %s", cause);
 | 
							cmdq_error(item, "size %s", cause);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -151,7 +151,8 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
	char				*cause = NULL;
 | 
						char				*cause = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (args_has(args, 'N')) {
 | 
						if (args_has(args, 'N')) {
 | 
				
			||||||
		np = args_strtonum(args, 'N', 1, UINT_MAX, &cause);
 | 
							np = args_strtonum_and_expand(args, 'N', 1, UINT_MAX, item,
 | 
				
			||||||
 | 
								 &cause);
 | 
				
			||||||
		if (cause != NULL) {
 | 
							if (cause != NULL) {
 | 
				
			||||||
			cmdq_error(item, "repeat count %s", cause);
 | 
								cmdq_error(item, "repeat count %s", cause);
 | 
				
			||||||
			free(cause);
 | 
								free(cause);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -66,67 +66,46 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
	enum layout_type	 type;
 | 
						enum layout_type	 type;
 | 
				
			||||||
	struct layout_cell	*lc;
 | 
						struct layout_cell	*lc;
 | 
				
			||||||
	struct cmd_find_state	 fs;
 | 
						struct cmd_find_state	 fs;
 | 
				
			||||||
	int			 size, percentage, flags, input;
 | 
						int			 size, flags, input;
 | 
				
			||||||
	const char		*template, *errstr, *p;
 | 
						const char		*template;
 | 
				
			||||||
	char			*cause, *cp, *copy;
 | 
						char			*cause = NULL, *cp;
 | 
				
			||||||
	size_t			 plen;
 | 
					 | 
				
			||||||
	struct args_value	*av;
 | 
						struct args_value	*av;
 | 
				
			||||||
	u_int			 count = args_count(args);
 | 
						u_int			 count = args_count(args), curval = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						type = LAYOUT_TOPBOTTOM;
 | 
				
			||||||
	if (args_has(args, 'h'))
 | 
						if (args_has(args, 'h'))
 | 
				
			||||||
		type = LAYOUT_LEFTRIGHT;
 | 
							type = LAYOUT_LEFTRIGHT;
 | 
				
			||||||
	else
 | 
					
 | 
				
			||||||
		type = LAYOUT_TOPBOTTOM;
 | 
						/* If the 'p' flag is dropped then this bit can be moved into 'l'. */
 | 
				
			||||||
	if ((p = args_get(args, 'l')) != NULL) {
 | 
						if (args_has(args, 'l') || args_has(args, 'p')) {
 | 
				
			||||||
		plen = strlen(p);
 | 
					 | 
				
			||||||
		if (p[plen - 1] == '%') {
 | 
					 | 
				
			||||||
			copy = xstrdup(p);
 | 
					 | 
				
			||||||
			copy[plen - 1] = '\0';
 | 
					 | 
				
			||||||
			percentage = strtonum(copy, 0, INT_MAX, &errstr);
 | 
					 | 
				
			||||||
			free(copy);
 | 
					 | 
				
			||||||
			if (errstr != NULL) {
 | 
					 | 
				
			||||||
				cmdq_error(item, "percentage %s", errstr);
 | 
					 | 
				
			||||||
				return (CMD_RETURN_ERROR);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		if (args_has(args, 'f')) {
 | 
							if (args_has(args, 'f')) {
 | 
				
			||||||
			if (type == LAYOUT_TOPBOTTOM)
 | 
								if (type == LAYOUT_TOPBOTTOM)
 | 
				
			||||||
					size = (w->sy * percentage) / 100;
 | 
									curval = w->sy;
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
					size = (w->sx * percentage) / 100;
 | 
									curval = w->sx;
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			if (type == LAYOUT_TOPBOTTOM)
 | 
								if (type == LAYOUT_TOPBOTTOM)
 | 
				
			||||||
					size = (wp->sy * percentage) / 100;
 | 
									curval = wp->sy;
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
					size = (wp->sx * percentage) / 100;
 | 
									curval = wp->sx;
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
 | 
					 | 
				
			||||||
			if (cause != NULL) {
 | 
					 | 
				
			||||||
				cmdq_error(item, "lines %s", cause);
 | 
					 | 
				
			||||||
				free(cause);
 | 
					 | 
				
			||||||
				return (CMD_RETURN_ERROR);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	} else if (args_has(args, 'p')) {
 | 
					
 | 
				
			||||||
		percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause);
 | 
					 | 
				
			||||||
		if (cause != NULL) {
 | 
					 | 
				
			||||||
			cmdq_error(item, "create pane failed: -p %s", cause);
 | 
					 | 
				
			||||||
			free(cause);
 | 
					 | 
				
			||||||
			return (CMD_RETURN_ERROR);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (args_has(args, 'f')) {
 | 
					 | 
				
			||||||
			if (type == LAYOUT_TOPBOTTOM)
 | 
					 | 
				
			||||||
				size = (w->sy * percentage) / 100;
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				size = (w->sx * percentage) / 100;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			if (type == LAYOUT_TOPBOTTOM)
 | 
					 | 
				
			||||||
				size = (wp->sy * percentage) / 100;
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				size = (wp->sx * percentage) / 100;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else
 | 
					 | 
				
			||||||
	size = -1;
 | 
						size = -1;
 | 
				
			||||||
 | 
						if (args_has(args, 'l')) {
 | 
				
			||||||
 | 
							size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
 | 
				
			||||||
 | 
								   item, &cause);
 | 
				
			||||||
 | 
						} else if (args_has(args, 'p')) {
 | 
				
			||||||
 | 
							size = args_strtonum_and_expand(args, 'l', 0, 100, item,
 | 
				
			||||||
 | 
								    &cause);
 | 
				
			||||||
 | 
							if (cause == NULL)
 | 
				
			||||||
 | 
								size = curval * size / 100;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (cause != NULL) {
 | 
				
			||||||
 | 
							cmdq_error(item, "size %s", cause);
 | 
				
			||||||
 | 
							free(cause);
 | 
				
			||||||
 | 
							return (CMD_RETURN_ERROR);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	window_push_zoom(wp->window, 1, args_has(args, 'Z'));
 | 
						window_push_zoom(wp->window, 1, args_has(args, 'Z'));
 | 
				
			||||||
	input = (args_has(args, 'I') && count == 0);
 | 
						input = (args_has(args, 'I') && count == 0);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								tmux.h
									
									
									
									
									
								
							@@ -2383,10 +2383,16 @@ struct args_value *args_first_value(struct args *, u_char);
 | 
				
			|||||||
struct args_value *args_next_value(struct args_value *);
 | 
					struct args_value *args_next_value(struct args_value *);
 | 
				
			||||||
long long	 args_strtonum(struct args *, u_char, long long, long long,
 | 
					long long	 args_strtonum(struct args *, u_char, long long, long long,
 | 
				
			||||||
		     char **);
 | 
							     char **);
 | 
				
			||||||
 | 
					long long	 args_strtonum_and_expand(struct args *, u_char, long long,
 | 
				
			||||||
 | 
							     long long, struct cmdq_item *, char **);
 | 
				
			||||||
long long	 args_percentage(struct args *, u_char, long long,
 | 
					long long	 args_percentage(struct args *, u_char, long long,
 | 
				
			||||||
		     long long, long long, char **);
 | 
							     long long, long long, char **);
 | 
				
			||||||
long long	 args_string_percentage(const char *, long long, long long,
 | 
					long long	 args_string_percentage(const char *, long long, long long,
 | 
				
			||||||
		     long long, char **);
 | 
							     long long, char **);
 | 
				
			||||||
 | 
					long long	 args_percentage_and_expand(struct args *, u_char, long long,
 | 
				
			||||||
 | 
							     long long, long long, struct cmdq_item *, char **);
 | 
				
			||||||
 | 
					long long	 args_string_percentage_and_expand(const char *, long long,
 | 
				
			||||||
 | 
							     long long, long long, struct cmdq_item *, char **);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* cmd-find.c */
 | 
					/* cmd-find.c */
 | 
				
			||||||
int		 cmd_find_target(struct cmd_find_state *, struct cmdq_item *,
 | 
					int		 cmd_find_target(struct cmd_find_state *, struct cmdq_item *,
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user