plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

commit 161742770e63fec914b0290def3ac063ad3d2cf9
parent cc9ecfbee7b1c346bd6b35bf1b9501bdf7eb9c21
Author: Russ Cox <rsc@swtch.com>
Date:   Wed, 24 Apr 2019 11:02:34 -0400

acme: delete trailing spaces during Put in autoindent mode

Autoident mode is the leading cause of trailing spaces on lines.
Remove them during Put to make various picky tools happier.
The changes during Put are added as a separate entry to the
file history, so that the first Undo after Put restores the spaces.

Diffstat:
Msrc/cmd/acme/exec.c | 105++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
1 file changed, 64 insertions(+), 41 deletions(-)

diff --git a/src/cmd/acme/exec.c b/src/cmd/acme/exec.c @@ -692,42 +692,10 @@ checksha1(char *name, File *f, Dir *d) } } -static uint -trimspaces(Rune *r, uint *np, int eof) -{ - uint i, w, nonspace, n; - Rune c; - - nonspace = 0; - w = 0; - n = *np; - for(i=0; i<n; i++) { - c = r[i]; - if(c == '\n') - w = nonspace; - r[w++] = c; - if(c != ' ' && c != '\t') - nonspace = w; - } - if(nonspace > 0 && nonspace < w) { - // Trailing spaces at end of buffer. - // Tell caller to reread them with what follows, - // so we can determine whether they need trimming. - // Unless the trailing spaces are the entire buffer, - // in which case let them through to avoid an infinite loop - // if an entire buffer fills with spaces. - // At EOF, just consume the spaces. - if(!eof) - *np = n - (w - nonspace); - w = nonspace; - } - return w; -} - void putfile(File *f, int q0, int q1, Rune *namer, int nname) { - uint n, nn, m; + uint n, m; Rune *r; Biobuf *b; char *s, *name; @@ -754,6 +722,7 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname) goto Rescue1; } } + fd = create(name, OWRITE, 0666); if(fd < 0){ warning(nil, "can't create file %s: %r\n", name); @@ -782,14 +751,7 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname) if(n > BUFSIZE/UTFmax) n = BUFSIZE/UTFmax; bufread(&f->b, q, r, n); - nn = n; - // An attempt at automatically trimming trailing spaces. - // Breaks programs that inspect body file and think it will match on-disk file - // when window is clean. Should apply the changes to the actual window instead. - // Later. - if(0 && w->autoindent) - nn = trimspaces(r, &n, q+n==q1); - m = snprint(s, BUFSIZE+1, "%.*S", nn, r); + m = snprint(s, BUFSIZE+1, "%.*S", n, r); sha1((uchar*)s, m, nil, h); if(Bwrite(b, s, m) != m){ warning(nil, "can't write file %s: %r\n", name); @@ -868,6 +830,65 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname) free(name); } +static void +trimspaces(Text *et) +{ + File *f; + Rune *r; + Text *t; + uint q0, n, delstart; + int c, i, marked; + + t = &et->w->body; + f = t->file; + marked = 0; + + if(t->w!=nil && et->w!=t->w){ + /* can this happen when t == &et->w->body? */ + c = 'M'; + if(et->w) + c = et->w->owner; + winlock(t->w, c); + } + + r = fbufalloc(); + q0 = f->b.nc; + delstart = q0; /* end of current space run, or 0 if no active run; = q0 to delete spaces before EOF */ + while(q0 > 0) { + n = RBUFSIZE; + if(n > q0) + n = q0; + q0 -= n; + bufread(&f->b, q0, r, n); + for(i=n; ; i--) { + if(i == 0 || (r[i-1] != ' ' && r[i-1] != '\t')) { + // Found non-space or start of buffer. Delete active space run. + if(q0+i < delstart) { + if(!marked) { + marked = 1; + seq++; + filemark(f); + } + textdelete(t, q0+i, delstart, TRUE); + } + if(i == 0) { + /* keep run active into tail of next buffer */ + if(delstart > 0) + delstart = q0; + break; + } + delstart = 0; + if(r[i-1] == '\n') + delstart = q0+i-1; /* delete spaces before this newline */ + } + } + } + fbuffree(r); + + if(t->w!=nil && et->w!=t->w) + winunlock(t->w); +} + void put(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg) { @@ -890,6 +911,8 @@ put(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg) warning(nil, "no file name\n"); return; } + if(w->autoindent) + trimspaces(et); namer = bytetorune(name, &nname); putfile(f, 0, f->b.nc, namer, nname); xfidlog(w, "put");