friendly 12 week ping :) On 2022/12/15 09:19:27 +0100, Omar Polo <o...@openbsd.org> wrote: > > > > On 2022/10/13 12:25:00 +0200, Omar Polo <o...@omarpolo.com> wrote: > > > > > shell-command (M-!) and shell-command-on-region (M-|) works by > > > > > displaying the output of the command in a new buffer, but in emacs > > > > > using a prefix argument (C-u) allows to operate on the current buffer. > > > > > > > > > > diff belows adds that for mg. I can finally C-u M-! got diff RET when > > > > > composing mails :) > > > > > > > > > > A possible drawback is that now the *Shell Command Output* buffer > > > > > gains an undo history. linsert is also possibly slower than addline > > > > > but on the plus side we're no more limited to BUFSIZ long lines. > > > > > > > > > > ok/comments/improvements? > > > > > > > > Here's a slightly tweaked version that adds a missing parens around a > > > > return value and uses ssize_t for some vars in preadin. it also changes > > > > the size read(2) from BUFSIZ-1 to BUFSIZ since we no longer need to NUL > > > > terminate it. > > > > > > > > This has been more useful than I originally expected. I wanted it to > > > > include diffs and the like more easily, now i'm using it also for all > > > > sorts of stuff that mg doesn't do out-of-the-box (like using C-u M-| > > > > sort RET instead of M-x sort-lines.) > > > > > > > > If it were for me, M-| and M-! would operate by default on the buffer > > > > and with C-u on a scratch one, but this is what emacs does and i'm > > > > probably several decades too late :)
diffstat /home/op/w/mg M region.c | 50+ 59- 1 file changed, 50 insertions(+), 59 deletions(-) diff /home/op/w/mg commit - 4e440c72920f8bfbe8fe8a752bd5eafff5c4c644 path + /home/op/w/mg blob - 21c5174f52d21103b9cd15942620eb746b5069b2 file + region.c --- region.c +++ region.c @@ -26,14 +26,13 @@ static char leftover[BUFSIZ]; #define TIMEOUT 10000 -static char leftover[BUFSIZ]; - static int getregion(struct region *); static int iomux(int, char * const, int, struct buffer *); static int preadin(int, struct buffer *); static void pwriteout(int, char **, int *); static int setsize(struct region *, RSIZE); -static int shellcmdoutput(char * const[], char * const, int); +static int shellcmdoutput(char * const[], char * const, int, + struct buffer *); /* * Kill the region. Ask "getregion" to figure out the bounds of the region. @@ -419,14 +418,11 @@ piperegion(int f, int n) piperegion(int f, int n) { struct region region; + struct buffer *bp = NULL; int len; char *cmd, cmdbuf[NFILEN], *text; char *argv[] = {"sh", "-c", (char *) NULL, (char *) NULL}; - /* C-u M-| is not supported yet */ - if (n > 1) - return (ABORT); - if (curwp->w_markp == NULL) { dobeep(); ewprintf("The mark is not set now, so there is no region"); @@ -452,7 +448,13 @@ piperegion(int f, int n) region_get_data(®ion, text, len); - return shellcmdoutput(argv, text, len); + if (n > 1) { + bp = curbp; + killregion(FFRAND, 1); + kdelete(); + } + + return (shellcmdoutput(argv, text, len, bp)); } /* @@ -462,12 +464,12 @@ shellcommand(int f, int n) int shellcommand(int f, int n) { - + struct buffer *bp = NULL; char *cmd, cmdbuf[NFILEN]; char *argv[] = {"sh", "-c", (char *) NULL, (char *) NULL}; if (n > 1) - return (ABORT); + bp = curbp; if ((cmd = eread("Shell command: ", cmdbuf, sizeof(cmdbuf), EFNEW | EFCR)) == NULL || (cmd[0] == '\0')) @@ -475,36 +477,43 @@ shellcommand(int f, int n) argv[2] = cmd; - return shellcmdoutput(argv, NULL, 0); + return (shellcmdoutput(argv, NULL, 0, bp)); } - int -shellcmdoutput(char* const argv[], char* const text, int len) +shellcmdoutput(char* const argv[], char* const text, int len, + struct buffer *bp) { - - struct buffer *bp; + struct mgwin *wp; char *shellp; - int ret; + int ret, special = 0; - bp = bfind("*Shell Command Output*", TRUE); - bp->b_flag |= BFREADONLY; - if (bclear(bp) != TRUE) { - free(text); - return (FALSE); + if (bp == NULL) { + special = 1; + bp = bfind("*Shell Command Output*", TRUE); + bp->b_flag &= ~BFREADONLY; /* disable read-only */ + wp = popbuf(bp, WNONE); + if (wp == NULL || bclear(bp) != TRUE) { + free(text); + return (FALSE); + } + curbp = bp; + curwp = wp; } shellp = getenv("SHELL"); ret = pipeio(shellp, argv, text, len, bp); - if (ret == TRUE) { eerase(); - if (lforw(bp->b_headp) == bp->b_headp) + if (special && lforw(bp->b_headp) == bp->b_headp) addline(bp, "(Shell command succeeded with no output)"); } free(text); + + if (special) + bp->b_flag |= BFREADONLY; /* restore read-only */ return (ret); } @@ -551,7 +560,11 @@ pipeio(const char* const path, char* const argv[], cha default: /* Parent process */ close(s[1]); + + undo_boundary_enable(FFRAND, 0); ret = iomux(s[0], text, len, outbp); + undo_boundary_enable(FFRAND, 1); + waitpid(pid, NULL, 0); /* Collect child to prevent zombies */ return (ret); @@ -596,13 +609,6 @@ iomux(int fd, char* const text, int len, struct buffer } close(fd); - /* In case if last line doesn't have a '\n' add the leftover - * characters to buffer. - */ - if (leftover[0] != '\0') { - addline(outbp, leftover); - leftover[0] = '\0'; - } if (nfds == 0) { dobeep(); ewprintf("poll timed out"); @@ -612,7 +618,7 @@ iomux(int fd, char* const text, int len, struct buffer ewprintf("poll error"); return (FALSE); } - return (popbuftop(outbp, WNONE)); + return (TRUE); } /* @@ -641,42 +647,27 @@ pwriteout(int fd, char **text, int *len) } /* - * Read some data from socket fd, break on '\n' and add - * to buffer. If couldn't break on newline hold leftover - * characters and append in next iteration. + * Read some data from socket fd and add to buffer. */ int preadin(int fd, struct buffer *bp) { - int len; - char buf[BUFSIZ], *p, *q; + char buf[BUFSIZ]; + ssize_t len, i; + int ret; - if ((len = read(fd, buf, BUFSIZ - 1)) <= 0) + if ((len = read(fd, buf, BUFSIZ)) <= 0) return (FALSE); - buf[len] = '\0'; - p = q = buf; - if (leftover[0] != '\0' && ((q = strchr(p, *bp->b_nlchr)) != NULL)) { - *q++ = '\0'; - if (strlcat(leftover, p, sizeof(leftover)) >= - sizeof(leftover)) { - dobeep(); - ewprintf("line too long"); - return (FALSE); + for (i = 0; i < len; ++i) { + if (buf[i] == *bp->b_nlchr) { + if ((ret = lnewline()) != TRUE) + return (ret); + continue; } - addline(bp, leftover); - leftover[0] = '\0'; - p = q; + + if ((ret = linsert(1, buf[i])) != TRUE) + return (ret); } - while ((q = strchr(p, *bp->b_nlchr)) != NULL) { - *q++ = '\0'; - addline(bp, p); - p = q; - } - if (strlcpy(leftover, p, sizeof(leftover)) >= sizeof(leftover)) { - dobeep(); - ewprintf("line too long"); - return (FALSE); - } return (TRUE); }