diff options
Diffstat (limited to 'compiler/layouter.nim')
-rw-r--r-- | compiler/layouter.nim | 56 |
1 files changed, 43 insertions, 13 deletions
diff --git a/compiler/layouter.nim b/compiler/layouter.nim index cc6ec48b7..8605ade45 100644 --- a/compiler/layouter.nim +++ b/compiler/layouter.nim @@ -28,10 +28,10 @@ type config: ConfigRef fid: FileIndex lastTok: TTokType - inquote: bool + inquote, lastTokWasTerse: bool semicolons: SemicolonKind - col, lastLineNumber, lineSpan, indentLevel, indWidth: int - nested: int + col, lastLineNumber, lineSpan, indentLevel, indWidth*: int + keepIndents*: int doIndentMore*: int content: string indentStack: seq[int] @@ -41,9 +41,10 @@ type proc openEmitter*(em: var Emitter, cache: IdentCache; config: ConfigRef, fileIdx: FileIndex) = let fullPath = Absolutefile config.toFullPath(fileIdx) - em.indWidth = getIndentWidth(fileIdx, llStreamOpen(fullPath, fmRead), - cache, config) - if em.indWidth == 0: em.indWidth = 2 + if em.indWidth == 0: + em.indWidth = getIndentWidth(fileIdx, llStreamOpen(fullPath, fmRead), + cache, config) + if em.indWidth == 0: em.indWidth = 2 em.config = config em.fid = fileIdx em.lastTok = tkInvalid @@ -52,11 +53,16 @@ proc openEmitter*(em: var Emitter, cache: IdentCache; em.content = newStringOfCap(16_000) em.indentStack = newSeqOfCap[int](30) em.indentStack.add 0 + em.lastLineNumber = 1 proc closeEmitter*(em: var Emitter) = + if fileExists(em.config.outFile) and readFile(em.config.outFile.string) == em.content: + discard "do nothing, see #9499" + return var f = llStreamOpen(em.config.outFile, fmWrite) if f == nil: rawMessage(em.config, errGenerated, "cannot open file: " & em.config.outFile.string) + return f.llStreamWrite em.content llStreamClose(f) @@ -106,15 +112,16 @@ proc softLinebreak(em: var Emitter, lit: string) = for i in 1..em.indentLevel+moreIndent(em): wr(" ") else: # search backwards for a good split position: - for a in em.altSplitPos: + for a in mitems(em.altSplitPos): if a > em.fixedUntil: var spaces = 0 while a+spaces < em.content.len and em.content[a+spaces] == ' ': inc spaces if spaces > 0: delete(em.content, a, a+spaces-1) - let ws = "\L" & repeat(' ',em.indentLevel+moreIndent(em)) em.col = em.content.len - a + let ws = "\L" & repeat(' ', em.indentLevel+moreIndent(em)) em.content.insert(ws, a) + a = -1 break proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = @@ -134,6 +141,22 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = for i in 1 .. LineCommentColumn - em.col: wr(" ") wr lit + if tok.tokType == tkComment and tok.literal.startsWith("#!nimpretty"): + case tok.literal + of "#!nimpretty off": + inc em.keepIndents + wr("\L") + em.lastLineNumber = tok.line + 1 + of "#!nimpretty on": + dec em.keepIndents + em.lastLineNumber = tok.line + wr("\L") + #for i in 1 .. tok.indent: wr " " + wr tok.literal + em.col = 0 + em.lineSpan = 0 + return + var preventComment = false if tok.tokType == tkComment and tok.line == em.lastLineNumber and tok.indent >= 0: # we have an inline comment so handle it before the indentation token: @@ -142,7 +165,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = em.fixedUntil = em.content.high elif tok.indent >= 0: - if em.lastTok in (splitters + oprSet): + if em.lastTok in (splitters + oprSet) or em.keepIndents > 0: em.indentLevel = tok.indent else: if tok.indent > em.indentStack[^1]: @@ -171,12 +194,13 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = wr(" ") em.fixedUntil = em.content.high + var lastTokWasTerse = false case tok.tokType of tokKeywordLow..tokKeywordHigh: if endsInAlpha(em): wr(" ") elif not em.inquote and not endsInWhite(em) and - em.lastTok notin openPars: + em.lastTok notin openPars and not em.lastTokWasTerse: #and tok.tokType in oprSet wr(" ") @@ -212,14 +236,19 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = tkBracketDotRi, tkCurlyDotRi, tkParDotRi, - tkColonColon, tkDot: + tkColonColon: + wr(TokTypeToStr[tok.tokType]) + of tkDot: + lastTokWasTerse = true wr(TokTypeToStr[tok.tokType]) of tkEquals: if not em.inquote and not em.endsInWhite: wr(" ") wr(TokTypeToStr[tok.tokType]) if not em.inquote: wr(" ") of tkOpr, tkDotDot: - if tok.strongSpaceA == 0 and tok.strongSpaceB == 0: + if (tok.strongSpaceA == 0 and tok.strongSpaceB == 0) or em.inquote: + # bug #9504: remember to not spacify a keyword: + lastTokWasTerse = true # if not surrounded by whitespace, don't produce any whitespace either: wr(tok.ident.s) else: @@ -229,8 +258,8 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = tok.strongSpaceB == 0 and tok.strongSpaceA > 0 if not isUnary(tok): - wr(" ") rememberSplit(splitBinary) + wr(" ") of tkAccent: if not em.inquote and endsInAlpha(em): wr(" ") wr(TokTypeToStr[tok.tokType]) @@ -253,6 +282,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = wr lit em.lastTok = tok.tokType + em.lastTokWasTerse = lastTokWasTerse em.lastLineNumber = tok.line + em.lineSpan em.lineSpan = 0 |