Add a -T flag to capture-pane to stop at the last used cell instead of
authornicm <nicm@openbsd.org>
Wed, 28 Sep 2022 07:55:29 +0000 (07:55 +0000)
committernicm <nicm@openbsd.org>
Wed, 28 Sep 2022 07:55:29 +0000 (07:55 +0000)
the full width. Restore the previous behaviour by making it default to
off unless -J is used (the only time it matters). Fixes mosh unit tests;
GitHub issue 3339.

usr.bin/tmux/cmd-capture-pane.c
usr.bin/tmux/grid-view.c
usr.bin/tmux/grid.c
usr.bin/tmux/tmux.1
usr.bin/tmux/tmux.h

index dd88bbd..25051b8 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-capture-pane.c,v 1.58 2022/07/06 07:36:36 nicm Exp $ */
+/* $OpenBSD: cmd-capture-pane.c,v 1.59 2022/09/28 07:55:29 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Jonathan Alvarado <radobobo@users.sourceforge.net>
@@ -40,7 +40,7 @@ const struct cmd_entry cmd_capture_pane_entry = {
        .alias = "capturep",
 
        .args = { "ab:CeE:JNpPqS:t:", 0, 0, NULL },
-       .usage = "[-aCeJNpPq] " CMD_BUFFER_USAGE " [-E end-line] "
+       .usage = "[-aCeJNpPqT] " CMD_BUFFER_USAGE " [-E end-line] "
                 "[-S start-line] " CMD_TARGET_PANE_USAGE,
 
        .target = { 't', CMD_FIND_PANE, 0 },
@@ -110,7 +110,7 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
        struct grid             *gd;
        const struct grid_line  *gl;
        struct grid_cell        *gc = NULL;
-       int                      n, with_codes, escape_c0, join_lines, no_trim;
+       int                      n, join_lines, flags = 0;
        u_int                    i, sx, top, bottom, tmp;
        char                    *cause, *buf, *line;
        const char              *Sflag, *Eflag;
@@ -169,15 +169,19 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
                top = tmp;
        }
 
-       with_codes = args_has(args, 'e');
-       escape_c0 = args_has(args, 'C');
        join_lines = args_has(args, 'J');
-       no_trim = args_has(args, 'N');
+       if (args_has(args, 'e'))
+               flags |= GRID_STRING_WITH_SEQUENCES;
+       if (args_has(args, 'C'))
+               flags |= GRID_STRING_ESCAPE_SEQUENCES;
+       if (!join_lines && !args_has(args, 'T'))
+               flags |= GRID_STRING_EMPTY_CELLS;
+       if (!join_lines && !args_has(args, 'N'))
+               flags |= GRID_STRING_TRIM_SPACES;
 
        buf = NULL;
        for (i = top; i <= bottom; i++) {
-               line = grid_string_cells(gd, 0, i, sx, &gc, with_codes,
-                   escape_c0, !join_lines && !no_trim, wp->screen);
+               line = grid_string_cells(gd, 0, i, sx, &gc, flags, wp->screen);
                linelen = strlen(line);
 
                buf = cmd_capture_pane_append(buf, len, line, linelen);
index 053b104..f13b27c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: grid-view.c,v 1.35 2022/07/06 07:36:36 nicm Exp $ */
+/* $OpenBSD: grid-view.c,v 1.36 2022/09/28 07:55:29 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -231,5 +231,5 @@ grid_view_string_cells(struct grid *gd, u_int px, u_int py, u_int nx)
        px = grid_view_x(gd, px);
        py = grid_view_y(gd, py);
 
-       return (grid_string_cells(gd, px, py, nx, NULL, 0, 0, 0, NULL));
+       return (grid_string_cells(gd, px, py, nx, NULL, 0, NULL));
 }
index a9f276b..552a88e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: grid.c,v 1.126 2022/07/06 07:36:36 nicm Exp $ */
+/* $OpenBSD: grid.c,v 1.127 2022/09/28 07:55:29 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -861,40 +861,45 @@ grid_string_cells_us(const struct grid_cell *gc, int *values)
 /* Add on SGR code. */
 static void
 grid_string_cells_add_code(char *buf, size_t len, u_int n, int *s, int *newc,
-    int *oldc, size_t nnewc, size_t noldc, int escape_c0)
+    int *oldc, size_t nnewc, size_t noldc, int flags)
 {
        u_int   i;
        char    tmp[64];
-
-       if (nnewc != 0 &&
-           (nnewc != noldc ||
-           memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0 ||
-           (n != 0 && s[0] == 0))) {
-               if (escape_c0)
-                       strlcat(buf, "\\033[", len);
+       int     reset = (n != 0 && s[0] == 0);
+
+       if (nnewc == 0)
+               return; /* no code to add */
+       if (!reset &&
+           nnewc == noldc &&
+           memcmp(newc, oldc, nnewc * sizeof newc[0]) == 0)
+               return; /* no reset and colour unchanged */
+       if (reset && (newc[0] == 49 || newc[0] == 39))
+               return; /* reset and colour default */
+
+       if (flags & GRID_STRING_ESCAPE_SEQUENCES)
+               strlcat(buf, "\\033[", len);
+       else
+               strlcat(buf, "\033[", len);
+       for (i = 0; i < nnewc; i++) {
+               if (i + 1 < nnewc)
+                       xsnprintf(tmp, sizeof tmp, "%d;", newc[i]);
                else
-                       strlcat(buf, "\033[", len);
-               for (i = 0; i < nnewc; i++) {
-                       if (i + 1 < nnewc)
-                               xsnprintf(tmp, sizeof tmp, "%d;", newc[i]);
-                       else
-                               xsnprintf(tmp, sizeof tmp, "%d", newc[i]);
-                       strlcat(buf, tmp, len);
-               }
-               strlcat(buf, "m", len);
+                       xsnprintf(tmp, sizeof tmp, "%d", newc[i]);
+               strlcat(buf, tmp, len);
        }
+       strlcat(buf, "m", len);
 }
 
 static int
 grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id,
-    const char *uri, int escape_c0)
+    const char *uri, int flags)
 {
        char    *tmp;
 
        if (strlen(uri) + strlen(id) + 17 >= len)
                return (0);
 
-       if (escape_c0)
+       if (flags & GRID_STRING_ESCAPE_SEQUENCES)
                strlcat(buf, "\\033]8;", len);
        else
                strlcat(buf, "\033]8;", len);
@@ -905,7 +910,7 @@ grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id,
        } else
                strlcat(buf, ";", len);
        strlcat(buf, uri, len);
-       if (escape_c0)
+       if (flags & GRID_STRING_ESCAPE_SEQUENCES)
                strlcat(buf, "\\033\\\\", len);
        else
                strlcat(buf, "\033\\", len);
@@ -918,7 +923,7 @@ grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id,
  */
 static void
 grid_string_cells_code(const struct grid_cell *lastgc,
-    const struct grid_cell *gc, char *buf, size_t len, int escape_c0,
+    const struct grid_cell *gc, char *buf, size_t len, int flags,
     struct screen *sc, int *has_link)
 {
        int                      oldc[64], newc[64], s[128];
@@ -927,7 +932,7 @@ grid_string_cells_code(const struct grid_cell *lastgc,
        char                     tmp[64];
        const char              *uri, *id;
 
-       struct {
+       static const struct {
                u_int   mask;
                u_int   code;
        } attrs[] = {
@@ -966,7 +971,7 @@ grid_string_cells_code(const struct grid_cell *lastgc,
        /* Write the attributes. */
        *buf = '\0';
        if (n > 0) {
-               if (escape_c0)
+               if (flags & GRID_STRING_ESCAPE_SEQUENCES)
                        strlcat(buf, "\\033[", len);
                else
                        strlcat(buf, "\033[", len);
@@ -988,29 +993,29 @@ grid_string_cells_code(const struct grid_cell *lastgc,
        nnewc = grid_string_cells_fg(gc, newc);
        noldc = grid_string_cells_fg(lastgc, oldc);
        grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc,
-           escape_c0);
+           flags);
 
        /* If the background colour changed, append its parameters. */
        nnewc = grid_string_cells_bg(gc, newc);
        noldc = grid_string_cells_bg(lastgc, oldc);
        grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc,
-           escape_c0);
+           flags);
 
        /* If the underscore colour changed, append its parameters. */
        nnewc = grid_string_cells_us(gc, newc);
        noldc = grid_string_cells_us(lastgc, oldc);
        grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc,
-           escape_c0);
+           flags);
 
        /* Append shift in/shift out if needed. */
        if ((attr & GRID_ATTR_CHARSET) && !(lastattr & GRID_ATTR_CHARSET)) {
-               if (escape_c0)
+               if (flags & GRID_STRING_ESCAPE_SEQUENCES)
                        strlcat(buf, "\\016", len); /* SO */
                else
                        strlcat(buf, "\016", len);  /* SO */
        }
        if (!(attr & GRID_ATTR_CHARSET) && (lastattr & GRID_ATTR_CHARSET)) {
-               if (escape_c0)
+               if (flags & GRID_STRING_ESCAPE_SEQUENCES)
                        strlcat(buf, "\\017", len); /* SI */
                else
                        strlcat(buf, "\017", len);  /* SI */
@@ -1020,10 +1025,10 @@ grid_string_cells_code(const struct grid_cell *lastgc,
        if (sc != NULL && sc->hyperlinks != NULL && lastgc->link != gc->link) {
                if (hyperlinks_get(sc->hyperlinks, gc->link, &uri, &id, NULL)) {
                        *has_link = grid_string_cells_add_hyperlink(buf, len,
-                           id, uri, escape_c0);
+                           id, uri, flags);
                } else if (*has_link) {
                        grid_string_cells_add_hyperlink(buf, len, "", "",
-                           escape_c0);
+                           flags);
                        *has_link = 0;
                }
        }
@@ -1032,15 +1037,14 @@ grid_string_cells_code(const struct grid_cell *lastgc,
 /* Convert cells into a string. */
 char *
 grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
-    struct grid_cell **lastgc, int with_codes, int escape_c0, int trim,
-    struct screen *s)
+    struct grid_cell **lastgc, int flags, struct screen *s)
 {
        struct grid_cell         gc;
        static struct grid_cell  lastgc1;
        const char              *data;
        char                    *buf, code[8192];
        size_t                   len, off, size, codelen;
-       u_int                    xx, has_link = 0;
+       u_int                    xx, has_link = 0, end;
        const struct grid_line  *gl;
 
        if (lastgc != NULL && *lastgc == NULL) {
@@ -1053,16 +1057,20 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
        off = 0;
 
        gl = grid_peek_line(gd, py);
+       if (flags & GRID_STRING_EMPTY_CELLS)
+               end = gl->cellsize;
+       else
+               end = gl->cellused;
        for (xx = px; xx < px + nx; xx++) {
-               if (gl == NULL || xx >= gl->cellused)
+               if (gl == NULL || xx >= end)
                        break;
                grid_get_cell(gd, xx, py, &gc);
                if (gc.flags & GRID_FLAG_PADDING)
                        continue;
 
-               if (with_codes) {
+               if (flags & GRID_STRING_WITH_SEQUENCES) {
                        grid_string_cells_code(*lastgc, &gc, code, sizeof code,
-                           escape_c0, s, &has_link);
+                           flags, s, &has_link);
                        codelen = strlen(code);
                        memcpy(*lastgc, &gc, sizeof **lastgc);
                } else
@@ -1070,7 +1078,9 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
 
                data = gc.data.data;
                size = gc.data.size;
-               if (escape_c0 && size == 1 && *data == '\\') {
+               if ((flags & GRID_STRING_ESCAPE_SEQUENCES) &&
+                   size == 1 &&
+                   *data == '\\') {
                        data = "\\\\";
                        size = 2;
                }
@@ -1090,7 +1100,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
 
        if (has_link) {
                grid_string_cells_add_hyperlink(code, sizeof code, "", "",
-                   escape_c0);
+                   flags);
                codelen = strlen(code);
                while (len < off + size + codelen + 1) {
                        buf = xreallocarray(buf, 2, len);
@@ -1100,7 +1110,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
                off += codelen;
        }
 
-       if (trim) {
+       if (flags & GRID_STRING_TRIM_SPACES) {
                while (off > 0 && buf[off - 1] == ' ')
                        off--;
        }
index 40d77cd..8e4dac4 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.901 2022/09/09 11:02:23 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.902 2022/09/28 07:55:29 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: September 9 2022 $
+.Dd $Mdocdate: September 28 2022 $
 .Dt TMUX 1
 .Os
 .Sh NAME
@@ -2011,7 +2011,7 @@ but a different format may be specified with
 .Fl F .
 .Tg capturep
 .It Xo Ic capture-pane
-.Op Fl aepPqCJN
+.Op Fl aAepPqCJN
 .Op Fl b Ar buffer-name
 .Op Fl E Ar end-line
 .Op Fl S Ar start-line
@@ -2036,10 +2036,15 @@ is given, the output includes escape sequences for text and background
 attributes.
 .Fl C
 also escapes non-printable characters as octal \exxx.
+.Fl T
+ignores trailing positions that do not contain a character.
 .Fl N
 preserves trailing spaces at each line's end and
 .Fl J
-preserves trailing spaces and joins any wrapped lines.
+preserves trailing spaces and joins any wrapped lines;
+.Fl J
+implies
+.Fl T .
 .Fl P
 captures only any output that the pane has received that is the beginning of an
 as-yet incomplete escape sequence.
index 6e53865..8b1405e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.1181 2022/08/15 09:10:34 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.1182 2022/09/28 07:55:29 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -667,6 +667,14 @@ struct colour_palette {
 #define GRID_LINE_EXTENDED 0x2
 #define GRID_LINE_DEAD 0x4
 
+/* Grid string flags. */
+#define GRID_STRING_WITH_SEQUENCES 0x1
+#define GRID_STRING_ESCAPE_SEQUENCES 0x2
+#define GRID_STRING_TRIM_SPACES 0x4
+#define GRID_STRING_USED_ONLY 0x8
+#define GRID_STRING_EMPTY_CELLS 0x10
+
+/* Cell positions. */
 #define CELL_INSIDE 0
 #define CELL_TOPBOTTOM 1
 #define CELL_LEFTRIGHT 2
@@ -681,6 +689,7 @@ struct colour_palette {
 #define CELL_JOIN 11
 #define CELL_OUTSIDE 12
 
+/* Cell borders. */
 #define CELL_BORDERS " xqlkmjwvtun~"
 #define SIMPLE_BORDERS " |-+++++++++."
 #define PADDED_BORDERS "             "
@@ -2783,7 +2792,7 @@ void       grid_clear_lines(struct grid *, u_int, u_int, u_int);
 void    grid_move_lines(struct grid *, u_int, u_int, u_int, u_int);
 void    grid_move_cells(struct grid *, u_int, u_int, u_int, u_int, u_int);
 char   *grid_string_cells(struct grid *, u_int, u_int, u_int,
-            struct grid_cell **, int, int, int, struct screen *);
+            struct grid_cell **, int, struct screen *);
 void    grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int,
             u_int);
 void    grid_reflow(struct grid *, u_int);