diff options
-rwxr-xr-x | compiler/docgen.nim | 45 | ||||
-rwxr-xr-x | compiler/highlite.nim | 8 | ||||
-rwxr-xr-x | compiler/rst.nim | 234 | ||||
-rwxr-xr-x | lib/impure/db_mysql.nim | 2 | ||||
-rwxr-xr-x | lib/impure/db_postgres.nim | 2 | ||||
-rwxr-xr-x | lib/impure/db_sqlite.nim | 2 | ||||
-rwxr-xr-x | lib/pure/htmlgen.nim | 2 | ||||
-rwxr-xr-x | lib/pure/strutils.nim | 10 | ||||
-rwxr-xr-x | todo.txt | 1 | ||||
-rwxr-xr-x | tools/nimweb.nim | 6 | ||||
-rwxr-xr-x | web/news.txt | 1 |
11 files changed, 229 insertions, 84 deletions
diff --git a/compiler/docgen.nim b/compiler/docgen.nim index d70f92ac4..c17884f21 100755 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -28,7 +28,8 @@ type TSections = array[TSymKind, PRope] TMetaEnum = enum metaNone, metaTitle, metaSubtitle, metaAuthor, metaVersion - TDocumentor{.final.} = object # contains a module's documentation + TDocumentor {.final.} = object # contains a module's documentation + options: TRstParseOptions filename*: string # filename of the source file; without extension basedir*: string # base directory (where to put the documentation) modDesc*: PRope # module description @@ -70,8 +71,8 @@ proc initIndexFile(d: PDoc) = gIndexFile = addFileExt(gIndexFile, "txt") d.indexValFilename = changeFileExt(extractFilename(d.filename), HtmlExt) if ExistsFile(gIndexFile): - d.indexFile = rstParse(readFile(gIndexFile), false, gIndexFile, 0, 1, - dummyHasToc) + d.indexFile = rstParse(readFile(gIndexFile), gIndexFile, 0, 1, + dummyHasToc, {}) d.theIndex = findIndexNode(d.indexFile) if (d.theIndex == nil) or (d.theIndex.kind != rnDefList): rawMessage(errXisNoValidIndexFile, gIndexFile) @@ -264,10 +265,11 @@ proc renderIndexTerm(d: PDoc, n: PRstNode): PRope = proc genComment(d: PDoc, n: PNode): PRope = var dummyHasToc: bool - if n.comment != nil and startsWith(n.comment, "##"): - result = renderRstToOut(d, rstParse(n.comment, true, toFilename(n.info), + if n.comment != nil and startsWith(n.comment, "##"): + result = renderRstToOut(d, rstParse(n.comment, toFilename(n.info), toLineNumber(n.info), toColumn(n.info), - dummyHasToc)) + dummyHasToc, + d.options + {roSkipPounds})) proc genRecComment(d: PDoc, n: PNode): PRope = if n == nil: return nil @@ -357,15 +359,15 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) = of tkSymbol: dispA(result, "<span class=\"Identifier\">$1</span>", "\\spanIdentifier{$1}", [toRope(esc(literal))]) - of tkInd, tkSad, tkDed, tkSpaces: + of tkInd, tkSad, tkDed, tkSpaces, tkInvalid: app(result, literal) of tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi, tkBracketDotLe, tkBracketDotRi, tkCurlyDotLe, tkCurlyDotRi, tkParDotLe, tkParDotRi, tkComma, tkSemiColon, tkColon, tkEquals, tkDot, tkDotDot, - tkAccent: + tkAccent, tkColonColon, + tkGStrLit, tkGTripleStrLit, tkInfixOpr, tkPrefixOpr, tkPostfixOpr: dispA(result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}", [toRope(esc(literal))]) - else: InternalError(n.info, "docgen.genThing(" & toktypeToStr[kind] & ')') inc(d.id) app(d.section[k], ropeFormatNamedVars(getConfigVar("doc.item"), ["name", "header", "desc", "itemID"], @@ -498,6 +500,9 @@ proc renderRstToRst(d: PDoc, n: PRstNode): PRope = of rnStrongEmphasis: result = renderRstSons(d, n) result = ropef("**$1**", [result]) + of rnTripleEmphasis: + result = renderRstSons(d, n) + result = ropef("***$1***", [result]) of rnInterpretedText: result = renderRstSons(d, n) result = ropef("`$1`", [result]) @@ -506,6 +511,8 @@ proc renderRstToRst(d: PDoc, n: PRstNode): PRope = result = renderRstSons(d, n) result = ropef("``$1``", [result]) dec(d.verbatim) + of rnSmiley: + result = toRope(n.text) of rnLeaf: if (d.verbatim == 0) and (n.text == "\\"): result = toRope("\\\\") # XXX: escape more special characters! @@ -560,6 +567,12 @@ proc renderImage(d: PDoc, n: PRstNode): PRope = [toRope(getArgument(n)), options]) if rsonsLen(n) >= 3: app(result, renderRstToOut(d, n.sons[2])) +proc renderSmiley(d: PDoc, n: PRstNode): PRope = + result = dispF( + """<img src="images/smilies/$1.gif" width="15" + height="17" hspace="2" vspace="2" />""", + "\\includegraphics{$1}", [toRope(n.text)]) + proc renderCodeBlock(d: PDoc, n: PRstNode): PRope = result = nil if n.sons[2] == nil: return @@ -741,7 +754,10 @@ proc renderRstToOut(d: PDoc, n: PRstNode): PRope = of rnEmphasis: result = renderAux(d, n, disp("<em>$1</em>", "\\emph{$1}")) of rnStrongEmphasis: result = renderAux(d, n, disp("<strong>$1</strong>", "\\textbf{$1}")) - of rnInterpretedText: + of rnTripleEmphasis: + result = renderAux(d, n, disp("<strong><em>$1</em></strong>", + "\\textbf{emph{$1}}")) + of rnInterpretedText: result = renderAux(d, n, disp("<cite>$1</cite>", "\\emph{$1}")) of rnIdx: if d.theIndex == nil: @@ -752,10 +768,10 @@ proc renderRstToOut(d: PDoc, n: PRstNode): PRope = result = renderAux(d, n, disp( "<tt class=\"docutils literal\"><span class=\"pre\">$1</span></tt>", "\\texttt{$1}")) + of rnSmiley: result = renderSmiley(d, n) of rnLeaf: result = toRope(esc(n.text)) of rnContents: d.hasToc = true of rnTitle: d.meta[metaTitle] = renderRstToOut(d, n.sons[0]) - else: InternalError("renderRstToOut") proc checkForFalse(n: PNode): bool = result = n.kind == nkIdent and IdentEq(n.ident, "false") @@ -869,7 +885,7 @@ proc CommandRstAux(filename, outExt: string) = var filen = addFileExt(filename, "txt") var d = newDocumentor(filen) initIndexFile(d) - var rst = rstParse(readFile(filen), false, filen, 0, 1, d.hasToc) + var rst = rstParse(readFile(filen), filen, 0, 1, d.hasToc, {}) d.modDesc = renderRstToOut(d, rst) writeOutput(d, filename, outExt) generateIndex(d) @@ -926,12 +942,13 @@ $content setConfigVar("doc.body_no_toc", "$moduledesc $content") setConfigVar("doc.file", "$content") -proc rstToHtml*(s: string): string = +proc rstToHtml*(s: string, options: TRstParseOptions): string = ## exported for *nimforum*. const filen = "input" var d = newDocumentor(filen) + d.options = options var dummyHasToc = false - var rst = rstParse(s, false, filen, 0, 1, dummyHasToc) + var rst = rstParse(s, filen, 0, 1, dummyHasToc, options) d.modDesc = renderRstToOut(d, rst) let res = genOutFile(d) result = res.ropeToStr diff --git a/compiler/highlite.nim b/compiler/highlite.nim index b0177a01e..ff4b27086 100755 --- a/compiler/highlite.nim +++ b/compiler/highlite.nim @@ -25,10 +25,10 @@ type gtReference, gtOther TGeneralTokenizer* = object of TObject kind*: TTokenClass - start*, length*: int # private: - buf*: cstring - pos*: int - state*: TTokenClass + start*, length*: int + buf: cstring + pos: int + state: TTokenClass TSourceLanguage* = enum langNone, langNimrod, langCpp, langCsharp, langC, langJava diff --git a/compiler/rst.nim b/compiler/rst.nim index 395c27119..1efcd9930 100755 --- a/compiler/rst.nim +++ b/compiler/rst.nim @@ -11,7 +11,7 @@ # subset is provided. import - os, msgs, strutils, platform, hashes, ropes, options + os, msgs, strutils, hashes, options type TRstNodeKind* = enum @@ -52,15 +52,25 @@ type # * `file#id <file#id>'_ rnSubstitutionDef, # a definition of a substitution rnGeneralRole, # Inline markup: - rnSub, rnSup, rnIdx, rnEmphasis, # "*" + rnSub, rnSup, rnIdx, + rnEmphasis, # "*" rnStrongEmphasis, # "**" + rnTripleEmphasis, # "***" rnInterpretedText, # "`" rnInlineLiteral, # "``" rnSubstitutionReferences, # "|" + rnSmiley, # some smiley rnLeaf # a leaf; the node's text field contains the # leaf val -type # the syntax tree of RST: +type + TRstParseOption* = enum ## options for the RST parser + roSkipPounds, ## skip ``#`` at line beginning (documentation + ## embedded in Nimrod comments) + roSupportSmilies, ## make the RST parser support smilies like ``:)`` + + TRstParseOptions* = set[TRstParseOption] + PRSTNode* = ref TRstNode TRstNodeSeq* = seq[PRstNode] TRSTNode*{.acyclic, final.} = object @@ -71,9 +81,9 @@ type # the syntax tree of RST: sons*: TRstNodeSeq # the node's sons -proc rstParse*(text: string, # the text to be parsed - skipPounds: bool, filename: string, # for error messages - line, column: int, hasToc: var bool): PRstNode +proc rstParse*(text, filename: string, + line, column: int, hasToc: var bool, + options: TRstParseOptions): PRstNode proc rsonsLen*(n: PRstNode): int proc newRstNode*(kind: TRstNodeKind): PRstNode proc newRstNode*(kind: TRstNodeKind, s: string): PRstNode @@ -91,8 +101,46 @@ proc clearIndex*(index: PRstNode, filename: string) const SymChars: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF'} + SmileyStartChars: TCharSet = {':', ';', '8'} + Smilies = { + ":D": "icon_e_biggrin", + ":-D": "icon_e_biggrin", + ":)": "icon_e_smile", + ":-)": "icon_e_smile", + ";)": "icon_e_wink", + ";-)": "icon_e_wink", + ":(": "icon_e_sad", + ":-(": "icon_e_sad", + ":o": "icon_e_surprised", + ":-o": "icon_e_surprised", + ":shock:": "icon_eek", + ":?": "icon_e_confused", + ":-?": "icon_e_confused", + "8-)": "icon_cool", + + ":lol:": "icon_lol", + ":x": "icon_mad", + ":-x": "icon_mad", + ":P": "icon_razz", + ":-P": "icon_razz", + ":oops:": "icon_redface", + ":cry:": "icon_cry", + ":evil:": "icon_evil", + ":twisted:": "icon_twisted", + ":roll:": "icon_rolleyes", + ":!:": "icon_exclaim", + + ":?:": "icon_question", + ":idea:": "icon_idea", + ":arrow:": "icon_arrow", + ":|": "icon_neutral", + ":-|": "icon_neutral", + ":mrgreen:": "icon_mrgreen", + ":geek:": "icon_e_geek", + ":ugeek:": "icon_e_ugeek" + } -type +type TTokType = enum tkEof, tkIndent, tkWhite, tkWord, tkAdornment, tkPunct, tkOther TToken{.final.} = object # a RST token @@ -117,7 +165,7 @@ proc getThing(L: var TLexer, tok: var TToken, s: TCharSet) = while True: add(tok.symbol, L.buf[pos]) inc(pos) - if not (L.buf[pos] in s): break + if L.buf[pos] notin s: break inc(L.col, pos - L.bufpos) L.bufpos = pos @@ -256,7 +304,8 @@ type key*: string value*: PRstNode - TSharedState{.final.} = object + TSharedState {.final.} = object + options: TRstParseOptions # parsing options uLevel*, oLevel*: int # counters for the section levels subs*: seq[TSubstitution] # substitutions refs*: seq[TSubstitution] # references @@ -280,10 +329,11 @@ type hasToc*: bool -proc newSharedState(): PSharedState = +proc newSharedState(options: TRstParseOptions): PSharedState = new(result) result.subs = @[] result.refs = @[] + result.options = options proc tokInfo(p: TRstParser, tok: TToken): TLineInfo = result = newLineInfo(p.filename, p.line + tok.line, p.col + tok.col) @@ -325,7 +375,7 @@ proc addNodes(n: PRstNode): string = proc rstnodeToRefnameAux(n: PRstNode, r: var string, b: var bool) = if n.kind == rnLeaf: - for i in countup(0, len(n.text) + 0 - 1): + for i in countup(0, len(n.text) - 1): case n.text[i] of '0'..'9': if b: @@ -440,15 +490,14 @@ proc matchesHyperlink(h: PRstNode, filename: string): bool = proc clearIndex(index: PRstNode, filename: string) = var - k, items, lastItem: int - val: PRstNode + lastItem: int assert(index.kind == rnDefList) for i in countup(0, rsonsLen(index) - 1): assert(index.sons[i].sons[1].kind == rnDefBody) - val = index.sons[i].sons[1].sons[0] + var val = index.sons[i].sons[1].sons[0] if val.kind == rnInner: val = val.sons[0] if val.kind == rnBulletList: - items = rsonsLen(val) + var items = rsonsLen(val) lastItem = - 1 # save the last valid item index for j in countup(0, rsonsLen(val) - 1): if val.sons[j] == nil: @@ -464,7 +513,7 @@ proc clearIndex(index: PRstNode, filename: string) = index.sons[i] = nil elif matchesHyperlink(val, filename): index.sons[i] = nil - k = 0 + var k = 0 for i in countup(0, rsonsLen(index) - 1): if index.sons[i] != nil: if k != i: index.sons[k] = index.sons[i] @@ -573,20 +622,6 @@ proc isInlineMarkupStart(p: TRstParser, markup: string): bool = of '<': d = '>' else: d = '\0' if d != '\0': result = p.tok[p.idx + 1].symbol[0] != d - -proc parseBackslash(p: var TRstParser, father: PRstNode) = - assert(p.tok[p.idx].kind == tkPunct) - if p.tok[p.idx].symbol == "\\\\": - addSon(father, newRstNode(rnLeaf, "\\")) - inc(p.idx) - elif p.tok[p.idx].symbol == "\\": - # XXX: Unicode? - inc(p.idx) - if p.tok[p.idx].kind != tkWhite: addSon(father, newLeaf(p)) - inc(p.idx) - else: - addSon(father, newLeaf(p)) - inc(p.idx) proc match(p: TRstParser, start: int, expr: string): bool = # regular expressions are: @@ -601,7 +636,7 @@ proc match(p: TRstParser, start: int, expr: string): bool = # 'e' tkWord or '#' (for enumeration lists) var i = 0 var j = start - var last = len(expr) + 0 - 1 + var last = len(expr) - 1 while i <= last: case expr[i] of 'w': result = p.tok[j].kind == tkWord @@ -632,7 +667,7 @@ proc match(p: TRstParser, start: int, expr: string): bool = inc(j) inc(i) result = true - + proc fixupEmbeddedRef(n, a, b: PRstNode) = var sep = - 1 for i in countdown(rsonsLen(n) - 2, 0): @@ -687,31 +722,85 @@ proc parsePostfix(p: var TRstParser, n: PRstNode): PRstNode = addSon(result, newRstNode(rnLeaf, p.tok[p.idx + 1].symbol)) inc(p.idx, 3) -proc isURL(p: TRstParser, i: int): bool = - result = (p.tok[i + 1].symbol == ":") and (p.tok[i + 2].symbol == "//") and - (p.tok[i + 3].kind == tkWord) and (p.tok[i + 4].symbol == ".") +proc matchVerbatim(p: TRstParser, start: int, expr: string): int = + result = start + var j = 0 + while j < expr.len and continuesWith(expr, p.tok[result].symbol, j): + inc j, p.tok[result].symbol.len + inc result + if j < expr.len: result = 0 + +proc parseSmiley(p: var TRstParser): PRstNode = + if p.tok[p.idx].symbol[0] notin SmileyStartChars: return + for key, val in items(smilies): + let m = matchVerbatim(p, p.idx, key) + if m > 0: + p.idx = m + result = newRstNode(rnSmiley) + result.text = val + return + +proc isURL(p: TRstParser, i: int): bool = + result = (p.tok[i+1].symbol == ":") and (p.tok[i+2].symbol == "//") and + (p.tok[i+3].kind == tkWord) and (p.tok[i+4].symbol == ".") proc parseURL(p: var TRstParser, father: PRstNode) = - #if p.tok[p.idx].symbol[strStart] = '<' then begin - if isURL(p, p.idx): + #if p.tok[p.idx].symbol[strStart] == '<': + if isURL(p, p.idx): var n = newRstNode(rnStandaloneHyperlink) while true: case p.tok[p.idx].kind - of tkWord, tkAdornment, tkOther: - nil + of tkWord, tkAdornment, tkOther: nil of tkPunct: - if not (p.tok[p.idx + 1].kind in - {tkWord, tkAdornment, tkOther, tkPunct}): - break + if p.tok[p.idx+1].kind notin {tkWord, tkAdornment, tkOther, tkPunct}: + break else: break addSon(n, newLeaf(p)) inc(p.idx) addSon(father, n) - else: + else: var n = newLeaf(p) inc(p.idx) if p.tok[p.idx].symbol == "_": n = parsePostfix(p, n) addSon(father, n) + +proc parseBackslash(p: var TRstParser, father: PRstNode) = + assert(p.tok[p.idx].kind == tkPunct) + if p.tok[p.idx].symbol == "\\\\": + addSon(father, newRstNode(rnLeaf, "\\")) + inc(p.idx) + elif p.tok[p.idx].symbol == "\\": + # XXX: Unicode? + inc(p.idx) + if p.tok[p.idx].kind != tkWhite: addSon(father, newLeaf(p)) + inc(p.idx) + else: + addSon(father, newLeaf(p)) + inc(p.idx) + +when false: + proc parseAdhoc(p: var TRstParser, father: PRstNode, verbatim: bool) = + if not verbatim and isURL(p, p.idx): + var n = newRstNode(rnStandaloneHyperlink) + while true: + case p.tok[p.idx].kind + of tkWord, tkAdornment, tkOther: nil + of tkPunct: + if p.tok[p.idx+1].kind notin {tkWord, tkAdornment, tkOther, tkPunct}: + break + else: break + addSon(n, newLeaf(p)) + inc(p.idx) + addSon(father, n) + elif not verbatim and roSupportSmilies in p.shared.options: + let n = parseSmiley(p) + if s != nil: + addSon(father, n) + else: + var n = newLeaf(p) + inc(p.idx) + if p.tok[p.idx].symbol == "_": n = parsePostfix(p, n) + addSon(father, n) proc parseUntil(p: var TRstParser, father: PRstNode, postfix: string, interpretBackslash: bool) = @@ -743,7 +832,12 @@ proc parseUntil(p: var TRstParser, father: PRstNode, postfix: string, proc parseInline(p: var TRstParser, father: PRstNode) = case p.tok[p.idx].kind of tkPunct: - if isInlineMarkupStart(p, "**"): + if isInlineMarkupStart(p, "***"): + inc(p.idx) + var n = newRstNode(rnTripleEmphasis) + parseUntil(p, n, "***", true) + addSon(father, n) + elif isInlineMarkupStart(p, "**"): inc(p.idx) var n = newRstNode(rnStrongEmphasis) parseUntil(p, n, "**", true) @@ -769,11 +863,26 @@ proc parseInline(p: var TRstParser, father: PRstNode) = var n = newRstNode(rnSubstitutionReferences) parseUntil(p, n, "|", false) addSon(father, n) - else: + else: + if roSupportSmilies in p.s.options: + let n = parseSmiley(p) + if n != nil: + addSon(father, n) + return parseBackslash(p, father) - of tkWord: + of tkWord: + if roSupportSmilies in p.s.options: + let n = parseSmiley(p) + if n != nil: + addSon(father, n) + return parseURL(p, father) of tkAdornment, tkOther, tkWhite: + if roSupportSmilies in p.s.options: + let n = parseSmiley(p) + if n != nil: + addSon(father, n) + return addSon(father, newLeaf(p)) inc(p.idx) else: nil @@ -878,7 +987,9 @@ proc getFieldValue(n: PRstNode, fieldname: string): string = result = "" if n.sons[1] == nil: return if (n.sons[1].kind != rnFieldList): - InternalError("getFieldValue (2): " & $n.sons[1].kind) + #InternalError("getFieldValue (2): " & $n.sons[1].kind) + # We don't like internal errors here anymore as that would break the forum! + return for i in countup(0, rsonsLen(n.sons[1]) - 1): var f = n.sons[1].sons[i] if cmpIgnoreStyle(addNodes(f.sons[0]), fieldname) == 0: @@ -975,7 +1086,8 @@ proc whichSection(p: TRstParser): TRstNodeKind = result = rnLineBlock elif (p.tok[p.idx].symbol == "..") and predNL(p): result = rnDirective - elif (p.tok[p.idx].symbol == ":") and predNL(p): + elif match(p, p.idx, ":w:") and predNL(p): + # (p.tok[p.idx].symbol == ":") result = rnFieldList elif match(p, p.idx, "(e) "): result = rnEnumList @@ -1317,13 +1429,14 @@ proc parseSection(p: var TRstParser, result: PRstNode) = of rnOverline: a = parseOverline(p) of rnTable: a = parseSimpleTable(p) of rnOptionList: a = parseOptionList(p) - else: InternalError("rst.parseSection()") - if (a == nil) and (k != rnDirective): + else: + #InternalError("rst.parseSection()") + nil + if a == nil and k != rnDirective: a = newRstNode(rnParagraph) parseParagraph(p, a) addSonIfNotNil(result, a) - if (sonKind(result, 0) == rnParagraph) and - (sonKind(result, 1) != rnParagraph): + if sonKind(result, 0) == rnParagraph and sonKind(result, 1) != rnParagraph: result.sons[0].kind = rnInner proc parseSectionWrapper(p: var TRstParser): PRstNode = @@ -1423,9 +1536,10 @@ proc dirInclude(p: var TRstParser): PRstNode = var q: TRstParser initParser(q, p.s) q.filename = filename - getTokens(readFile(path), false, q.tok) # workaround a GCC bug: - if find(q.tok[high(q.tok)].symbol, "\0\x01\x02") > 0: - InternalError("Too many binary zeros in include file") + getTokens(readFile(path), false, q.tok) + # workaround a GCC bug; more like the interior pointer bug? + #if find(q.tok[high(q.tok)].symbol, "\0\x01\x02") > 0: + # InternalError("Too many binary zeros in include file") result = parseDoc(q) proc dirCodeBlock(p: var TRstParser): PRstNode = @@ -1580,15 +1694,15 @@ proc resolveSubs(p: var TRstParser, n: PRstNode): PRstNode = else: for i in countup(0, rsonsLen(n) - 1): n.sons[i] = resolveSubs(p, n.sons[i]) -proc rstParse(text: string, # the text to be parsed - skipPounds: bool, filename: string, # for error messages - line, column: int, hasToc: var bool): PRstNode = +proc rstParse(text, filename: string, + line, column: int, hasToc: var bool, + options: TRstParseOptions): PRstNode = var p: TRstParser if isNil(text): rawMessage(errCannotOpenFile, filename) - initParser(p, newSharedState()) + initParser(p, newSharedState(options)) p.filename = filename p.line = line p.col = column - getTokens(text, skipPounds, p.tok) + getTokens(text, roSkipPounds in options, p.tok) result = resolveSubs(p, parseDoc(p)) hasToc = p.hasToc diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim index 4c77c707f..2b94ab614 100755 --- a/lib/impure/db_mysql.nim +++ b/lib/impure/db_mysql.nim @@ -106,7 +106,7 @@ proc getRow*(db: TDbConn, query: TSqlQuery, var sqlres = mysql.UseResult(db) if sqlres != nil: var L = int(mysql.NumFields(sqlres)) - var result = newRow(L) + result = newRow(L) var row = mysql.FetchRow(sqlres) if row != nil: for i in 0..L-1: diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim index dff607081..506da9c84 100755 --- a/lib/impure/db_postgres.nim +++ b/lib/impure/db_postgres.nim @@ -108,7 +108,7 @@ proc getRow*(db: TDbConn, query: TSqlQuery, ## retrieves a single row. var res = setupQuery(db, query, args) var L = int(PQnfields(res)) - var result = newRow(L) + result = newRow(L) setRow(res, result, 0, L) PQclear(res) diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim index 3f5be772c..b6c8003b9 100755 --- a/lib/impure/db_sqlite.nim +++ b/lib/impure/db_sqlite.nim @@ -106,7 +106,7 @@ proc getRow*(db: TDbConn, query: TSqlQuery, ## retrieves a single row. var stmt = setupQuery(db, query, args) var L = int(columnCount(stmt)) - var result = newRow(L) + result = newRow(L) if step(stmt) == SQLITE_ROW: setRow(stmt, result, L) if finalize(stmt) != SQLITE_OK: dbError(db) diff --git a/lib/pure/htmlgen.nim b/lib/pure/htmlgen.nim index b61aa2925..86ee4159b 100755 --- a/lib/pure/htmlgen.nim +++ b/lib/pure/htmlgen.nim @@ -222,7 +222,7 @@ macro head*(e: expr): expr = macro html*(e: expr): expr = ## generates the HTML ``html`` element. - result = xmlCheckedTag(e, "html", "", "xmlns") + result = xmlCheckedTag(e, "html", "xmlns", "") macro hr*(e: expr): expr = ## generates the HTML ``hr`` element. diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 8e3816904..368ef2564 100755 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -531,6 +531,16 @@ proc endsWith*(s, suffix: string): bool {.noSideEffect, if s[i+j] != suffix[i]: return false inc(i) if suffix[i] == '\0': return true + +proc continuesWith*(s, substr: string, start: int): bool {.noSideEffect, + rtl, extern: "nsuContinuesWith".} = + ## Returns true iff ``s`` continues with ``substr`` at position ``start``. + ## If ``substr == ""`` true is returned. + var i = 0 + while true: + if substr[i] == '\0': return true + if s[i+start] != substr[i]: return false + inc(i) proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect, inline.} = diff --git a/todo.txt b/todo.txt index 761c6d419..3f7f2e2df 100755 --- a/todo.txt +++ b/todo.txt @@ -2,6 +2,7 @@ version 0.9.0 ============= - make templates hygienic by default +- ``bind`` for overloaded symbols does not work apparently - ``=`` should be overloadable; requires specialization for ``=`` - fix remaining generics bugs - fix remaining closure bugs: diff --git a/tools/nimweb.nim b/tools/nimweb.nim index cc5ea97a6..61f23ab8c 100755 --- a/tools/nimweb.nim +++ b/tools/nimweb.nim @@ -203,8 +203,10 @@ proc main(c: var TConfigData) = if c.ticker.len > 0: Exec(cmd % [c.nimrodArgs, c.ticker]) var temp = "web" / changeFileExt(c.ticker, "temp") - c.ticker = readFile(temp) - if isNil(c.ticker): quit("[Error] cannot open:" & temp) + try: + c.ticker = readFile(temp) + except EIO: + quit("[Error] cannot open: " & temp) RemoveFile(temp) for i in 0..c.tabs.len-1: var file = c.tabs[i].val diff --git a/web/news.txt b/web/news.txt index 8504be619..64d0ce928 100755 --- a/web/news.txt +++ b/web/news.txt @@ -43,6 +43,7 @@ Library Additions - Added ``system.TInteger`` and ``system.TNumber`` type classes matching any of the corresponding type available in nimrod. - Added ``system.clamp`` to limit a value within an interval ``[a, b]``. +- Added ``strutils.continuesWith``. - The GC supports (soft) realtime systems via ``GC_setMaxPause`` and ``GC_step`` procs. |