summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Labrecque <vincent@cvs.openbsd.org>2003-08-15 23:23:19 +0000
committerVincent Labrecque <vincent@cvs.openbsd.org>2003-08-15 23:23:19 +0000
commitcccde189d91e9b3ab6fe8a3aa1f98da1b1af39d7 (patch)
tree9dd2c2ca28df1b18b29d6f4eb651533a27b6b120
parent5d56ea0ca32e34ec476c82a335f0150d8304f517 (diff)
make dired work more like emacs. (well, make it _work_, and then add a
bunch of missing commands)
-rw-r--r--usr.bin/mg/buffer.c11
-rw-r--r--usr.bin/mg/def.h4
-rw-r--r--usr.bin/mg/dired.c277
-rw-r--r--usr.bin/mg/display.c3
-rw-r--r--usr.bin/mg/fileio.c14
5 files changed, 277 insertions, 32 deletions
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 <sys/queue.h>
@@ -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 <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <libgen.h>
#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 */