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;
}
}