mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-27 11:52:03 +00:00
acme: angle bracket tag matching, for XML, HTML etc
http://codereview.appspot.com/98042
This commit is contained in:
parent
6f4a41c68c
commit
e47d0a1e98
2 changed files with 111 additions and 0 deletions
|
@ -198,6 +198,7 @@ struct Text
|
||||||
uint textbacknl(Text*, uint, uint);
|
uint textbacknl(Text*, uint, uint);
|
||||||
uint textbsinsert(Text*, uint, Rune*, uint, int, int*);
|
uint textbsinsert(Text*, uint, Rune*, uint, int, int*);
|
||||||
int textbswidth(Text*, Rune);
|
int textbswidth(Text*, Rune);
|
||||||
|
int textclickhtmlmatch(Text*, uint*, uint*);
|
||||||
int textclickmatch(Text*, int, int, int, uint*);
|
int textclickmatch(Text*, int, int, int, uint*);
|
||||||
void textclose(Text*);
|
void textclose(Text*);
|
||||||
void textcolumnate(Text*, Dirlist**, int);
|
void textcolumnate(Text*, Dirlist**, int);
|
||||||
|
|
|
@ -1381,6 +1381,10 @@ textdoubleclick(Text *t, uint *q0, uint *q1)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(textclickhtmlmatch(t, q0, q1))
|
||||||
|
return;
|
||||||
|
|
||||||
/* try filling out word to right */
|
/* try filling out word to right */
|
||||||
while(*q1<t->file->b.nc && isalnum(textreadc(t, *q1)))
|
while(*q1<t->file->b.nc && isalnum(textreadc(t, *q1)))
|
||||||
(*q1)++;
|
(*q1)++;
|
||||||
|
@ -1417,6 +1421,112 @@ textclickmatch(Text *t, int cl, int cr, int dir, uint *q)
|
||||||
return cl=='\n' && nest==1;
|
return cl=='\n' && nest==1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is the text starting at location q an html tag?
|
||||||
|
// Return 1 for <a>, -1 for </a>, 0 for no tag or <a />.
|
||||||
|
// Set *q1, if non-nil, to the location after the tag.
|
||||||
|
static int
|
||||||
|
ishtmlstart(Text *t, uint q, uint *q1)
|
||||||
|
{
|
||||||
|
int c, c1, c2;
|
||||||
|
|
||||||
|
if(q+2 > t->file->b.nc)
|
||||||
|
return 0;
|
||||||
|
if(textreadc(t, q++) != '<')
|
||||||
|
return 0;
|
||||||
|
c = textreadc(t, q++);
|
||||||
|
c1 = c;
|
||||||
|
c2 = c;
|
||||||
|
while(c != '>') {
|
||||||
|
if(q >= t->file->b.nc)
|
||||||
|
return 0;
|
||||||
|
c2 = c;
|
||||||
|
c = textreadc(t, q++);
|
||||||
|
}
|
||||||
|
if(q1)
|
||||||
|
*q1 = q;
|
||||||
|
if(c1 == '/') // closing tag
|
||||||
|
return -1;
|
||||||
|
if(c2 == '/' || c2 == '!') // open + close tag or comment
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the text ending at location q an html tag?
|
||||||
|
// Return 1 for <a>, -1 for </a>, 0 for no tag or <a />.
|
||||||
|
// Set *q0, if non-nil, to the start of the tag.
|
||||||
|
static int
|
||||||
|
ishtmlend(Text *t, uint q, uint *q0)
|
||||||
|
{
|
||||||
|
int c, c1, c2;
|
||||||
|
|
||||||
|
if(q < 2)
|
||||||
|
return 0;
|
||||||
|
if(textreadc(t, --q) != '>')
|
||||||
|
return 0;
|
||||||
|
c = textreadc(t, --q);
|
||||||
|
c1 = c;
|
||||||
|
c2 = c;
|
||||||
|
while(c != '<') {
|
||||||
|
if(q == 0)
|
||||||
|
return 0;
|
||||||
|
c1 = c;
|
||||||
|
c = textreadc(t, --q);
|
||||||
|
}
|
||||||
|
if(q0)
|
||||||
|
*q0 = q;
|
||||||
|
if(c1 == '/') // closing tag
|
||||||
|
return -1;
|
||||||
|
if(c2 == '/' || c2 == '!') // open + close tag or comment
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
textclickhtmlmatch(Text *t, uint *q0, uint *q1)
|
||||||
|
{
|
||||||
|
int depth, n;
|
||||||
|
uint q, nq;
|
||||||
|
|
||||||
|
q = *q0;
|
||||||
|
// after opening tag? scan forward for closing tag
|
||||||
|
if(ishtmlend(t, q, nil) == 1) {
|
||||||
|
depth = 1;
|
||||||
|
while(q < t->file->b.nc) {
|
||||||
|
n = ishtmlstart(t, q, &nq);
|
||||||
|
if(n != 0) {
|
||||||
|
depth += n;
|
||||||
|
if(depth == 0) {
|
||||||
|
*q1 = q;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
q = nq;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// before closing tag? scan backward for opening tag
|
||||||
|
if(ishtmlstart(t, q, nil) == -1) {
|
||||||
|
depth = -1;
|
||||||
|
while(q > 0) {
|
||||||
|
n = ishtmlend(t, q, &nq);
|
||||||
|
if(n != 0) {
|
||||||
|
depth += n;
|
||||||
|
if(depth == 0) {
|
||||||
|
*q0 = q;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
q = nq;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
q--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint
|
uint
|
||||||
textbacknl(Text *t, uint p, uint n)
|
textbacknl(Text *t, uint p, uint n)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue