friendly 12 week ping :)
On 2022/12/15 09:19:27 +0100, Omar Polo <[email protected]> wrote:
> > > > On 2022/10/13 12:25:00 +0200, Omar Polo <[email protected]> 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);
}