acme: add spacesindent mode
This commit is contained in:
parent
2b619dc966
commit
4757debd0b
|
@ -4,7 +4,7 @@ acme, win \- interactive text windows
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B acme
|
.B acme
|
||||||
[
|
[
|
||||||
.B -ab
|
.B -aib
|
||||||
]
|
]
|
||||||
[
|
[
|
||||||
.B -c
|
.B -c
|
||||||
|
@ -174,6 +174,16 @@ The option
|
||||||
.B -a
|
.B -a
|
||||||
causes each window to start in
|
causes each window to start in
|
||||||
autoindent mode.
|
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
|
.SS "Directory context
|
||||||
Each window's tag names a directory: explicitly if the window
|
Each window's tag names a directory: explicitly if the window
|
||||||
holds a directory; implicitly if it holds a regular file
|
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
|
Arrange the windows in the column from top to bottom in lexicographical
|
||||||
order based on their names.
|
order based on their names.
|
||||||
.TP
|
.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
|
.B Tab
|
||||||
Set the width of tab stops for this window to the value of the argument, in units of widths of the zero
|
Set the width of tab stops for this window to the value of the argument, in units of widths of the zero
|
||||||
character.
|
character.
|
||||||
|
|
|
@ -66,7 +66,7 @@ threadmain(int argc, char *argv[])
|
||||||
loadfile = nil;
|
loadfile = nil;
|
||||||
ARGBEGIN{
|
ARGBEGIN{
|
||||||
case 'a':
|
case 'a':
|
||||||
globalautoindent = TRUE;
|
globalindent[AUTOINDENT] = TRUE;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
bartflag = TRUE;
|
bartflag = TRUE;
|
||||||
|
@ -89,6 +89,9 @@ threadmain(int argc, char *argv[])
|
||||||
if(fontnames[1] == nil)
|
if(fontnames[1] == nil)
|
||||||
goto Usage;
|
goto Usage;
|
||||||
break;
|
break;
|
||||||
|
case 'i':
|
||||||
|
globalindent[SPACESINDENT] = TRUE;
|
||||||
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
loadfile = ARGF();
|
loadfile = ARGF();
|
||||||
if(loadfile == nil)
|
if(loadfile == nil)
|
||||||
|
@ -96,7 +99,7 @@ threadmain(int argc, char *argv[])
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Usage:
|
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");
|
exits("usage");
|
||||||
}ARGEND
|
}ARGEND
|
||||||
|
|
||||||
|
|
|
@ -224,6 +224,13 @@ void textsetselect(Text*, uint, uint);
|
||||||
void textshow(Text*, uint, uint, int);
|
void textshow(Text*, uint, uint, int);
|
||||||
void texttype(Text*, Rune);
|
void texttype(Text*, Rune);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SPACESINDENT = 0,
|
||||||
|
AUTOINDENT,
|
||||||
|
NINDENT,
|
||||||
|
};
|
||||||
|
|
||||||
struct Window
|
struct Window
|
||||||
{
|
{
|
||||||
QLock;
|
QLock;
|
||||||
|
@ -235,7 +242,7 @@ struct Window
|
||||||
uchar isscratch;
|
uchar isscratch;
|
||||||
uchar filemenu;
|
uchar filemenu;
|
||||||
uchar dirty;
|
uchar dirty;
|
||||||
uchar autoindent;
|
uchar indent[NINDENT];
|
||||||
uchar showdel;
|
uchar showdel;
|
||||||
uint noredraw;
|
uint noredraw;
|
||||||
int id;
|
int id;
|
||||||
|
@ -538,7 +545,7 @@ int plumbeditfd;
|
||||||
char wdir[];
|
char wdir[];
|
||||||
int editing;
|
int editing;
|
||||||
int messagesize; /* negotiated in 9P version setup */
|
int messagesize; /* negotiated in 9P version setup */
|
||||||
int globalautoindent;
|
int globalindent[NINDENT];
|
||||||
|
|
||||||
Channel *cplumb; /* chan(Plumbmsg*) */
|
Channel *cplumb; /* chan(Plumbmsg*) */
|
||||||
Channel *cwait; /* chan(Waitmsg) */
|
Channel *cwait; /* chan(Waitmsg) */
|
||||||
|
|
|
@ -73,7 +73,7 @@ Exectab exectab[] = {
|
||||||
{ L"Get", get, FALSE, TRUE, XXX },
|
{ L"Get", get, FALSE, TRUE, XXX },
|
||||||
{ L"ID", id, FALSE, XXX, XXX },
|
{ L"ID", id, FALSE, XXX, XXX },
|
||||||
{ L"Incl", incl, 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"Kill", kill, FALSE, XXX, XXX },
|
||||||
{ L"Load", dump, FALSE, FALSE, XXX },
|
{ L"Load", dump, FALSE, FALSE, XXX },
|
||||||
{ L"Local", local, FALSE, XXX, XXX },
|
{ L"Local", local, FALSE, XXX, XXX },
|
||||||
|
@ -87,6 +87,7 @@ Exectab exectab[] = {
|
||||||
{ L"Send", sendx, TRUE, XXX, XXX },
|
{ L"Send", sendx, TRUE, XXX, XXX },
|
||||||
{ L"Snarf", cut, FALSE, TRUE, FALSE },
|
{ L"Snarf", cut, FALSE, TRUE, FALSE },
|
||||||
{ L"Sort", sort, FALSE, XXX, XXX },
|
{ L"Sort", sort, FALSE, XXX, XXX },
|
||||||
|
{ L"Spaces", indent, FALSE, SPACESINDENT, XXX },
|
||||||
{ L"Tab", tab, FALSE, XXX, XXX },
|
{ L"Tab", tab, FALSE, XXX, XXX },
|
||||||
{ L"Undo", undo, FALSE, TRUE, XXX },
|
{ L"Undo", undo, FALSE, TRUE, XXX },
|
||||||
{ L"Zerox", zeroxx, FALSE, XXX, XXX },
|
{ L"Zerox", zeroxx, FALSE, XXX, XXX },
|
||||||
|
@ -1087,57 +1088,67 @@ incl(Text *et, Text*, Text *argt, int, int, Rune *arg, int narg)
|
||||||
enum {
|
enum {
|
||||||
IGlobal = -2,
|
IGlobal = -2,
|
||||||
IError = -1,
|
IError = -1,
|
||||||
Ion = 0,
|
|
||||||
Ioff = 1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
indentval(Rune *s, int n)
|
indentval(Rune *s, int n, int type)
|
||||||
{
|
{
|
||||||
|
static char *strs[] = {
|
||||||
|
[SPACESINDENT] "Spaces",
|
||||||
|
[AUTOINDENT] "Indent",
|
||||||
|
};
|
||||||
|
|
||||||
if(n < 2)
|
if(n < 2)
|
||||||
return IError;
|
return IError;
|
||||||
if(runestrncmp(s, L"ON", n) == 0){
|
if(runestrncmp(s, L"ON", n) == 0){
|
||||||
globalautoindent = TRUE;
|
globalindent[type] = TRUE;
|
||||||
warning(nil, "Indent ON\n");
|
warning(nil, "%s ON\n", strs[type]);
|
||||||
return IGlobal;
|
return IGlobal;
|
||||||
}
|
}
|
||||||
if(runestrncmp(s, L"OFF", n) == 0){
|
if(runestrncmp(s, L"OFF", n) == 0){
|
||||||
globalautoindent = FALSE;
|
globalindent[type] = FALSE;
|
||||||
warning(nil, "Indent OFF\n");
|
warning(nil, "%s OFF\n", strs[type]);
|
||||||
return IGlobal;
|
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
|
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
|
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;
|
Rune *a, *r;
|
||||||
Window *w;
|
Window *w;
|
||||||
int na, len, autoindent;
|
int na, len, ival;
|
||||||
|
|
||||||
w = nil;
|
w = nil;
|
||||||
if(et!=nil && et->w!=nil)
|
if(et!=nil && et->w!=nil)
|
||||||
w = et->w;
|
w = et->w;
|
||||||
autoindent = IError;
|
ival = IError;
|
||||||
getarg(argt, FALSE, TRUE, &r, &len);
|
getarg(argt, FALSE, TRUE, &r, &len);
|
||||||
if(r!=nil && len>0)
|
if(r!=nil && len>0)
|
||||||
autoindent = indentval(r, len);
|
ival = indentval(r, len, type);
|
||||||
else{
|
else{
|
||||||
a = findbl(arg, narg, &na);
|
a = findbl(arg, narg, &na);
|
||||||
if(a != arg)
|
if(a != arg)
|
||||||
autoindent = indentval(arg, narg-na);
|
ival = indentval(arg, narg-na, type);
|
||||||
}
|
}
|
||||||
if(autoindent == IGlobal)
|
if(ival == IGlobal)
|
||||||
allwindows(fixindent, nil);
|
allwindows(fixindent, (void*)type);
|
||||||
else if(w != nil && autoindent >= 0)
|
else if(w != nil && ival >= 0)
|
||||||
w->autoindent = autoindent;
|
w->indent[type] = ival;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -663,9 +663,11 @@ openfile(Text *t, Expand *e)
|
||||||
runemove(rp, ow->incl[i], n);
|
runemove(rp, ow->incl[i], n);
|
||||||
winaddincl(w, rp, n);
|
winaddincl(w, rp, n);
|
||||||
}
|
}
|
||||||
w->autoindent = ow->autoindent;
|
for(i=0; i < NINDENT; i++)
|
||||||
|
w->indent[i] = ow->indent[i];
|
||||||
}else
|
}else
|
||||||
w->autoindent = globalautoindent;
|
for(i=0; i < NINDENT; i++)
|
||||||
|
w->indent[i] = globalindent[i];
|
||||||
}
|
}
|
||||||
if(e->a1 == e->a0)
|
if(e->a1 == e->a0)
|
||||||
eval = FALSE;
|
eval = FALSE;
|
||||||
|
|
|
@ -502,6 +502,27 @@ textreadc(Text *t, uint q)
|
||||||
return r;
|
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
|
int
|
||||||
textbswidth(Text *t, Rune c)
|
textbswidth(Text *t, Rune c)
|
||||||
{
|
{
|
||||||
|
@ -510,8 +531,11 @@ textbswidth(Text *t, Rune c)
|
||||||
int skipping;
|
int skipping;
|
||||||
|
|
||||||
/* there is known to be at least one character to erase */
|
/* 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;
|
return 1;
|
||||||
|
}
|
||||||
q = t->q0;
|
q = t->q0;
|
||||||
skipping = TRUE;
|
skipping = TRUE;
|
||||||
while(q > 0){
|
while(q > 0){
|
||||||
|
@ -775,8 +799,19 @@ texttype(Text *t, Rune r)
|
||||||
for(i=0; i<t->file->ntext; i++)
|
for(i=0; i<t->file->ntext; i++)
|
||||||
textfill(t->file->text[i]);
|
textfill(t->file->text[i]);
|
||||||
return;
|
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':
|
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 */
|
/* find beginning of previous line using backspace code */
|
||||||
nnb = textbswidth(t, 0x15); /* ^U case */
|
nnb = textbswidth(t, 0x15); /* ^U case */
|
||||||
rp = runemalloc(nnb + 1);
|
rp = runemalloc(nnb + 1);
|
||||||
|
|
|
@ -85,7 +85,8 @@ errorwin1(Rune *dir, int ndir, Rune **incl, int nincl)
|
||||||
runemove(r, incl[i], n);
|
runemove(r, incl[i], n);
|
||||||
winaddincl(w, r, n);
|
winaddincl(w, r, n);
|
||||||
}
|
}
|
||||||
w->autoindent = globalautoindent;
|
for(i=0; i<NINDENT; i++)
|
||||||
|
w->indent[i] = globalindent[i];
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ wininit(Window *w, Window *clone, Rectangle r)
|
||||||
File *f;
|
File *f;
|
||||||
Reffont *rf;
|
Reffont *rf;
|
||||||
Rune *rp;
|
Rune *rp;
|
||||||
int nc;
|
int nc, i;
|
||||||
|
|
||||||
w->tag.w = w;
|
w->tag.w = w;
|
||||||
w->taglines = 1;
|
w->taglines = 1;
|
||||||
|
@ -78,13 +78,14 @@ wininit(Window *w, Window *clone, Rectangle r)
|
||||||
draw(screen, br, button, nil, button->r.min);
|
draw(screen, br, button, nil, button->r.min);
|
||||||
w->filemenu = TRUE;
|
w->filemenu = TRUE;
|
||||||
w->maxlines = w->body.maxlines;
|
w->maxlines = w->body.maxlines;
|
||||||
w->autoindent = globalautoindent;
|
for(i=0; i<NINDENT; i++)
|
||||||
|
w->indent[i] = globalindent[i];
|
||||||
if(clone){
|
if(clone){
|
||||||
w->dirty = clone->dirty;
|
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);
|
textsetselect(&w->body, clone->body.q0, clone->body.q1);
|
||||||
winsettag(w);
|
winsettag(w);
|
||||||
w->autoindent = clone->autoindent;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue