Skip to content

Commit

Permalink
Let C-u M-! and C-u M-| insert the result in current buffer
Browse files Browse the repository at this point in the history
This change adds support for using the universal argument (C-u) with
shell-command (M-!) and shell-command-on-region (M-|) to insert the
result in the current buffer instead of opening a separate buffer for
the result.

Signed-off-by: Omar Polo <[email protected]>
Signed-off-by: Joachim Wiberg <[email protected]>
  • Loading branch information
omar-polo authored and troglobit committed Aug 2, 2024
1 parent cbd9a28 commit fbc84fc
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 68 deletions.
11 changes: 7 additions & 4 deletions doc/mg.1
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.\" $OpenBSD: mg.1,v 1.137 2024/06/04 06:48:34 op Exp $
.\" $OpenBSD: mg.1,v 1.138 2024/07/09 14:51:37 op Exp $
.\" This file is in the public domain.
.\"
.Dd $Mdocdate: June 4 2024 $
.Dd $Mdocdate: July 9 2024 $
.Dt MG 1
.Os
.Sh NAME
Expand Down Expand Up @@ -980,9 +980,12 @@ command.
Set the tab width for the current buffer, or the default for new buffers
if called with a prefix argument or from the startup file.
.It Ic shell-command
Execute external command from mini-buffer.
Execute external command from mini-buffer. With a universal argument
(C-u), this command inserts the output into the current buffer.
.It Ic shell-command-on-region
Provide the text in region to the shell command as input.
Provide the text in region to the shell command as input. With a
universal argument (C-u), this command replaces the marked region
with the output from the command.
.It Ic shrink-window
Shrink current window by one line.
The window immediately below is expanded to pick up the slack.
Expand Down
128 changes: 64 additions & 64 deletions src/region.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: region.c,v 1.44 2023/03/28 14:47:28 op Exp $ */
/* $OpenBSD: region.c,v 1.45 2024/07/09 14:46:17 op Exp $ */

/* This file is in the public domain. */

Expand Down Expand Up @@ -26,14 +26,13 @@

#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 int iomux(int, char * const, int);
static int preadin(int);
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.
Expand Down Expand Up @@ -413,13 +412,10 @@ int
piperegion(int f, int n)
{
struct region region;
struct buffer *bp = NULL;
int len;
char *cmd, cmdbuf[NFILEN], *text;

/* 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");
Expand All @@ -443,7 +439,14 @@ piperegion(int f, int n)

region_get_data(&region, text, len);

return shellcmdoutput(cmd, text, len);
if (n > 1) {
bp = curbp;
undo_boundary_enable(FFRAND, 0);
killregion(FFRAND, 1);
kdelete();
}

return (shellcmdoutput(cmd, text, len, bp));
}

/*
Expand All @@ -453,33 +456,51 @@ piperegion(int f, int n)
int
shellcommand(int f, int n)
{
struct buffer *bp = NULL;
char *cmd, cmdbuf[NFILEN];

if (n > 1)
return (ABORT);
bp = curbp;

if ((cmd = eread("Shell command: ", cmdbuf, sizeof(cmdbuf),
EFNEW | EFCR)) == NULL || (cmd[0] == '\0'))
return (ABORT);

return shellcmdoutput(cmd, NULL, 0);
return (shellcmdoutput(cmd, NULL, 0, bp));
}

int
shellcmdoutput(char* const cmd, char* const text, int len)
shellcmdoutput(char* const cmd, char* const text, int len,
struct buffer *bp)
{
struct buffer *bp;
struct mgwin *wp;
struct line *tlp;
char *argv[] = {NULL, "-c", cmd, NULL};
char *shellp;
int ret;
int tbo, ret, special = 0;

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;
}

bp = bfind("*Shell Command Output*", TRUE);
bp->b_flag |= BFREADONLY;
if (bclear(bp) != TRUE) {
free(text);
if (bp->b_flag & BFREADONLY) {
dobeep();
ewprintf("Buffer is read-only");
return (FALSE);
}

tlp = curwp->w_dotp; /* save current position */
tbo = curwp->w_doto;

if ((shellp = getenv("SHELL")) == NULL)
shellp = _PATH_BSHELL;

Expand All @@ -489,14 +510,21 @@ shellcmdoutput(char* const cmd, char* const text, int len)
argv[0] = shellp;

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 */
gotobob(0, 0);
} else {
curwp->w_dotp = tlp; /* return to old position */
curwp->w_doto = tbo;
}
return (ret);
}

Expand Down Expand Up @@ -539,7 +567,11 @@ pipeio(const char* const path, char* const argv[], char* const text, int len,
default:
/* Parent process */
close(s[1]);
ret = iomux(s[0], text, len, outbp);

undo_boundary_enable(FFRAND, 0);
ret = iomux(s[0], text, len);
undo_boundary_enable(FFRAND, 1);

waitpid(pid, NULL, 0); /* Collect child to prevent zombies */

return (ret);
Expand All @@ -552,7 +584,7 @@ pipeio(const char* const path, char* const argv[], char* const text, int len,
* Poll on the fd for both read and write readiness.
*/
int
iomux(int fd, char* const text, int len, struct buffer *outbp)
iomux(int fd, char* const text, int len)
{
struct pollfd pfd[1];
int nfds;
Expand All @@ -577,20 +609,13 @@ iomux(int fd, char* const text, int len, struct buffer *outbp)
if (pfd[0].revents & POLLOUT && len > 0)
pwriteout(fd, &textcopy, &len);
else if (pfd[0].revents & POLLIN)
if (preadin(fd, outbp) == FALSE)
if (preadin(fd) == FALSE)
break;
if (len == 0 && pfd[0].events & POLLOUT)
pfd[0].events = POLLIN;
}
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");
Expand All @@ -600,7 +625,7 @@ iomux(int fd, char* const text, int len, struct buffer *outbp)
ewprintf("poll error");
return (FALSE);
}
return (popbuftop(outbp, WNONE));
return (TRUE);
}

/*
Expand Down Expand Up @@ -634,42 +659,17 @@ 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)
preadin(int fd)
{
int len;
char buf[BUFSIZ], *p, *q;
char buf[BUFSIZ];
ssize_t len;

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);
}
addline(bp, leftover);
leftover[0] = '\0';
p = q;
}
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);
}
region_put_data(buf, len);
return (TRUE);
}

0 comments on commit fbc84fc

Please sign in to comment.