shithub: nc

ref: d746543eaed06a1027b5faf07ce37963710d36c2
dir: /dirviewcmd.c/

View raw version
#include "a.h"

static long
dirlist(Dirpanel *p, Dir **d)
{
	long n;

	n = dirmodelmarklist(p->model, d);
	if(n == 0){
		n = dirpanelselectedindex(p);
		if(n == 0 && !p->model->isroot) /* up dir */
			return 0;
		*d = emalloc(sizeof(Dir));
		**d = dirmodelgetdir(p->model, n);
		n = 1;
	}
	return n;
}

static void
cmdhelp(void)
{
	textset(text, "Help", help, strlen(help));
	setmode(Mhelp);
}

static void
cmdview(void)
{
	Dirpanel *p;
	Dir d;
	char *s, *t;

	p = dirviewcurrentpanel(dview);
	d = dirmodelgetdir(p->model, dirpanelselectedindex(p));
	if(d.qid.type&QTDIR){
		p->cursor = 0;
		p->offset = 0;
		dirmodelcd(p->model, d.name);
	}else{
		t = smprint("%s/%s", p->model->path, d.name);
		s = slurp(t);
		textset(text, t, s, strlen(s));
		setmode(Mview);
	}
}

static void
cmdplumb(void)
{
	Dirpanel *p;
	Dir d;
	int fd;
	char buf[1024];
	
	p = dirviewcurrentpanel(dview);
	d = dirmodelgetdir(p->model, dirpanelselectedindex(p));
	fd = plumbopen("send", OWRITE|OCEXEC);
	snprint(buf, sizeof buf, "%s/%s", p->model->path, d.name);
	if(d.qid.type&QTDIR)
		plumbsendtext(fd, "nc", nil, nil, buf);
	else
		plumbsendtext(fd, "nc", nil, p->model->path, buf);
	close(fd);
}

static void
cmdcopy(void)
{
	Dirpanel *p, *o;
	Dir *d;
	int nd, n;
	char buf[1024] = {0};
	
	p = dirviewcurrentpanel(dview);
	o = dirviewotherpanel(dview);
	if(dirmodeleq(p->model, o->model)){
		errormessage("cannot copy files to the same directory.", mc, kc);
		return;
	}
	nd = dirlist(p, &d);
	if(nd == 1)
		snprint(buf, sizeof buf, "copy %s '%s' to '%s' ?", 
			(d[0].qid.type&QTDIR) ? "directory" : "file", d[0].name, o->model->path);
	else
		snprint(buf, sizeof buf, "copy %d files/directories ?", nd);
	if(message(Dconfirm, buf, mc, kc) == Bno)
		return;
	for(n = 0; n < nd; n++){
		if(cp(p->model->path, d[n], o->model->path, nil) < 0){
			errormessage("copy failed: %r", mc, kc);
			return;
		}
	}
	dirmodelreload(o->model);
}

static void
cmdrenmov(void)
{
	Dirpanel *p, *o;
	Dir *d, null;
	char opath[1024] = {0}, buf[255] = {0};
	int i, n;

	p = dirviewcurrentpanel(dview);
	o = dirviewotherpanel(dview);
	n = dirlist(p, &d);
	if(dirmodeleq(p->model, o->model)){
		if(n > 1){
			errormessage("cannot rename multiple files/directories.", mc, kc);
			return;
		}
		snprint(buf, sizeof buf, d[0].name);
		if(input("rename to:", buf, sizeof buf, mc, kc) <= 0)
			return;
		if(strcmp(buf, d[0].name) == 0){
			errormessage("target file name should be different.", mc, kc);
			return;
		}
		if(d[0].qid.type&QTDIR){
			if(cp(p->model->path, d[0], o->model->path, buf) < 0){
				errormessage("rename failed: %r", mc, kc);
				return;
			}
			if(rm(p->model->path, d[0]) < 0){
				errormessage("rename failed: %r", mc, kc);
				return;
			}
		}else{
			snprint(opath, sizeof opath, "%s/%s", p->model->path, d[0].name);
			nulldir(&null);
			null.name = buf;
			if(dirwstat(opath, &null) < 0){
				errormessage("rename failed: %r", mc, kc);
				return;
			}
		}
	}else{
		if(n == 1)
			snprint(buf, sizeof buf, "move %s '%s' to '%s' ?", 
				(d[0].qid.type&QTDIR) ? "directory" : "file", d[0].name, o->model->path);
		else
			snprint(buf, sizeof buf, "move %d files/directories ?", n);
		if(message(Dconfirm, buf, mc, kc) == Bno)
			return;
		for(i = 0; i < n; i++){
			if(cp(p->model->path, d[i], o->model->path, nil) < 0){
				errormessage("move failed: %r", mc, kc);
				return;
			}
			if(rm(p->model->path, d[i]) < 0){
				errormessage("move failed: %r", mc, kc);
				return;
			}
		}
	}
	dirmodelreload(p->model);
	dirmodelreload(o->model);		
	return;	
}

static void
cmdmkdir(void)
{
	Dirpanel *p;
	char buf[1024] = {0};

	p = dirviewcurrentpanel(dview);
	if(input("create directory:", buf, sizeof buf, mc, kc) <= 0)
		return;
	if(mkdir(p->model->path, buf) < 0){
		errormessage("directory creation failed: %r", mc, kc);
		return;
	}
	dirmodelreload(p->model);
	dirmodelreloadifsame(p->model, dirviewotherpanel(dview)->model);
}

static void
cmddelete(void)
{
	Dirpanel *p, *o;
	Dir *d;
	char buf[1024] = {0};
	int i, n;

	p = dirviewcurrentpanel(dview);
	o = dirviewotherpanel(dview);
	n = dirlist(p, &d);
	if(n == 1)
		snprint(buf, sizeof buf, "delete %s '%s' ?", (d[0].qid.type&QTDIR) ? "directory" : "file", d[0].name);
	else
		snprint(buf, sizeof buf, "delete %d files/directories ?", n);
	if(message(Dconfirm, buf, mc, kc) == Bno)
		return;
	for(i = 0; i < n; i++){
		if(rm(p->model->path, d[i]) < 0){
			errormessage("delete failed: %r", mc, kc);
			return;
		}
	}
	dirmodelreload(p->model);
	dirmodelreloadifsame(p->model, o->model);
}

static void
cmdquit(void)
{
	threadexitsall(nil);
}

static void
cmdswitchfocus(void)
{
	dview->leftp->focused = !dview->leftp->focused;
	dview->rightp->focused = !dview->rightp->focused;
	dirviewredraw(dview);
	sendul(dview->c, 1);
}

static void
cmdreload(void)
{
	Dirpanel *p;
	
	p = dirviewcurrentpanel(dview);
	dirmodelreload(p->model);
}

static void
cmdcd(void)
{
	Dirpanel *p;
	char buf[1024] = {0};

	p = dirviewcurrentpanel(dview);
	if(input("go to directory:", buf, sizeof buf, mc, kc) <= 0)
		return;
	dirpanelresetcursor(p);
	dirmodelcd(p->model, buf);
}

static void
cmdcdo(void)
{
	Dirpanel *p;
	char buf[1024] = {0};

	p = dirviewotherpanel(dview);
	if(input("go to directory:", buf, sizeof buf, mc, kc) <= 0)
		return;
	dirpanelresetcursor(p);
	dirmodelcd(p->model, buf);
}

static void
cmdcdmatch(void)
{
	Dirpanel *o;
	char *path;

	path = dirviewcurrentpanel(dview)->model->path;
	o = dirviewotherpanel(dview);
	dirpanelresetcursor(o);
	dirmodelcd(o->model, path);
}

static void
cmdselectgroup(void)
{
	Dirpanel *p;
	Dir d;
	int i;
	char buf[256] = {0};

	p = dirviewcurrentpanel(dview);
	if(input("select pattern:", buf, sizeof(buf), mc, kc) <= 0)
		return;
	for(i = !p->model->isroot; i < dirmodelcount(p->model); i++){
		d = dirmodelgetdir(p->model, i);
		p->model->sel[i] = match(d.name, buf);
	}
	dirpanelredrawnotify(p);
}

static void
cmdunselectgroup(void)
{
	Dirpanel *p;
	Dir d;
	int i, r;
	char buf[256] = {0};

	p = dirviewcurrentpanel(dview);
	if(input("unselect pattern:", buf, sizeof(buf), mc, kc) <= 0)
		return;
	r = 0;
	for(i = !p->model->isroot; i < dirmodelcount(p->model); i++){
		d = dirmodelgetdir(p->model, i);
		if(match(d.name, buf) && p->model->sel[i]){
			p->model->sel[i] = 0;
			r = 1;
		}
	}
	if(r)
		dirpanelredrawnotify(p);
}

static void
cmdinvertselection(void)
{
	Dirpanel *p;
	int i;

	p = dirviewcurrentpanel(dview);
	for(i = !p->model->isroot; i < dirmodelcount(p->model); i++)
		p->model->sel[i] = !p->model->sel[i];
	dirpanelredrawnotify(p);
}

static void
cmdselect(void)
{
	Dirpanel *p;
	Dir d;
	int i;

	p = dirviewcurrentpanel(dview);
	i = p->offset + p->cursor;
	d = dirmodelgetdir(p->model, i);
	if(i == 0 && !p->model->isroot)
		return;
	p->model->sel[i] = !p->model->sel[i];
	if(p->cursor == p->nlines - 1 && (p->offset + p->nlines >= dirmodelcount(p->model)))
		goto Draw;
	if(p->offset + p->cursor + 1 >= dirmodelcount(p->model))
		goto Draw;
	if(p->cursor == p->nlines - 1){
		p->offset += p->nlines;
		p->cursor = 0;
	}else{
		p->cursor += 1;
	}
Draw:
	dirpanelredrawnotify(p);
}

static void
cmdfilter(void)
{
	Dirpanel *p;
	char buf[256] = {0};

	p = dirviewcurrentpanel(dview);
	if(input("filter pattern:", buf, sizeof buf, mc, kc) <= 0){
		if(p->model->filter != nil){
			dirpanelresetcursor(p);
			dirmodelfilter(p->model, nil);
		}
	}else{
		dirpanelresetcursor(p);
		dirmodelfilter(p->model, buf);
	}
}

static void
cmdup(void)
{
	Dirpanel *p;

	p = dirviewcurrentpanel(dview);
	if(p->cursor == 0 && p->offset == 0)
		return;
	if(p->cursor == 0){
		p->offset -= p->nlines;
		if(p->offset < 0)
			p->offset = 0;
		p->cursor = p->nlines -1;
	}else{
		p->cursor -= 1;
	}
	dirpanelredrawnotify(p);
}

static void
cmddown(void)
{
	Dirpanel *p;

	p = dirviewcurrentpanel(dview);
	if(p->cursor == p->nlines - 1 && (p->offset + p->nlines >= dirmodelcount(p->model)))
		return;
	if(p->offset + p->cursor + 1 >= dirmodelcount(p->model))
		return;
	if(p->cursor == p->nlines - 1){
		p->offset += p->nlines;
		p->cursor = 0;
		if(dirmodelcount(p->model)-p->offset < p->nlines)
			p->offset = dirmodelcount(p->model) - p->nlines;
	}else{
		p->cursor += 1;
	}
	dirpanelredrawnotify(p);
}

static void
cmdhome(void)
{
	Dirpanel *p;

	p = dirviewcurrentpanel(dview);
	dirpanelresetcursor(p);
	dirpanelredrawnotify(p);
}

static void
cmdend(void)
{
	Dirpanel *p;

	p = dirviewcurrentpanel(dview);
	p->offset = p->nlines * (dirmodelcount(p->model) / p->nlines);
	if(dirmodelcount(p->model)-p->offset < p->nlines)
		p->offset = dirmodelcount(p->model) - p->nlines;
	if(p->offset < 0)
		p->offset = 0;
	p->cursor = dirmodelcount(p->model) - p->offset - 1;
	dirpanelredrawnotify(p);
}

static void
cmdpageup(void)
{
	Dirpanel *p;

	p = dirviewcurrentpanel(dview);
	if(p->offset == 0 && p->cursor == 0)
		return;
	if(p->offset == 0)
		p->cursor = 0;
	else
		p->offset -= p->nlines;
	if(p->offset < 0)
		p->offset = 0;
	dirpanelredrawnotify(p);
}

static void
cmdpagedown(void)
{
	Dirpanel *p;
	int end;

	p = dirviewcurrentpanel(dview);
	end = dirmodelcount(p->model) - p->offset - 1;
	if(p->offset + p->nlines >= dirmodelcount(p->model) && p->cursor == end)
		return;
	if(p->offset + p->nlines < dirmodelcount(p->model)){
		p->offset += p->nlines;
		if(dirmodelcount(p->model)-p->offset < p->nlines)
			p->offset = dirmodelcount(p->model) - p->nlines;		
	}else
		p->cursor = end;
	if(p->cursor > end)
		p->cursor = end;
	dirpanelredrawnotify(p);
}

Binding	dirviewbindings[] = {
	{ KF|1,		cmdhelp },
	{ KF|3,		cmdview },
	{ KF|4,		cmdplumb },
	{ KF|5,		cmdcopy },
	{ KF|6,		cmdrenmov },
	{ KF|7,		cmdmkdir },
	{ KF|8,		cmddelete },
	{ KF|10,	cmdquit },
	{ '\t',		cmdswitchfocus },
	{ 'r',		cmdreload },
	{ 'c',		cmdcd },
	{ 'C',		cmdcdo },
	{ '=',		cmdcdmatch },
	{ '\n',		cmdview },
	{ '+',		cmdselectgroup },
	{ '-',		cmdunselectgroup },
	{ '*',		cmdinvertselection },
	{ Kins,		cmdselect },
	{ 'f',		cmdfilter },
	{ Kup,		cmdup },
	{ Kdown,	cmddown },
	{ Khome,	cmdhome },
	{ Kend,		cmdend },
	{ Kpgup,	cmdpageup },
	{ Kpgdown,	cmdpagedown },
	nil
};

void
setupdirviewbindings(void)
{
	bindings = dirviewbindings;
	actionbarclear(abar);
	actionbarset(abar, 1, "Help",   cmdhelp);
	actionbarset(abar, 3, "View",   cmdview);
	actionbarset(abar, 4, "Plumb",  cmdplumb);
	actionbarset(abar, 5, "Copy",   cmdcopy);
	actionbarset(abar, 6, "RenMov", cmdrenmov);
	actionbarset(abar, 7, "Mkdir",  cmdmkdir);
	actionbarset(abar, 8, "Delete", cmddelete);
	actionbarset(abar, 10, "Quit",  cmdquit);
}