From cccde189d91e9b3ab6fe8a3aa1f98da1b1af39d7 Mon Sep 17 00:00:00 2001 From: Vincent Labrecque Date: Fri, 15 Aug 2003 23:23:19 +0000 Subject: make dired work more like emacs. (well, make it _work_, and then add a bunch of missing commands) --- usr.bin/mg/buffer.c | 11 +- usr.bin/mg/def.h | 4 +- usr.bin/mg/dired.c | 277 +++++++++++++++++++++++++++++++++++++++++++++++---- usr.bin/mg/display.c | 3 +- usr.bin/mg/fileio.c | 14 +-- 5 files changed, 277 insertions(+), 32 deletions(-) (limited to 'usr.bin') diff --git a/usr.bin/mg/buffer.c b/usr.bin/mg/buffer.c index 3e57434de45..54ff40af09e 100644 --- a/usr.bin/mg/buffer.c +++ b/usr.bin/mg/buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: buffer.c,v 1.31 2003/06/26 23:04:10 vincent Exp $ */ +/* $OpenBSD: buffer.c,v 1.32 2003/08/15 23:23:18 vincent Exp $ */ /* * Buffer handling. @@ -434,7 +434,8 @@ bfind(const char *bname, int cflag) if (cflag != TRUE) return NULL; - if ((bp = malloc(sizeof(BUFFER))) == NULL) { + bp = calloc(1, sizeof(BUFFER)); + if (bp == NULL) { ewprintf("Can't get %d bytes", sizeof(BUFFER)); return NULL; } @@ -495,7 +496,7 @@ bclear(BUFFER *bp) bp->b_flag &= ~BFCHG; /* Not changed */ while ((lp = lforw(bp->b_linep)) != bp->b_linep) lfree(lp); - bp->b_dotp = bp->b_linep; /* Fix "." */ + bp->b_dotp = bp->b_linep; /* Fix dot */ bp->b_doto = 0; bp->b_markp = NULL; /* Invalidate "mark" */ bp->b_marko = 0; @@ -512,8 +513,10 @@ showbuffer(BUFFER *bp, MGWIN *wp, int flags) BUFFER *obp; MGWIN *owp; - if (wp->w_bufp == bp) { /* Easy case! */ + if (wp->w_bufp == bp) { /* Easy case! */ wp->w_flag |= flags; + wp->w_dotp = bp->b_dotp; + wp->w_doto = bp->b_doto; return TRUE; } /* First, dettach the old buffer from the window */ diff --git a/usr.bin/mg/def.h b/usr.bin/mg/def.h index 6e286922301..1f1815b24a2 100644 --- a/usr.bin/mg/def.h +++ b/usr.bin/mg/def.h @@ -1,4 +1,4 @@ -/* $OpenBSD: def.h,v 1.47 2003/06/26 23:04:10 vincent Exp $ */ +/* $OpenBSD: def.h,v 1.48 2003/08/15 23:23:18 vincent Exp $ */ #include @@ -325,6 +325,8 @@ int d_expunge(int, int); int d_copy(int, int); int d_del(int, int); int d_rename(int, int); +int d_shell_command(int, int); +int d_create_directory(int, int); /* file.c X */ int fileinsert(int, int); diff --git a/usr.bin/mg/dired.c b/usr.bin/mg/dired.c index f0d18d4d63f..272b92c2163 100644 --- a/usr.bin/mg/dired.c +++ b/usr.bin/mg/dired.c @@ -1,28 +1,115 @@ -/* $OpenBSD: dired.c,v 1.11 2003/06/26 23:04:10 vincent Exp $ */ +/* $OpenBSD: dired.c,v 1.12 2003/08/15 23:23:18 vincent Exp $ */ /* dired module for mg 2a */ /* by Robert A. Larson */ #include "def.h" #include "kbd.h" +#include +#include +#include + +#include +#include +#include +#include #ifndef NO_DIRED int d_findfile(int, int); -static PF dired_pf[] = { - d_findfile, +static PF dired_cmds_1[] = { + forwline, /* space */ + d_shell_command, /* ! */ + rescan, /* " */ + rescan, /* # */ + rescan, /* $ */ + rescan, /* % */ + rescan, /* & */ + rescan, /* ' */ + rescan, /* ( */ + rescan, /* ) */ + rescan, /* * */ + d_create_directory, /* + */ +}; + +static PF dired_cmds_2[] = { + rescan, /* a */ + rescan, /* b */ + rescan, /* c */ + rescan, /* d */ + d_findfile, /* e */ + d_findfile, /* f */ + rescan, /* g */ + rescan, /* h */ + rescan, /* i */ + rescan, /* j */ + rescan, /* k */ + rescan, /* l */ + rescan, /* m */ + forwline, /* n */ + d_ffotherwindow, /* o */ + rescan, /* p */ + rescan, /* q */ + rescan, /* r */ + rescan, /* s */ + rescan, /* t */ + rescan, /* u */ + d_findfile, /* v */ + rescan, /* w */ + d_expunge, /* x */ + rescan, /* y */ + rescan, /* z */ +}; + +static PF dired_cmds_3[] = { + rescan, /* A */ + rescan, /* B */ + d_copy, /* C */ + d_del, /* D */ + rescan, /* E */ + rescan, /* F */ + rescan, /* G */ + rescan, /* H */ + rescan, /* I */ + rescan, /* J */ + rescan, /* K */ + rescan, /* L */ + rescan, /* M */ + rescan, /* N */ + rescan, /* O */ + rescan, /* P */ + rescan, /* Q */ + d_rename, /* R */ + rescan, /* S */ + rescan, /* T */ + rescan, /* U */ + d_findfile, /* V */ + rescan, /* W */ + d_expunge, /* X */ + rescan, /* Y */ + rescan, /* Z */ }; -static struct KEYMAPE (1 + IMAPEXT) diredmap = { - 1, - 1 + IMAPEXT, +static PF dired_pf[] = { + d_findfile, /* ^M */ + rescan, /* ^N */ + d_findfile, /* ^O */ +}; + +static struct KEYMAPE (4 + IMAPEXT) diredmap = { + 4, + 4 + IMAPEXT, rescan, { - { CCHR('M'), CCHR('M'), dired_pf, NULL }, + { CCHR('M'), CCHR('O'), dired_pf, NULL }, + { ' ', '+', dired_cmds_1, NULL }, + { 'A', 'Z', dired_cmds_3, NULL }, + { 'a', 'z', dired_cmds_2, NULL } } }; + /* ARGSUSED */ int dired(int f, int n) @@ -57,7 +144,8 @@ d_otherwindow(int f, int n) MGWIN *wp; dirname[0] = '\0'; - if (eread("Dired other window: ", dirname, NFILEN, EFNEW | EFCR) == ABORT) + if (eread("Dired other window: ", dirname, NFILEN, EFNEW | EFCR) + == ABORT) return ABORT; if ((bp = dired_(dirname)) == NULL) return FALSE; @@ -129,7 +217,11 @@ d_findfile(int f, int n) if ((s = d_makename(curwp->w_dotp, fname, sizeof fname)) == ABORT) return FALSE; - if ((bp = (s ? dired_(fname) : findbuffer(fname))) == NULL) + if (s == TRUE) + bp = dired_(fname); + else + bp = findbuffer(fname); + if (bp == NULL) return FALSE; curbp = bp; if (showbuffer(bp, curwp, WFHARD) != TRUE) @@ -177,14 +269,15 @@ d_expunge(int f, int n) return FALSE; case FALSE: if (unlink(fname) < 0) { - ewprintf("Could not delete '%s'", fname); + ewprintf("Could not delete '%s'", + basename(fname)); return FALSE; } break; case TRUE: if (rmdir(fname) < 0) { ewprintf("Could not delete directory '%s'", - fname); + basename(fname)); return FALSE; } break; @@ -196,21 +289,32 @@ d_expunge(int f, int n) return TRUE; } + /* ARGSUSED */ int d_copy(int f, int n) { char frname[NFILEN], toname[NFILEN]; - int stat; + int stat, off; + BUFFER *bp; if (d_makename(curwp->w_dotp, frname, sizeof frname) != FALSE) { ewprintf("Not a file"); return FALSE; } - if ((stat = eread("Copy %s to: ", toname, NFILEN, EFNEW | EFCR, frname)) - != TRUE) - return stat; - return copy(frname, toname) >= 0; + off = strlcpy(toname, curbp->b_fname, sizeof toname); + if (off >= sizeof toname - 1) { /* can't happen, really */ + ewprintf("too long directory name"); + return (FALSE); + } + if ((stat = eread("Copy %s to: ", toname + off, sizeof toname - off, + EFNEW | EFCR, basename(frname))) != TRUE) + return (stat); + stat = (copy(frname, toname) >= 0) ? TRUE : FALSE; + if (stat != TRUE) + return (stat); + bp = dired_(curbp->b_fname); + return (showbuffer(bp, curwp, WFHARD | WFMODE)); } /* ARGSUSED */ @@ -218,15 +322,148 @@ int d_rename(int f, int n) { char frname[NFILEN], toname[NFILEN]; - int stat; + int stat, off; + BUFFER *bp; if (d_makename(curwp->w_dotp, frname, sizeof frname) != FALSE) { ewprintf("Not a file"); return FALSE; } - if ((stat = eread("Rename %s to: ", toname, NFILEN, EFNEW | EFCR, - frname)) != TRUE) + off = strlcpy(toname, curbp->b_fname, sizeof toname); + if (off >= sizeof toname - 1) { /* can't happen, really */ + ewprintf("too long directory name"); + return (FALSE); + } + if ((stat = eread("Rename %s to: ", toname + off, + sizeof toname - off, EFNEW | EFCR, basename(frname))) != TRUE) return stat; - return rename(frname, toname) >= 0; + stat = (rename(frname, toname) >= 0) ? TRUE : FALSE; + if (stat != TRUE) + return (stat); + bp = dired_(curbp->b_fname); + return (showbuffer(bp, curwp, WFHARD | WFMODE)); } #endif + +void +reaper(int signo __attribute__((unused))) +{ + pid_t ret; + int status; + + while ((ret = waitpid(-1, &status, WNOHANG)) >= 0) + ; +} + +/* + * Pipe the currently selected file through a shell command. + */ +int +d_shell_command(int f, int n) +{ + char command[512], fname[MAXPATHLEN], buf[BUFSIZ], *cp; + int infd, fds[2]; + pid_t pid; + struct sigaction olda, newa; + BUFFER *bp; + MGWIN *wp; + FILE *fin; + + bp = bfind("*Shell Command Output*", TRUE); + if (bclear(bp) != TRUE) + return (ABORT); + + if (d_makename(curwp->w_dotp, fname, sizeof fname) != FALSE) { + ewprintf("bad line"); + return (ABORT); + } + + command[0] = '\0'; + if (eread("! on %s: ", command, sizeof command, 0, + basename(fname)) == ABORT) + return (ABORT); + infd = open(fname, O_RDONLY); + if (infd == -1) { + ewprintf("Can't open input file : %s", strerror(errno)); + return (ABORT); + } + if (pipe(fds) == -1) { + ewprintf("Can't create pipe : %s", strerror(errno)); + close(infd); + return (ABORT); + } + + newa.sa_handler = reaper; + newa.sa_flags = 0; + if (sigaction(SIGCHLD, &newa, &olda) == -1) { + close(infd); + close(fds[0]); + close(fds[1]); + return (ABORT); + } + pid = fork(); + switch (pid) { + case -1: + ewprintf("Can't fork"); + return (ABORT); + case 0: + close(fds[0]); + dup2(infd, STDIN_FILENO); + dup2(fds[1], STDOUT_FILENO); + dup2(fds[1], STDERR_FILENO); + execl("/bin/sh", "sh", "-c", command, (char *)NULL); + exit(1); + default: + close(infd); + close(fds[1]); + fin = fdopen(fds[0], "r"); + if (fin == NULL) /* "r" is surely a valid mode! */ + panic("can't happen"); + while (fgets(buf, sizeof buf, fin) != NULL) { + cp = strrchr(buf, '\n'); + if (cp == NULL && !feof(fin)) { /* too long a line */ + int c; + addlinef(bp, "%s...", buf); + while ((c = getc(fin)) != EOF && c != '\n') + ; + continue; + } else if (cp) + *cp = '\0'; + addline(bp, buf); + } + fclose(fin); + close(fds[0]); + break; + } + wp = popbuf(bp); + if (wp == NULL) + return (ABORT); /* XXX - free the buffer?? */ + curwp = wp; + curbp = wp->w_bufp; + if (sigaction(SIGCHLD, &olda, NULL) == -1) + ewprintf("Warning, couldn't reset previous signal handler"); + return (TRUE); +} + +int +d_create_directory(int f, int n) +{ + char tocreate[MAXPATHLEN], off; + int stat; + BUFFER *bp; + + off = strlcpy(tocreate, curbp->b_fname, sizeof tocreate); + if (off >= sizeof tocreate - 1) + return (FALSE); + if ((stat = ereply("Create directory: ", tocreate + off, + sizeof tocreate - off)) + != TRUE) + return (stat); + if (mkdir(tocreate, 0755) == -1) { + ewprintf("Creating directory: %s, %s", strerror(errno), + tocreate); + return (ABORT); + } + bp = dired_(curbp->b_fname); + return (showbuffer(bp, curwp, WFHARD | WFMODE)); +} diff --git a/usr.bin/mg/display.c b/usr.bin/mg/display.c index 31db3b1665f..354d4ca266b 100644 --- a/usr.bin/mg/display.c +++ b/usr.bin/mg/display.c @@ -1,4 +1,4 @@ -/* $OpenBSD: display.c,v 1.19 2002/09/15 13:59:16 vincent Exp $ */ +/* $OpenBSD: display.c,v 1.20 2003/08/15 23:23:18 vincent Exp $ */ /* * The functions in this file handle redisplay. The @@ -347,6 +347,7 @@ vtpute(int c) } } + /* * Erase from the end of the software cursor to the end of the line on which * the software cursor is located. The display routines will decide if a diff --git a/usr.bin/mg/fileio.c b/usr.bin/mg/fileio.c index 478f5db1e19..7123a9ffef7 100644 --- a/usr.bin/mg/fileio.c +++ b/usr.bin/mg/fileio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fileio.c,v 1.37 2003/08/15 23:09:57 vincent Exp $ */ +/* $OpenBSD: fileio.c,v 1.38 2003/08/15 23:23:18 vincent Exp $ */ /* * POSIX fileio.c @@ -402,7 +402,8 @@ dired_(char *dirname) if (bclear(bp) != TRUE) return NULL; bp->b_flag |= BFREADONLY; - if (snprintf(line, sizeof(line), "ls -al %s", dirname) >= sizeof(line)){ + if (snprintf(line, sizeof(line), "ls -al %s", dirname) + >= sizeof(line)) { ewprintf("Path too long"); return NULL; } @@ -416,17 +417,18 @@ dired_(char *dirname) (void) addline(bp, line); } if (pclose(dirpipe) == -1) { - ewprintf("Problem closing pipe to ls"); + ewprintf("Problem closing pipe to ls : %s", + strerror(errno)); return NULL; } bp->b_dotp = lforw(bp->b_linep); /* go to first line */ (void) strlcpy(bp->b_fname, dirname, sizeof bp->b_fname); - if ((bp->b_modes[0] = name_mode("dired")) == NULL) { + if ((bp->b_modes[1] = name_mode("dired")) == NULL) { bp->b_modes[0] = name_mode("fundamental"); ewprintf("Could not find mode dired"); return NULL; } - bp->b_nmodes = 0; + bp->b_nmodes = 1; return bp; } @@ -452,7 +454,7 @@ d_makename(LINE *lp, char *fn, int len) return (ABORT); } strlcat(fn, p, len); - return lgetc(lp, 2) == 'd'; + return (lgetc(lp, 2) == 'd') ? TRUE : FALSE; } #endif /* NO_DIRED */ -- cgit v1.2.3