anyone?

On 2022/11/09 09:00:03 +0100, Omar Polo <o...@omarpolo.com> wrote:
> bump
> 
> On 2022/10/25 14:30:51 +0200, Omar Polo <o...@omarpolo.com> 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 :)


diff 214e94d3085276f4e5c6b416bfd54b5d50a7bf91 
cde294b6d4634ab98c7926103d373202007e23c2
commit - 214e94d3085276f4e5c6b416bfd54b5d50a7bf91
commit + cde294b6d4634ab98c7926103d373202007e23c2
blob - 21c5174f52d21103b9cd15942620eb746b5069b2
blob + 1bee60b37ceea3f9ec3ceb779727f877a7f15851
--- usr.bin/mg/region.c
+++ usr.bin/mg/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(&region, 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);
 }

Reply via email to