From 161742770e63fec914b0290def3ac063ad3d2cf9 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 24 Apr 2019 11:02:34 -0400 Subject: 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. --- src/cmd/acme/exec.c | 105 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 41 deletions(-) (limited to 'src/cmd/acme') diff --git a/src/cmd/acme/exec.c b/src/cmd/acme/exec.c index b3bb0ac3..ff491601 100644 --- 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 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"); -- cgit v1.2.3 From 7a241631b2097b1acda431ff059b771c5d1c391c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 10 Jun 2019 16:01:10 -0400 Subject: acme: accept expanded URLs in look Just as look expands a click in /etc/passwd to the full name (provided that file exists), it now expands a click in https://9fans.net/ to the full URL (provided the prefix is http:// or https://). Probably more adjustment is needed. --- src/cmd/acme/look.c | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) (limited to 'src/cmd/acme') diff --git a/src/cmd/acme/look.c b/src/cmd/acme/look.c index cbbc71bf..44e23cca 100644 --- a/src/cmd/acme/look.c +++ b/src/cmd/acme/look.c @@ -30,7 +30,7 @@ plumbthread(void *v) USED(v); threadsetname("plumbproc"); - + /* * Loop so that if plumber is restarted, acme need not be. */ @@ -46,7 +46,7 @@ plumbthread(void *v) } plumbeditfid = fid; plumbsendfid = plumbopenfid("send", OWRITE|OCEXEC); - + /* * Relay messages. */ @@ -432,9 +432,9 @@ includename(Text *t, Rune *r, int n) char buf[128]; Rune Lsysinclude[] = { '/', 's', 'y', 's', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 }; Rune Lusrinclude[] = { '/', 'u', 's', 'r', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 }; - Rune Lusrlocalinclude[] = { '/', 'u', 's', 'r', '/', 'l', 'o', 'c', 'a', 'l', + Rune Lusrlocalinclude[] = { '/', 'u', 's', 'r', '/', 'l', 'o', 'c', 'a', 'l', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 }; - Rune Lusrlocalplan9include[] = { '/', 'u', 's', 'r', '/', 'l', 'o', 'c', 'a', 'l', + Rune Lusrlocalplan9include[] = { '/', 'u', 's', 'r', '/', 'l', 'o', 'c', 'a', 'l', '/', 'p', 'l', 'a', 'n', '9', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 }; Runestr file; int i; @@ -443,7 +443,7 @@ includename(Text *t, Rune *r, int n) sprint(buf, "/%s/include", objtype); objdir = bytetorune(buf, &i); objdir = runerealloc(objdir, i+1); - objdir[i] = '\0'; + objdir[i] = '\0'; } w = t->w; @@ -514,6 +514,19 @@ dirname(Text *t, Rune *r, int n) return tmp; } +static int +texthas(Text *t, uint q0, Rune *r) +{ + int i; + + if((int)q0 < 0) + return FALSE; + for(i=0; r[i]; i++) + if(q0+i >= t->file->b.nc || textreadc(t, q0+i) != r[i]) + return FALSE; + return TRUE; +} + int expandfile(Text *t, uint q0, uint q1, Expand *e) { @@ -522,12 +535,14 @@ expandfile(Text *t, uint q0, uint q1, Expand *e) Rune *r, c; Window *w; Runestr rs; + Rune Lhttpcss[] = {'h', 't', 't', 'p', ':', '/', '/', 0}; + Rune Lhttpscss[] = {'h', 't', 't', 'p', 's', ':', '/', '/', 0}; amax = q1; if(q1 == q0){ colon = -1; while(q1file->b.nc && isfilec(c=textreadc(t, q1))){ - if(c == ':'){ + if(c == ':' && !texthas(t, q1-4, Lhttpcss) && !texthas(t, q1-5, Lhttpscss)){ colon = q1; break; } @@ -535,7 +550,7 @@ expandfile(Text *t, uint q0, uint q1, Expand *e) } while(q0>0 && (isfilec(c=textreadc(t, q0-1)) || isaddrc(c) || isregexc(c))){ q0--; - if(colon<0 && c==':') + if(colon<0 && c==':' && !texthas(t, q0-4, Lhttpcss) && !texthas(t, q0-5, Lhttpscss)) colon = q0; } /* @@ -565,8 +580,23 @@ expandfile(Text *t, uint q0, uint q1, Expand *e) if(n == 0) return FALSE; /* see if it's a file name */ - r = runemalloc(n); + r = runemalloc(n+1); bufread(&t->file->b, q0, r, n); + r[n] = 0; + /* is it a URL? look for http:// and https:// prefix */ + if(runestrncmp(r, Lhttpcss, 7) == 0 || runestrncmp(r, Lhttpscss, 8) == 0){ + // Avoid capturing end-of-sentence punctuation. + if(r[n-1] == '.') { + e->q1--; + n--; + } + e->name = r; + e->nname = n; + e->u.at = t; + e->a0 = e->q1; + e->a1 = e->q1; + return TRUE; + } /* first, does it have bad chars? */ nname = -1; for(i=0; i