Expand arguments to some commands where it makes sense, GitHub issue
authornicm <nicm@openbsd.org>
Tue, 7 Jun 2022 10:02:19 +0000 (10:02 +0000)
committernicm <nicm@openbsd.org>
Tue, 7 Jun 2022 10:02:19 +0000 (10:02 +0000)
3204 from Anindya Mukherjee.

usr.bin/tmux/arguments.c
usr.bin/tmux/cmd-capture-pane.c
usr.bin/tmux/cmd-join-pane.c
usr.bin/tmux/cmd-send-keys.c
usr.bin/tmux/cmd-split-window.c
usr.bin/tmux/tmux.h

index 09f933c..5bac7fa 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: arguments.c,v 1.54 2022/05/30 13:04:24 nicm Exp $ */
+/* $OpenBSD: arguments.c,v 1.55 2022/06/07 10:02:19 nicm Exp $ */
 
 /*
  * Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -848,6 +848,41 @@ args_strtonum(struct args *args, u_char flag, long long minval,
        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. */
 long long
 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;
        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);
+}
index 74e4da3..b860886 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-capture-pane.c,v 1.55 2021/08/21 10:22:38 nicm Exp $ */
+/* $OpenBSD: cmd-capture-pane.c,v 1.56 2022/06/07 10:02:19 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Jonathan Alvarado <radobobo@users.sourceforge.net>
@@ -133,7 +133,8 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
        if (Sflag != NULL && strcmp(Sflag, "-") == 0)
                top = 0;
        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) {
                        top = gd->hsize;
                        free(cause);
@@ -149,7 +150,8 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
        if (Eflag != NULL && strcmp(Eflag, "-") == 0)
                bottom = gd->hsize + gd->sy - 1;
        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) {
                        bottom = gd->hsize + gd->sy - 1;
                        free(cause);
index a59dc9e..12549f2 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-join-pane.c,v 1.49 2021/08/21 10:22:39 nicm Exp $ */
+/* $OpenBSD: cmd-join-pane.c,v 1.50 2022/06/07 10:02:19 nicm Exp $ */
 
 /*
  * Copyright (c) 2011 George Nachman <tmux@georgester.com>
@@ -72,10 +72,11 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
        struct window           *src_w, *dst_w;
        struct window_pane      *src_wp, *dst_wp;
        char                    *cause = NULL;
-       int                      size, percentage, dst_idx;
+       int                      size, dst_idx;
        int                      flags;
        enum layout_type         type;
        struct layout_cell      *lc;
+       u_int                    curval = 0;
 
        dst_s = target->s;
        dst_wl = target->wl;
@@ -98,24 +99,31 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
        if (args_has(args, 'h'))
                type = LAYOUT_LEFTRIGHT;
 
-       size = -1;
-       if (args_has(args, 'l')) {
-               if (type == LAYOUT_TOPBOTTOM) {
-                       size = args_percentage(args, 'l', 0, INT_MAX,
-                           dst_wp->sy, &cause);
+       /* 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 {
-                       size = args_percentage(args, 'l', 0, INT_MAX,
-                           dst_wp->sx, &cause);
-               }
-       } else if (args_has(args, 'p')) {
-               percentage = args_strtonum(args, 'p', 0, 100, &cause);
-               if (cause == NULL) {
                        if (type == LAYOUT_TOPBOTTOM)
-                               size = (dst_wp->sy * percentage) / 100;
+                               curval = dst_wp->sy;
                        else
-                               size = (dst_wp->sx * percentage) / 100;
+                               curval = dst_wp->sx;
                }
        }
+
+       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);
index f86a284..4373f29 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-send-keys.c,v 1.71 2021/10/19 12:51:43 nicm Exp $ */
+/* $OpenBSD: cmd-send-keys.c,v 1.72 2022/06/07 10:02:19 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -151,7 +151,8 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
        char                            *cause = NULL;
 
        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) {
                        cmdq_error(item, "repeat count %s", cause);
                        free(cause);
index 0e33748..f961caf 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-split-window.c,v 1.112 2022/03/08 22:14:25 nicm Exp $ */
+/* $OpenBSD: cmd-split-window.c,v 1.113 2022/06/07 10:02:19 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -66,67 +66,46 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
        enum layout_type         type;
        struct layout_cell      *lc;
        struct cmd_find_state    fs;
-       int                      size, percentage, flags, input;
-       const char              *template, *errstr, *p;
-       char                    *cause, *cp, *copy;
-       size_t                   plen;
+       int                      size, flags, input;
+       const char              *template;
+       char                    *cause = NULL, *cp;
        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'))
                type = LAYOUT_LEFTRIGHT;
-       else
-               type = LAYOUT_TOPBOTTOM;
-       if ((p = args_get(args, 'l')) != NULL) {
-               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 (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 = 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 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)
-                               size = (w->sy * percentage) / 100;
+                               curval = w->sy;
                        else
-                               size = (w->sx * percentage) / 100;
+                               curval = w->sx;
                } else {
                        if (type == LAYOUT_TOPBOTTOM)
-                               size = (wp->sy * percentage) / 100;
+                               curval = wp->sy;
                        else
-                               size = (wp->sx * percentage) / 100;
+                               curval = wp->sx;
                }
-       } 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'));
        input = (args_has(args, 'I') && count == 0);
index cf497af..b6d495a 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.1171 2022/06/04 07:42:07 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.1172 2022/06/07 10:02:19 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -2383,10 +2383,16 @@ struct args_value *args_first_value(struct args *, u_char);
 struct args_value *args_next_value(struct args_value *);
 long long       args_strtonum(struct args *, u_char, long long, long long,
                     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, long long, char **);
 long long       args_string_percentage(const char *, long long, long long,
                     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 */
 int             cmd_find_target(struct cmd_find_state *, struct cmdq_item *,