From aa7447358f537d19c15514c6cf59bffd30ded7ed Mon Sep 17 00:00:00 2001 From: Andrey Makarov Date: Wed, 10 Mar 2021 18:12:37 +0300 Subject: [PATCH] revert dedent workarounds, address other comments --- compiler/docgen.nim | 3 +- lib/packages/docutils/rst.nim | 34 ++++++++------ lib/packages/docutils/rstgen.nim | 6 ++- lib/pure/strutils.nim | 78 +++++++++++++++----------------- 4 files changed, 63 insertions(+), 58 deletions(-) diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 20c563d7b62c0..305527ee4e4c3 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -1347,7 +1347,8 @@ proc commandRstAux(cache: IdentCache, conf: ConfigRef; var d = newDocumentor(filen, cache, conf, outExt) d.isPureRst = true - var rst = parseRst(readFile(filen.string), filen.string, line=1, column=0, + var rst = parseRst(readFile(filen.string), filen.string, + line=LineRstInit, column=ColRstInit, d.hasToc, {roSupportRawDirective, roSupportMarkdown}, conf) var modDesc = newStringOfCap(30_000) renderRstToOut(d[], rst, modDesc) diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim index 135524e5ba643..d2bfb39785fe2 100644 --- a/lib/packages/docutils/rst.nim +++ b/lib/packages/docutils/rst.nim @@ -471,13 +471,16 @@ type ## documenation fragment that will be added ## in case of error/warning reporting to ## (relative) line/column of the token. - ## For standalone text should be line=1 and - ## col=0 (Nim global reporting adds ColOffset=1) hasToc*: bool curAnchor*: string # variable to track latest anchor in s.anchors EParseError* = object of ValueError +const + LineRstInit* = 1 ## Initial line number for standalone RST text + ColRstInit* = 0 ## Initial column number for standalone RST text + ## (Nim global reporting adds ColOffset=1) + template currentTok(p: RstParser): Token = p.tok[p.idx] template prevTok(p: RstParser): Token = p.tok[p.idx - 1] template nextTok(p: RstParser): Token = p.tok[p.idx + 1] @@ -547,8 +550,8 @@ proc initParser(p: var RstParser, sharedState: PSharedState) = p.idx = 0 p.filename = "" p.hasToc = false - p.col = 0 - p.line = 1 + p.col = ColRstInit + p.line = LineRstInit p.s = sharedState proc addNodesAux(n: PRstNode, result: var string) = @@ -1951,25 +1954,26 @@ proc parseEnumList(p: var RstParser): PRstNode = if match(p, p.idx, wildcards[w]): break inc w assert w < wildcards.len - template checkAfterNewline = + proc checkAfterNewline(p: RstParser, report: bool): bool = let j = tokenAfterNewline(p, start=p.idx+1) if p.tok[j].kind notin {tkIndent, tkEof} and p.tok[j].col < p.tok[p.idx+wildToken[w]].col and (p.tok[j].col > col or (p.tok[j].col == col and not match(p, j, wildcards[w]))): - # check `result == nil` to avoid duplication of warning since for - # subsequent enum.items parseEnumList will be called second time - if result == nil: + if report: let n = p.line + p.tok[j].line - let msg = "\n" & dedent """ + let msg = "\n" & """ not enough indentation on line $2 (if it's continuation of enumeration list), or no blank line after line $1 (if it should be the next paragraph), or no escaping \ at the beginning of line $1 - (if lines $1..$2 are a normal paragraph, not enum. list)""" - rstMessage(p, mwRstStyle, indent(msg, 2) % [$(n-1), $n]) - return - checkAfterNewline + (if lines $1..$2 are a normal paragraph, not enum. list)""". + unindent(8) + rstMessage(p, mwRstStyle, msg % [$(n-1), $n]) + result = false + else: + result = true + if not checkAfterNewline(p, report = true): return nil result = newRstNodeA(p, rnEnumList) let autoEnums = if roSupportMarkdown in p.s.options: @["#", "1"] else: @["#"] var prevAE = "" # so as not allow mixing auto-enumerators `1` and `#` @@ -1990,7 +1994,9 @@ proc parseEnumList(p: var RstParser): PRstNode = result.add(item) if currentTok(p).kind == tkIndent and currentTok(p).ival == col and match(p, p.idx+1, wildcards[w]): - checkAfterNewline + # don't report to avoid duplication of warning since for + # subsequent enum. items parseEnumList will be called second time: + if not checkAfterNewline(p, report = false): return nil let enumerator = p.tok[p.idx + 1 + wildIndex[w]].symbol # check that it's in sequence: enumerator == next(prevEnum) if "n" in wildcards[w]: # arabic numeral diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim index bf74672ecb3d9..f72ff9e8f0ba9 100644 --- a/lib/packages/docutils/rstgen.nim +++ b/lib/packages/docutils/rstgen.nim @@ -1506,7 +1506,8 @@ proc rstToHtml*(s: string, options: RstParseOptions, initRstGenerator(d, outHtml, config, filen, options, myFindFile, rst.defaultMsgHandler) var dummyHasToc = false - var rst = rstParse(s, filen, line=1, column=0, dummyHasToc, options) + var rst = rstParse(s, filen, line=LineRstInit, column=ColRstInit, + dummyHasToc, options) result = "" renderRstToOut(d, rst, result) @@ -1519,5 +1520,6 @@ proc rstToLatex*(rstSource: string; options: RstParseOptions): string {.inline, var rstGenera: RstGenerator rstGenera.initRstGenerator(outLatex, defaultConfig(), "input", options) rstGenera.renderRstToOut( - rstParse(rstSource, "", line=1, column=0, option, options), + rstParse(rstSource, "", line=LineRstInit, column=ColRstInit, + option, options), result) diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 6ec6234555b2f..ba1c78479064e 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -1438,47 +1438,43 @@ func unindent*(s: string, count: Natural = int.high, result.add(line[indentCount*padding.len .. ^1]) i.inc -since (1, 3): - func indentation*(s: string): Natural = - ## Returns the amount of indentation all lines of `s` have in common, - ## ignoring lines that consist only of whitespace. - result = int.high - for line in s.splitLines: - for i, c in line: - if i >= result: break - elif c != ' ': - result = i - break - if result == int.high: - result = 0 - - func dedent*(s: string, count: Natural): string {.rtl, extern: "nsuDedent".} = - unindent(s, count, " ") - - proc dedent*(a: string): string {.inline.} = - ## Unindents each line in `s` by `count` amount of `padding`. - ## The only difference between this and the - ## `unindent func<#unindent,string,Natural,string>`_ is that this by default - ## only cuts off the amount of indentation that all lines of `s` share as - ## opposed to all indentation. It only supports spaces as padding. - ## - ## **Note:** This does not preserve the new line characters used in `s`. - ## - ## See also: - ## * `unindent func<#unindent,string,Natural,string>`_ - ## * `align func<#align,string,Natural,char>`_ - ## * `alignLeft func<#alignLeft,string,Natural,char>`_ - ## * `spaces func<#spaces,Natural>`_ - ## * `indent func<#indent,string,Natural,string>`_ - # workaround, see https://github.com/timotheecour/Nim/issues/521 - runnableExamples: - let x = """ - Hello - There - """.dedent() - - doAssert x == "Hello\n There\n" - dedent(a, indentation(a)) +func indentation*(s: string): Natural {.since: (1, 3).} = + ## Returns the amount of indentation all lines of `s` have in common, + ## ignoring lines that consist only of whitespace. + result = int.high + for line in s.splitLines: + for i, c in line: + if i >= result: break + elif c != ' ': + result = i + break + if result == int.high: + result = 0 + +func dedent*(s: string, count: Natural = indentation(s)): string {.rtl, + extern: "nsuDedent", since: (1, 3).} = + ## Unindents each line in `s` by `count` amount of `padding`. + ## The only difference between this and the + ## `unindent func<#unindent,string,Natural,string>`_ is that this by default + ## only cuts off the amount of indentation that all lines of `s` share as + ## opposed to all indentation. It only supports spaces as padding. + ## + ## **Note:** This does not preserve the new line characters used in `s`. + ## + ## See also: + ## * `unindent func<#unindent,string,Natural,string>`_ + ## * `align func<#align,string,Natural,char>`_ + ## * `alignLeft func<#alignLeft,string,Natural,char>`_ + ## * `spaces func<#spaces,Natural>`_ + ## * `indent func<#indent,string,Natural,string>`_ + runnableExamples: + let x = """ + Hello + There + """.dedent() + + doAssert x == "Hello\n There\n" + unindent(s, count, " ") func delete*(s: var string, first, last: int) {.rtl, extern: "nsuDelete".} = ## Deletes in `s` (must be declared as `var`) the characters at positions