shithub: nc

Download patch

ref: aac2549d724f05d5b5dcce35c6f3e29a936f8cd1
parent: bcac03391b9eec054bfb6911ac8e1e504c91889b
author: phil9 <telephil9@gmail.com>
date: Tue Dec 27 11:37:30 EST 2022

implement delete command

--- a/a.h
+++ b/a.h
@@ -116,8 +116,10 @@
 Dir			dirmodelgetdir(Dirmodel*, int);
 long		dirmodelcount(Dirmodel*);
 void		dirmodelreload(Dirmodel*);
+void		dirmodelreloadifsame(Dirmodel*, Dirmodel*);
 void		dirmodelcd(Dirmodel*, char*);
 void		dirmodelfilter(Dirmodel*, char*);
+long		dirmodelmarklist(Dirmodel*, Dir**);
 
 Dirpanel*	mkdirpanel(Dirmodel*);
 void		dirpanelsetrect(Dirpanel*, Rectangle);
@@ -148,7 +150,12 @@
 int			match(char*, char*);
 
 int			message(int, const char*, Mousectl*, Keyboardctl*);
+void		errormessage(char*, Mousectl*, Keyboardctl*);
 
+int			mkdir(char*, char*);
+int			rm(char*, Dir);
+int			rmdir(char*);
+
 Rectangle	boundsrect(Rectangle);
 Image*		ealloccolor(ulong);
 void*		emalloc(ulong);
@@ -156,7 +163,6 @@
 char*		slurp(char*);
 char*		homedir(void);
 char*		abspath(char*, char*);
-int			mkdir(char*, char*);
 
 enum
 {
--- a/dirmodel.c
+++ b/dirmodel.c
@@ -48,6 +48,13 @@
 }
 
 void
+dirmodelreloadifsame(Dirmodel *m, Dirmodel *o)
+{
+	if(strcmp(m->path, o->path) == 0)
+		dirmodelreload(o);
+}
+
+void
 dirmodelcd(Dirmodel *m, char *p)
 {
 	char newpath[1024] = {0};
@@ -134,4 +141,31 @@
 	memset(m->sel, 0, m->ndirs * sizeof(uchar));
 	m->filter = strdup(p);
 	sendul(m->c, 1);
+}
+
+long
+dirmodelmarklist(Dirmodel *m, Dir **d)
+{
+	int i, j;
+	long n, ndirs;
+	Dir *dirs;
+
+	n = 0;
+	ndirs = m->ndirs;
+	dirs = m->dirs;
+	if(m->filter){
+		ndirs = m->fndirs;
+		dirs = m->fdirs;
+	}
+	for(i = 0; i < ndirs; i++)
+		n += m->sel[i];
+	if(n == 0)
+		return 0;
+	*d = emalloc(n*sizeof(Dir));
+	j = 0;
+	for(i = 0; i < ndirs; i++){
+		if(m->sel[i])
+			(*d)[j++] = dirs[i];
+	}
+	return n;
 }
--- a/dirviewcmd.c
+++ b/dirviewcmd.c
@@ -58,7 +58,7 @@
 {
 	Dirpanel *p;
 	Dir d, null;
-	char errbuf[64+ERRMAX], opath[1024] = {0}, buf[255] = {0};
+	char opath[1024] = {0}, buf[255] = {0};
 	int n;
 
 	p = dirviewcurrentpanel(dview);
@@ -65,7 +65,7 @@
 	if(strcmp(p->model->path, dirviewotherpanel(dview)->model->path) == 0){
 		d = dirmodelgetdir(p->model, dirpanelselectedindex(p));
 		if(d.qid.type&QTDIR){
-			message(Derror, "cannot rename directories.", mc, kc);
+			errormessage("cannot rename directories.", mc, kc);
 			return;
 		}
 		snprint(buf, sizeof buf, d.name);
@@ -77,8 +77,7 @@
 		nulldir(&null);
 		null.name = buf;
 		if(dirwstat(opath, &null) < 0){
-			snprint(errbuf, sizeof errbuf, "rename failed: %r");
-			message(Derror, errbuf, mc, kc);
+			errormessage("rename failed: %r", mc, kc);
 		}else{
 			dirmodelreload(p->model);
 			dirmodelreload(dirviewotherpanel(dview)->model);
@@ -85,7 +84,7 @@
 		}			
 		return;
 	}
-};
+}
 
 static void
 cmdmkdir(void)
@@ -97,16 +96,51 @@
 	if(enter("new dir:", buf, sizeof buf, mc, kc, nil) <= 0)
 		return;
 	if(mkdir(p->model->path, buf) < 0){
-		fprint(2, "mkdir: %r\n");
+		errormessage("directory creation failed: %r", mc, kc);
 		return;
 	}
 	dirmodelreload(p->model);
+	dirmodelreloadifsame(p->model, dirviewotherpanel(dview)->model);
 }
 
 static void
 cmddelete(void)
 {
-	fprint(2, "TODO: delete\n");
+	Dirpanel *p;
+	Dir *md, d;
+	char buf[1024] = {0}, *path;
+	long nd;
+	int n;
+
+	p = dirviewcurrentpanel(dview);
+	path = p->model->path;
+	nd = dirmodelmarklist(p->model, &md);
+	if(nd != 0){
+		snprint(buf, sizeof buf, "delete %ld files/directories ?", nd);
+		if(message(Dconfirm, buf, mc, kc) == Bno)
+			return;
+		for(n = 0; n < nd; n++){
+			d = md[n];
+			if(rm(path, d) < 0){
+				errormessage("delete failed: %r", mc, kc);
+				return;
+			}
+		}
+	}else{
+		n = dirpanelselectedindex(p);
+		if(n == 0 && !p->model->isroot) /* up dir */
+			return;
+		d = dirmodelgetdir(p->model, n);
+		snprint(buf, sizeof buf, "delete %s '%s' ?", (d.qid.type&QTDIR) ? "directory" : "file", d.name);
+		if(message(Dconfirm, buf, mc, kc) == Bno)
+			return;
+		if(rm(path, d) < 0){
+			errormessage("delete failed: %r", mc, kc);
+			return;
+		}
+	}
+	dirmodelreload(p->model);
+	dirmodelreloadifsame(p->model, dirviewotherpanel(dview)->model);
 }
 
 static void
--- /dev/null
+++ b/fops.c
@@ -1,0 +1,63 @@
+#include "a.h"
+
+int
+mkdir(char *wd, char *name)
+{
+	char *p;
+	int fd;
+	
+	p = abspath(wd, name);
+	if(access(p, 0) >= 0){
+		werrstr("directory already exists");
+		free(p);
+		return -1;
+	}
+	fd = create(p, OREAD, DMDIR|0755);
+	if(fd < 0){
+		free(p);
+		return -1;
+	}
+	free(p);
+	close(fd);
+	return 0;
+}
+
+int
+rmdir(char *path)
+{
+	Dir *dirs;
+	int i, fd, ndirs;
+	
+	fd = open(path, OREAD);
+	if(fd < 0)
+		return -1;
+	ndirs = dirreadall(fd, &dirs);
+	close(fd);
+	if(ndirs < 0)
+		return -1;
+	for(i = 0; i < ndirs; i++){
+		if(rm(path, dirs[i]) < 0){
+			free(dirs);
+			return -1;
+		}
+	}
+	free(dirs);
+	if(remove(path) < 0)
+		return -1;
+	return 0;
+}
+
+int
+rm(char *path, Dir d)
+{
+	char buf[1024] = {0};
+	int rc;
+
+	snprint(buf, sizeof buf, "%s/%s", path, d.name);
+	if(d.qid.type&QTDIR){
+		rc = rmdir(buf);
+	}else{
+		rc = remove(buf);
+	}
+	return rc;
+}
--- a/message.c
+++ b/message.c
@@ -136,3 +136,12 @@
 	flushimage(display, 1);
 	return rc;
 }
+
+void
+errormessage(char *msg, Mousectl *mc, Keyboardctl *kc)
+{
+	char errbuf[64+ERRMAX] = {0};
+	
+	snprint(errbuf, sizeof errbuf, msg);
+	message(Derror, msg, mc, kc);
+}
--- a/mkfile
+++ b/mkfile
@@ -15,6 +15,7 @@
 	text.$O			\
 	message.$O		\
 	glob.$O			\
+	fops.$O			\
 	utils.$O
 
 </sys/src/cmd/mkone
--- a/utils.c
+++ b/utils.c
@@ -99,25 +99,3 @@
 	cleanname(s);
 	return s;
 }
-
-int
-mkdir(char *wd, char *name)
-{
-	char *p;
-	int fd;
-	
-	p = abspath(wd, name);
-	if(access(p, 0) >= 0){
-		werrstr("directory already exists");
-		free(p);
-		return -1;
-	}
-	fd = create(p, OREAD, DMDIR|0755);
-	if(fd < 0){
-		free(p);
-		return -1;
-	}
-	free(p);
-	close(fd);
-	return 0;
-}