Skip to content

Commit fbc84fc

Browse files
omar-polotroglobit
authored andcommitted
Let C-u M-! and C-u M-| insert the result in current buffer
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]>
1 parent cbd9a28 commit fbc84fc

File tree

2 files changed

+71
-68
lines changed

2 files changed

+71
-68
lines changed

doc/mg.1

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
.\" $OpenBSD: mg.1,v 1.137 2024/06/04 06:48:34 op Exp $
1+
.\" $OpenBSD: mg.1,v 1.138 2024/07/09 14:51:37 op Exp $
22
.\" This file is in the public domain.
33
.\"
4-
.Dd $Mdocdate: June 4 2024 $
4+
.Dd $Mdocdate: July 9 2024 $
55
.Dt MG 1
66
.Os
77
.Sh NAME
@@ -980,9 +980,12 @@ command.
980980
Set the tab width for the current buffer, or the default for new buffers
981981
if called with a prefix argument or from the startup file.
982982
.It Ic shell-command
983-
Execute external command from mini-buffer.
983+
Execute external command from mini-buffer. With a universal argument
984+
(C-u), this command inserts the output into the current buffer.
984985
.It Ic shell-command-on-region
985-
Provide the text in region to the shell command as input.
986+
Provide the text in region to the shell command as input. With a
987+
universal argument (C-u), this command replaces the marked region
988+
with the output from the command.
986989
.It Ic shrink-window
987990
Shrink current window by one line.
988991
The window immediately below is expanded to pick up the slack.

src/region.c

+64-64
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: region.c,v 1.44 2023/03/28 14:47:28 op Exp $ */
1+
/* $OpenBSD: region.c,v 1.45 2024/07/09 14:46:17 op Exp $ */
22

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

@@ -26,14 +26,13 @@
2626

2727
#define TIMEOUT 10000
2828

29-
static char leftover[BUFSIZ];
30-
3129
static int getregion(struct region *);
32-
static int iomux(int, char * const, int, struct buffer *);
33-
static int preadin(int, struct buffer *);
30+
static int iomux(int, char * const, int);
31+
static int preadin(int);
3432
static void pwriteout(int, char **, int *);
3533
static int setsize(struct region *, RSIZE);
36-
static int shellcmdoutput(char * const, char * const, int);
34+
static int shellcmdoutput(char * const, char * const, int,
35+
struct buffer *);
3736

3837
/*
3938
* Kill the region. Ask "getregion" to figure out the bounds of the region.
@@ -413,13 +412,10 @@ int
413412
piperegion(int f, int n)
414413
{
415414
struct region region;
415+
struct buffer *bp = NULL;
416416
int len;
417417
char *cmd, cmdbuf[NFILEN], *text;
418418

419-
/* C-u M-| is not supported yet */
420-
if (n > 1)
421-
return (ABORT);
422-
423419
if (curwp->w_markp == NULL) {
424420
dobeep();
425421
ewprintf("The mark is not set now, so there is no region");
@@ -443,7 +439,14 @@ piperegion(int f, int n)
443439

444440
region_get_data(&region, text, len);
445441

446-
return shellcmdoutput(cmd, text, len);
442+
if (n > 1) {
443+
bp = curbp;
444+
undo_boundary_enable(FFRAND, 0);
445+
killregion(FFRAND, 1);
446+
kdelete();
447+
}
448+
449+
return (shellcmdoutput(cmd, text, len, bp));
447450
}
448451

449452
/*
@@ -453,33 +456,51 @@ piperegion(int f, int n)
453456
int
454457
shellcommand(int f, int n)
455458
{
459+
struct buffer *bp = NULL;
456460
char *cmd, cmdbuf[NFILEN];
457461

458462
if (n > 1)
459-
return (ABORT);
463+
bp = curbp;
460464

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

465-
return shellcmdoutput(cmd, NULL, 0);
469+
return (shellcmdoutput(cmd, NULL, 0, bp));
466470
}
467471

468472
int
469-
shellcmdoutput(char* const cmd, char* const text, int len)
473+
shellcmdoutput(char* const cmd, char* const text, int len,
474+
struct buffer *bp)
470475
{
471-
struct buffer *bp;
476+
struct mgwin *wp;
477+
struct line *tlp;
472478
char *argv[] = {NULL, "-c", cmd, NULL};
473479
char *shellp;
474-
int ret;
480+
int tbo, ret, special = 0;
481+
482+
if (bp == NULL) {
483+
special = 1;
484+
bp = bfind("*Shell Command Output*", TRUE);
485+
bp->b_flag &= ~BFREADONLY; /* disable read-only */
486+
wp = popbuf(bp, WNONE);
487+
if (wp == NULL || bclear(bp) != TRUE) {
488+
free(text);
489+
return (FALSE);
490+
}
491+
curbp = bp;
492+
curwp = wp;
493+
}
475494

476-
bp = bfind("*Shell Command Output*", TRUE);
477-
bp->b_flag |= BFREADONLY;
478-
if (bclear(bp) != TRUE) {
479-
free(text);
495+
if (bp->b_flag & BFREADONLY) {
496+
dobeep();
497+
ewprintf("Buffer is read-only");
480498
return (FALSE);
481499
}
482500

501+
tlp = curwp->w_dotp; /* save current position */
502+
tbo = curwp->w_doto;
503+
483504
if ((shellp = getenv("SHELL")) == NULL)
484505
shellp = _PATH_BSHELL;
485506

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

491512
ret = pipeio(shellp, argv, text, len, bp);
492-
493513
if (ret == TRUE) {
494514
eerase();
495-
if (lforw(bp->b_headp) == bp->b_headp)
515+
if (special && lforw(bp->b_headp) == bp->b_headp)
496516
addline(bp, "(Shell command succeeded with no output)");
497517
}
498518

499519
free(text);
520+
521+
if (special) {
522+
bp->b_flag |= BFREADONLY; /* restore read-only */
523+
gotobob(0, 0);
524+
} else {
525+
curwp->w_dotp = tlp; /* return to old position */
526+
curwp->w_doto = tbo;
527+
}
500528
return (ret);
501529
}
502530

@@ -539,7 +567,11 @@ pipeio(const char* const path, char* const argv[], char* const text, int len,
539567
default:
540568
/* Parent process */
541569
close(s[1]);
542-
ret = iomux(s[0], text, len, outbp);
570+
571+
undo_boundary_enable(FFRAND, 0);
572+
ret = iomux(s[0], text, len);
573+
undo_boundary_enable(FFRAND, 1);
574+
543575
waitpid(pid, NULL, 0); /* Collect child to prevent zombies */
544576

545577
return (ret);
@@ -552,7 +584,7 @@ pipeio(const char* const path, char* const argv[], char* const text, int len,
552584
* Poll on the fd for both read and write readiness.
553585
*/
554586
int
555-
iomux(int fd, char* const text, int len, struct buffer *outbp)
587+
iomux(int fd, char* const text, int len)
556588
{
557589
struct pollfd pfd[1];
558590
int nfds;
@@ -577,20 +609,13 @@ iomux(int fd, char* const text, int len, struct buffer *outbp)
577609
if (pfd[0].revents & POLLOUT && len > 0)
578610
pwriteout(fd, &textcopy, &len);
579611
else if (pfd[0].revents & POLLIN)
580-
if (preadin(fd, outbp) == FALSE)
612+
if (preadin(fd) == FALSE)
581613
break;
582614
if (len == 0 && pfd[0].events & POLLOUT)
583615
pfd[0].events = POLLIN;
584616
}
585617
close(fd);
586618

587-
/* In case if last line doesn't have a '\n' add the leftover
588-
* characters to buffer.
589-
*/
590-
if (leftover[0] != '\0') {
591-
addline(outbp, leftover);
592-
leftover[0] = '\0';
593-
}
594619
if (nfds == 0) {
595620
dobeep();
596621
ewprintf("poll timed out");
@@ -600,7 +625,7 @@ iomux(int fd, char* const text, int len, struct buffer *outbp)
600625
ewprintf("poll error");
601626
return (FALSE);
602627
}
603-
return (popbuftop(outbp, WNONE));
628+
return (TRUE);
604629
}
605630

606631
/*
@@ -634,42 +659,17 @@ pwriteout(int fd, char **text, int *len)
634659
}
635660

636661
/*
637-
* Read some data from socket fd, break on '\n' and add
638-
* to buffer. If couldn't break on newline hold leftover
639-
* characters and append in next iteration.
662+
* Read some data from socket fd and add to buffer.
640663
*/
641664
int
642-
preadin(int fd, struct buffer *bp)
665+
preadin(int fd)
643666
{
644-
int len;
645-
char buf[BUFSIZ], *p, *q;
667+
char buf[BUFSIZ];
668+
ssize_t len;
646669

647-
if ((len = read(fd, buf, BUFSIZ - 1)) <= 0)
670+
if ((len = read(fd, buf, BUFSIZ)) <= 0)
648671
return (FALSE);
649672

650-
buf[len] = '\0';
651-
p = q = buf;
652-
if (leftover[0] != '\0' && ((q = strchr(p, *bp->b_nlchr)) != NULL)) {
653-
*q++ = '\0';
654-
if (strlcat(leftover, p, sizeof(leftover)) >=
655-
sizeof(leftover)) {
656-
dobeep();
657-
ewprintf("line too long");
658-
return (FALSE);
659-
}
660-
addline(bp, leftover);
661-
leftover[0] = '\0';
662-
p = q;
663-
}
664-
while ((q = strchr(p, *bp->b_nlchr)) != NULL) {
665-
*q++ = '\0';
666-
addline(bp, p);
667-
p = q;
668-
}
669-
if (strlcpy(leftover, p, sizeof(leftover)) >= sizeof(leftover)) {
670-
dobeep();
671-
ewprintf("line too long");
672-
return (FALSE);
673-
}
673+
region_put_data(buf, len);
674674
return (TRUE);
675675
}

0 commit comments

Comments
 (0)