shithub: riscv

Download patch

ref: 4757debd0b5935dae94944c35c3cac74b14aa209
parent: 2b619dc9669e34c7b110ce188a10d03849119c78
author: spew <devnull@localhost>
date: Wed Aug 1 07:14:59 EDT 2018

acme: add spacesindent mode

--- a/sys/man/1/acme
+++ b/sys/man/1/acme
@@ -4,7 +4,7 @@
 .SH SYNOPSIS
 .B acme
 [
-.B -ab
+.B -aib
 ]
 [
 .B -c
@@ -174,6 +174,16 @@
 .B -a
 causes each window to start in 
 autoindent mode.
+.PP
+When a window is in spacesindent mode
+(see the
+.B Spaces
+command below) and a tab character is typed,
+acme indents the line with spaces equal to the current
+tabstop for the window. The option
+.B -i
+causes each window to start in spacesindent
+mode.
 .SS "Directory context
 Each window's tag names a directory: explicitly if the window
 holds a directory; implicitly if it holds a regular file
@@ -429,6 +439,17 @@
 .B Sort
 Arrange the windows in the column from top to bottom in lexicographical
 order based on their names.
+.TP
+.B Spaces
+Set the spacesindent mode according to the argument:
+.B on
+and
+.B off
+set the mode for the current window;
+.B ON
+and
+.B OFF
+set the mode for all existing and future windows.
 .TP
 .B Tab
 Set the width of tab stops for this window to the value of the argument, in units of widths of the zero
--- a/sys/src/cmd/acme/acme.c
+++ b/sys/src/cmd/acme/acme.c
@@ -66,7 +66,7 @@
 	loadfile = nil;
 	ARGBEGIN{
 	case 'a':
-		globalautoindent = TRUE;
+		globalindent[AUTOINDENT] = TRUE;
 		break;
 	case 'b':
 		bartflag = TRUE;
@@ -89,6 +89,9 @@
 		if(fontnames[1] == nil)
 			goto Usage;
 		break;
+	case 'i':
+		globalindent[SPACESINDENT] = TRUE;
+		break;
 	case 'l':
 		loadfile = ARGF();
 		if(loadfile == nil)
@@ -96,7 +99,7 @@
 		break;
 	default:
 	Usage:
-		fprint(2, "usage: acme [-ab] [-c ncol] [-f font] [-F fixedfont] [-l loadfile | file...]\n");
+		fprint(2, "usage: acme [-aib] [-c ncol] [-f font] [-F fixedfont] [-l loadfile | file...]\n");
 		exits("usage");
 	}ARGEND
 
--- a/sys/src/cmd/acme/dat.h
+++ b/sys/src/cmd/acme/dat.h
@@ -224,6 +224,13 @@
 void		textshow(Text*, uint, uint, int);
 void		texttype(Text*, Rune);
 
+enum
+{
+	SPACESINDENT	= 0,
+	AUTOINDENT,
+	NINDENT,
+};
+
 struct Window
 {
 		QLock;
@@ -235,7 +242,7 @@
 	uchar	isscratch;
 	uchar	filemenu;
 	uchar	dirty;
-	uchar	autoindent;
+	uchar	indent[NINDENT];
 	uchar	showdel;
 	uint		noredraw;
 	int		id;
@@ -538,7 +545,7 @@
 char			wdir[];
 int			editing;
 int			messagesize;		/* negotiated in 9P version setup */
-int			globalautoindent;
+int			globalindent[NINDENT];
 
 Channel	*cplumb;		/* chan(Plumbmsg*) */
 Channel	*cwait;		/* chan(Waitmsg) */
--- a/sys/src/cmd/acme/exec.c
+++ b/sys/src/cmd/acme/exec.c
@@ -73,7 +73,7 @@
 	{ L"Get",		get,		FALSE,	TRUE,	XXX		},
 	{ L"ID",		id,		FALSE,	XXX,		XXX		},
 	{ L"Incl",		incl,		FALSE,	XXX,		XXX		},
-	{ L"Indent",	indent,	FALSE,	XXX,		XXX		},
+	{ L"Indent",	indent,		FALSE,	AUTOINDENT,		XXX		},
 	{ L"Kill",		kill,		FALSE,	XXX,		XXX		},
 	{ L"Load",		dump,	FALSE,	FALSE,	XXX		},
 	{ L"Local",		local,	FALSE,	XXX,		XXX		},
@@ -87,6 +87,7 @@
 	{ L"Send",		sendx,	TRUE,	XXX,		XXX		},
 	{ L"Snarf",		cut,		FALSE,	TRUE,	FALSE	},
 	{ L"Sort",		sort,		FALSE,	XXX,		XXX		},
+	{ L"Spaces",	indent,		FALSE,	SPACESINDENT,	XXX		},
 	{ L"Tab",		tab,		FALSE,	XXX,		XXX		},
 	{ L"Undo",		undo,	FALSE,	TRUE,	XXX		},
 	{ L"Zerox",	zeroxx,	FALSE,	XXX,		XXX		},
@@ -1087,57 +1088,67 @@
 enum {
 	IGlobal = -2,
 	IError = -1,
-	Ion = 0,
-	Ioff = 1,
 };
 
 static int
-indentval(Rune *s, int n)
+indentval(Rune *s, int n, int type)
 {
+	static char *strs[] = {
+		[SPACESINDENT] "Spaces",
+		[AUTOINDENT] "Indent",
+	};
+
 	if(n < 2)
 		return IError;
 	if(runestrncmp(s, L"ON", n) == 0){
-		globalautoindent = TRUE;
-		warning(nil, "Indent ON\n");
+		globalindent[type] = TRUE;
+		warning(nil, "%s ON\n", strs[type]);
 		return IGlobal;
 	}
 	if(runestrncmp(s, L"OFF", n) == 0){
-		globalautoindent = FALSE;
-		warning(nil, "Indent OFF\n");
+		globalindent[type] = FALSE;
+		warning(nil, "%s OFF\n", strs[type]);
 		return IGlobal;
 	}
-	return runestrncmp(s, L"on", n) == 0;
+	if(runestrncmp(s, L"on", n) == 0)
+		return TRUE;
+	if(runestrncmp(s, L"off", n) == 0)
+		return FALSE;
+	return IError;
 }
 
 static void
-fixindent(Window *w, void*)
+fixindent(Window *w, void *v)
 {
-	w->autoindent = globalautoindent;
+	int t;
+
+	t = (int)v;
+	w->indent[t] = globalindent[t];
 }
 
 void
-indent(Text *et, Text*, Text *argt, int, int, Rune *arg, int narg)
+indent(Text *et, Text*, Text *argt, int type, int, Rune *arg, int narg)
 {
 	Rune *a, *r;
 	Window *w;
-	int na, len, autoindent;
+	int na, len, ival;
 
 	w = nil;
 	if(et!=nil && et->w!=nil)
 		w = et->w;
-	autoindent = IError;
+	ival = IError;
 	getarg(argt, FALSE, TRUE, &r, &len);
 	if(r!=nil && len>0)
-		autoindent = indentval(r, len);
+		ival = indentval(r, len, type);
 	else{
 		a = findbl(arg, narg, &na);
 		if(a != arg)
-			autoindent = indentval(arg, narg-na);
+			ival = indentval(arg, narg-na, type);
 	}
-	if(autoindent == IGlobal)
-		allwindows(fixindent, nil);
-	else if(w != nil && autoindent >= 0)
-		w->autoindent = autoindent;
+	if(ival == IGlobal)
+		allwindows(fixindent, (void*)type);
+	else if(w != nil && ival >= 0)
+		w->indent[type] = ival;
 }
 
 void
--- a/sys/src/cmd/acme/look.c
+++ b/sys/src/cmd/acme/look.c
@@ -663,9 +663,11 @@
 				runemove(rp, ow->incl[i], n);
 				winaddincl(w, rp, n);
 			}
-			w->autoindent = ow->autoindent;
+			for(i=0; i < NINDENT; i++)
+				w->indent[i] = ow->indent[i];
 		}else
-			w->autoindent = globalautoindent;
+			for(i=0; i < NINDENT; i++)
+				w->indent[i] = globalindent[i];
 	}
 	if(e->a1 == e->a0)
 		eval = FALSE;
--- a/sys/src/cmd/acme/text.c
+++ b/sys/src/cmd/acme/text.c
@@ -502,6 +502,27 @@
 	return r;
 }
 
+static int
+spacesindentbswidth(Text *t)
+{
+	uint q, col;
+	Rune r;
+
+	col = textbswidth(t, 0x15);
+	q = t->q0;
+	while(q > 0){
+		r = textreadc(t, q-1);
+		if(r != ' ')
+			break;
+		q--;
+		if(--col % t->tabstop == 0)
+			break;
+	}
+	if(t->q0 == q)
+		return 1;
+	return t->q0-q;
+}
+
 int
 textbswidth(Text *t, Rune c)
 {
@@ -510,8 +531,11 @@
 	int skipping;
 
 	/* there is known to be at least one character to erase */
-	if(c == 0x08)	/* ^H: erase character */
+	if(c == 0x08){	/* ^H: erase character */
+		if(t->what == Body && t->w->indent[SPACESINDENT])
+			return spacesindentbswidth(t);
 		return 1;
+	}
 	q = t->q0;
 	skipping = TRUE;
 	while(q > 0){
@@ -775,8 +799,19 @@
 		for(i=0; i<t->file->ntext; i++)
 			textfill(t->file->text[i]);
 		return;
+	case '\t':
+		if(t->what == Body && t->w->indent[SPACESINDENT]){
+			nnb = textbswidth(t, 0x15);
+			if(nnb == 1 && textreadc(t, t->q0-1) == '\n')
+				nnb = 0;
+			nnb = t->tabstop - nnb % t->tabstop;
+			rp = runemalloc(nnb);
+			for(nr = 0; nr < nnb; nr++)
+				rp[nr] = ' ';
+		}
+		break;
 	case '\n':
-		if(t->what == Body && t->w->autoindent){
+		if(t->what == Body && t->w->indent[AUTOINDENT]){
 			/* find beginning of previous line using backspace code */
 			nnb = textbswidth(t, 0x15); /* ^U case */
 			rp = runemalloc(nnb + 1);
--- a/sys/src/cmd/acme/util.c
+++ b/sys/src/cmd/acme/util.c
@@ -85,7 +85,8 @@
 		runemove(r, incl[i], n);
 		winaddincl(w, r, n);
 	}
-	w->autoindent = globalautoindent;
+	for(i=0; i<NINDENT; i++)
+		w->indent[i] = globalindent[i];
 	return w;
 }
 
--- a/sys/src/cmd/acme/wind.c
+++ b/sys/src/cmd/acme/wind.c
@@ -20,7 +20,7 @@
 	File *f;
 	Reffont *rf;
 	Rune *rp;
-	int nc;
+	int nc, i;
 
 	w->tag.w = w;
 	w->taglines = 1;
@@ -78,13 +78,14 @@
 	draw(screen, br, button, nil, button->r.min);
 	w->filemenu = TRUE;
 	w->maxlines = w->body.maxlines;
-	w->autoindent = globalautoindent;
+	for(i=0; i<NINDENT; i++)
+		w->indent[i] = globalindent[i];
 	if(clone){
 		w->dirty = clone->dirty;
-		w->autoindent = clone->autoindent;
+		for(i=0; i<NINDENT; i++)
+			w->indent[i] = clone->indent[i];
 		textsetselect(&w->body, clone->body.q0, clone->body.q1);
 		winsettag(w);
-		w->autoindent = clone->autoindent;
 	}
 }