Mercurial > projects > ddmd
view dmd/ddoc/Util.d @ 153:560eaedcb7a2
added lots of ddoc code, still needs much care
added helpers functions in ddoc.Util
author | trass3r |
---|---|
date | Wed, 15 Sep 2010 04:18:46 +0200 |
parents | |
children |
line wrap: on
line source
module dmd.ddoc.Util; public import std.string : cmp, icmp; /***************************************** * Return !=0 if comment consists entirely of "ditto". */ bool isDitto(string comment) { if (comment) { string p = skipwhitespace(comment); if (icmp(p, "ditto") == 0 && skipwhitespace(p[5..$])[0] == 0) return true; } return false; } /********************************************** * Skip white space. */ string skipwhitespace(string p) { size_t i = 0; for (; true; i++) { switch (p[i]) { case ' ': case '\t': case '\n': continue; default: } break; } return p[i .. $]; } /+ /************************************************ * Scan forward to one of: * start of identifier * beginning of next line * end of buf */ unsigned skiptoident(OutBuffer buf, size_t i) { while (i < buf.offset) { dchar_t c; size_t oi = i; if (utf_decodeChar((unsigned char *)buf.data, buf.offset, &i, &c)) /* Ignore UTF errors, but still consume input */ break; if (c >= 0x80) { if (!isUniAlpha(c)) continue; } else if (!(isalpha(c) || c == '_' || c == '\n')) continue; i = oi; break; } return i; } /************************************************ * Scan forward past end of identifier. */ unsigned skippastident(OutBuffer buf, size_t i) { while (i < buf.offset) { dchar_t c; size_t oi = i; if (utf_decodeChar((unsigned char *)buf.data, buf.offset, &i, &c)) /* Ignore UTF errors, but still consume input */ break; if (c >= 0x80) { if (isUniAlpha(c)) continue; } else if (isalnum(c) || c == '_') continue; i = oi; break; } return i; } /************************************************ * Scan forward past URL starting at i. * We don't want to highlight parts of a URL. * Returns: * i if not a URL * index just past it if it is a URL */ unsigned skippastURL(OutBuffer buf, size_t i) { unsigned length = buf.offset - i; unsigned char *p = &buf.data[i]; unsigned j; unsigned sawdot = 0; if (length > 7 && memicmp((char *)p, "http://", 7) == 0) { j = 7; } else if (length > 8 && memicmp((char *)p, "https://", 8) == 0) { j = 8; } else goto Lno; for (; j < length; j++) { unsigned char c = p[j]; if (isalnum(c)) continue; if (c == '-' || c == '_' || c == '?' || c == '=' || c == '%' || c == '&' || c == '/' || c == '+' || c == '#' || c == '~') continue; if (c == '.') { sawdot = 1; continue; } break; } if (sawdot) return i + j; Lno: return i; } /**************************************************** */ bool isKeyword(string p) { static string[] table = [ "true", "false", "null" ]; for (int i = 0; i < table.length; i++) { if (table[i][0 .. p.length] == p) return true; } return false; } /**************************************************** */ Parameter isFunctionParameter(Dsymbol s, string p) { FuncDeclaration f = s.isFuncDeclaration(); /* f.type may be NULL for template members. */ if (f && f.type) { TypeFunction *tf; if (f.originalType) { tf = (TypeFunction *)f.originalType; } else tf = (TypeFunction *)f.type; if (tf.parameters) { for (size_t k = 0; k < tf.parameters.dim; k++) { Parameter *arg = (Parameter *)tf.parameters.data[k]; if (arg.ident && cmp(arg.ident.toChars(), p, len) == 0) { return arg; } } } } return NULL; } +/ /+ /************************************************** * Highlight text section. */ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset) { //printf("highlightText()\n"); const char *sid = s.ident.toChars(); FuncDeclaration *f = s.isFuncDeclaration(); unsigned char *p; const char *se; int leadingBlank = 1; int inCode = 0; int inComment = 0; // in <!-- ... -. comment unsigned iCodeStart; // start of code section unsigned iLineStart = offset; for (unsigned i = offset; i < buf.offset; i++) { unsigned char c = buf.data[i]; Lcont: switch (c) { case ' ': case '\t': break; case '\n': if (sc && !inCode && i == iLineStart && i + 1 < buf.offset) // if "\n\n" { static char blankline[] = "$(DDOC_BLANKLINE)\n"; i = buf.insert(i, blankline, sizeof(blankline) - 1); } leadingBlank = 1; iLineStart = i + 1; break; case '<': leadingBlank = 0; if (inCode) break; p = &buf.data[i]; // Skip over comments if (p[1] == '!' && p[2] == '-' && p[3] == '-') { unsigned j = i + 4; p += 4; while (1) { if (j == buf.offset) goto L1; if (p[0] == '-' && p[1] == '-' && p[2] == '>') { i = j + 2; // place on closing '>' break; } j++; p++; } break; } // Skip over HTML tag if (isalpha(p[1]) || (p[1] == '/' && isalpha(p[2]))) { unsigned j = i + 2; p += 2; while (1) { if (j == buf.offset) goto L1; if (p[0] == '>') { i = j; // place on closing '>' break; } j++; p++; } break; } L1: // Replace '<' with '<' character entity se = Escape::escapeChar('<'); if (se) { size_t len = strlen(se); buf.remove(i, 1); i = buf.insert(i, se, len); i--; // point to ';' } break; case '>': leadingBlank = 0; if (inCode) break; // Replace '>' with '>' character entity se = Escape::escapeChar('>'); if (se) { size_t len = strlen(se); buf.remove(i, 1); i = buf.insert(i, se, len); i--; // point to ';' } break; case '&': leadingBlank = 0; if (inCode) break; p = &buf.data[i]; if (p[1] == '#' || isalpha(p[1])) break; // already a character entity // Replace '&' with '&' character entity se = Escape::escapeChar('&'); if (se) { size_t len = strlen(se); buf.remove(i, 1); i = buf.insert(i, se, len); i--; // point to ';' } break; case '-': /* A line beginning with --- delimits a code section. * inCode tells us if it is start or end of a code section. */ if (leadingBlank) { int istart = i; int eollen = 0; leadingBlank = 0; while (1) { ++i; if (i >= buf.offset) break; c = buf.data[i]; if (c == '\n') { eollen = 1; break; } if (c == '\r') { eollen = 1; if (i + 1 >= buf.offset) break; if (buf.data[i + 1] == '\n') { eollen = 2; break; } } // BUG: handle UTF PS and LS too if (c != '-') goto Lcont; } if (i - istart < 3) goto Lcont; // We have the start/end of a code section // Remove the entire --- line, including blanks and \n buf.remove(iLineStart, i - iLineStart + eollen); i = iLineStart; if (inCode && (i <= iCodeStart)) { // Empty code section, just remove it completely. inCode = 0; break; } if (inCode) { inCode = 0; // The code section is from iCodeStart to i OutBuffer codebuf; codebuf.write(buf.data + iCodeStart, i - iCodeStart); codebuf.writeByte(0); highlightCode2(sc, s, &codebuf, 0); buf.remove(iCodeStart, i - iCodeStart); i = buf.insert(iCodeStart, codebuf.data, codebuf.offset); i = buf.insert(i, ")\n", 2); i--; } else { static char pre[] = "$(D_CODE \n"; inCode = 1; i = buf.insert(i, pre, sizeof(pre) - 1); iCodeStart = i; i--; // place i on > leadingBlank = true; } } break; default: leadingBlank = 0; if (sc && !inCode && isIdStart(&buf.data[i])) { unsigned j; j = skippastident(buf, i); if (j > i) { unsigned k = skippastURL(buf, i); if (k > i) { i = k - 1; break; } if (buf.data[i] == '_') // leading '_' means no highlight { buf.remove(i, 1); i = j - 1; } else { if (cmp(sid, buf.data + i, j - i) == 0) { i = buf.bracket(i, "$(DDOC_PSYMBOL ", j, ")") - 1; break; } else if (isKeyword(buf.data + i, j - i)) { i = buf.bracket(i, "$(DDOC_KEYWORD ", j, ")") - 1; break; } else { if (f && isFunctionParameter(f, buf.data + i, j - i)) { //printf("highlighting arg '%s', i = %d, j = %d\n", arg.ident.toChars(), i, j); i = buf.bracket(i, "$(DDOC_PARAM ", j, ")") - 1; break; } } i = j - 1; } } } break; } } Ldone: if (inCode) s.error("unmatched --- in DDoc comment"); ; }+/