From 4757debd0b5935dae94944c35c3cac74b14aa209 Mon Sep 17 00:00:00 2001 From: spew Date: Wed, 1 Aug 2018 11:14:59 -0400 Subject: [PATCH] acme: add spacesindent mode --- sys/man/1/acme | 23 ++++++++++++++++++- sys/src/cmd/acme/acme.c | 7 ++++-- sys/src/cmd/acme/dat.h | 11 +++++++-- sys/src/cmd/acme/exec.c | 51 +++++++++++++++++++++++++---------------- sys/src/cmd/acme/look.c | 6 +++-- sys/src/cmd/acme/text.c | 39 +++++++++++++++++++++++++++++-- sys/src/cmd/acme/util.c | 3 ++- sys/src/cmd/acme/wind.c | 9 ++++---- 8 files changed, 115 insertions(+), 34 deletions(-) diff --git a/sys/man/1/acme b/sys/man/1/acme index 2220fa670..36fbd8ae3 100644 --- a/sys/man/1/acme +++ b/sys/man/1/acme @@ -4,7 +4,7 @@ acme, win \- interactive text windows .SH SYNOPSIS .B acme [ -.B -ab +.B -aib ] [ .B -c @@ -174,6 +174,16 @@ The option .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 @@ -430,6 +440,17 @@ Place selected text in snarf buffer. 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 character. diff --git a/sys/src/cmd/acme/acme.c b/sys/src/cmd/acme/acme.c index 5c67c9bfd..69ea715ce 100644 --- a/sys/src/cmd/acme/acme.c +++ b/sys/src/cmd/acme/acme.c @@ -66,7 +66,7 @@ threadmain(int argc, char *argv[]) loadfile = nil; ARGBEGIN{ case 'a': - globalautoindent = TRUE; + globalindent[AUTOINDENT] = TRUE; break; case 'b': bartflag = TRUE; @@ -89,6 +89,9 @@ threadmain(int argc, char *argv[]) if(fontnames[1] == nil) goto Usage; break; + case 'i': + globalindent[SPACESINDENT] = TRUE; + break; case 'l': loadfile = ARGF(); if(loadfile == nil) @@ -96,7 +99,7 @@ threadmain(int argc, char *argv[]) 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 diff --git a/sys/src/cmd/acme/dat.h b/sys/src/cmd/acme/dat.h index 2c4d40d79..070be119b 100644 --- a/sys/src/cmd/acme/dat.h +++ b/sys/src/cmd/acme/dat.h @@ -224,6 +224,13 @@ void textsetselect(Text*, uint, uint); void textshow(Text*, uint, uint, int); void texttype(Text*, Rune); +enum +{ + SPACESINDENT = 0, + AUTOINDENT, + NINDENT, +}; + struct Window { QLock; @@ -235,7 +242,7 @@ struct Window uchar isscratch; uchar filemenu; uchar dirty; - uchar autoindent; + uchar indent[NINDENT]; uchar showdel; uint noredraw; int id; @@ -538,7 +545,7 @@ int plumbeditfd; char wdir[]; int editing; int messagesize; /* negotiated in 9P version setup */ -int globalautoindent; +int globalindent[NINDENT]; Channel *cplumb; /* chan(Plumbmsg*) */ Channel *cwait; /* chan(Waitmsg) */ diff --git a/sys/src/cmd/acme/exec.c b/sys/src/cmd/acme/exec.c index fa18e8af2..baf125927 100644 --- a/sys/src/cmd/acme/exec.c +++ b/sys/src/cmd/acme/exec.c @@ -73,7 +73,7 @@ Exectab exectab[] = { { 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 @@ Exectab exectab[] = { { 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 @@ incl(Text *et, Text*, Text *argt, int, int, Rune *arg, int narg) 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 diff --git a/sys/src/cmd/acme/look.c b/sys/src/cmd/acme/look.c index d8882995a..60ade8b25 100644 --- a/sys/src/cmd/acme/look.c +++ b/sys/src/cmd/acme/look.c @@ -663,9 +663,11 @@ openfile(Text *t, Expand *e) 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; diff --git a/sys/src/cmd/acme/text.c b/sys/src/cmd/acme/text.c index 7380d0163..b96213a68 100644 --- a/sys/src/cmd/acme/text.c +++ b/sys/src/cmd/acme/text.c @@ -502,6 +502,27 @@ textreadc(Text *t, uint q) 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 @@ textbswidth(Text *t, Rune c) 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 @@ texttype(Text *t, Rune r) for(i=0; ifile->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); diff --git a/sys/src/cmd/acme/util.c b/sys/src/cmd/acme/util.c index aa5d3ac14..bf00a9e65 100644 --- a/sys/src/cmd/acme/util.c +++ b/sys/src/cmd/acme/util.c @@ -85,7 +85,8 @@ errorwin1(Rune *dir, int ndir, Rune **incl, int nincl) runemove(r, incl[i], n); winaddincl(w, r, n); } - w->autoindent = globalautoindent; + for(i=0; iindent[i] = globalindent[i]; return w; } diff --git a/sys/src/cmd/acme/wind.c b/sys/src/cmd/acme/wind.c index 90acb486b..7c222a17c 100644 --- a/sys/src/cmd/acme/wind.c +++ b/sys/src/cmd/acme/wind.c @@ -20,7 +20,7 @@ wininit(Window *w, Window *clone, Rectangle r) File *f; Reffont *rf; Rune *rp; - int nc; + int nc, i; w->tag.w = w; w->taglines = 1; @@ -78,13 +78,14 @@ wininit(Window *w, Window *clone, Rectangle r) draw(screen, br, button, nil, button->r.min); w->filemenu = TRUE; w->maxlines = w->body.maxlines; - w->autoindent = globalautoindent; + for(i=0; iindent[i] = globalindent[i]; if(clone){ w->dirty = clone->dirty; - w->autoindent = clone->autoindent; + for(i=0; iindent[i] = clone->indent[i]; textsetselect(&w->body, clone->body.q0, clone->body.q1); winsettag(w); - w->autoindent = clone->autoindent; } }