nimpretty: more features

This commit is contained in:
Andreas Rumpf
2018-06-16 09:53:36 +02:00
parent 97398edc05
commit 7819e63f77
2 changed files with 51 additions and 13 deletions

View File

@@ -9,7 +9,6 @@
## Layouter for nimpretty. Still primitive but useful.
## TODO
## - Fix 'echo ()' vs 'echo()' difference!
## - Make indentations consistent.
## - Align 'if' and 'case' expressions properly.
@@ -31,6 +30,7 @@ type
lastTok: TTokType
inquote: bool
col, lastLineNumber, lineSpan, indentLevel: int
doIndentMore*: int
content: string
fixedUntil: int # marks where we must not go in the content
altSplitPos: array[SplitKind, int] # alternative split positions
@@ -77,6 +77,8 @@ template rememberSplit(kind) =
if goodCol(em.col):
em.altSplitPos[kind] = em.content.len
template moreIndent(em): int = (if em.doIndentMore > 0: 4 else: 2)
proc softLinebreak(em: var Emitter, lit: string) =
# XXX Use an algorithm that is outlined here:
# https://llvm.org/devmtg/2013-04/jasper-slides.pdf
@@ -85,12 +87,12 @@ proc softLinebreak(em: var Emitter, lit: string) =
if em.lastTok in splitters:
wr("\L")
em.col = 0
for i in 1..em.indentLevel+2: wr(" ")
for i in 1..em.indentLevel+moreIndent(em): wr(" ")
else:
# search backwards for a good split position:
for a in em.altSplitPos:
if a > em.fixedUntil:
let ws = "\L" & repeat(' ',em.indentLevel+2)
let ws = "\L" & repeat(' ',em.indentLevel+moreIndent(em))
em.col = em.content.len - a
em.content.insert(ws, a)
break
@@ -155,15 +157,19 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
wr(TokTypeToStr[tok.tokType])
wr(" ")
rememberSplit(splitComma)
of tkParLe, tkParRi, tkBracketLe,
tkBracketRi, tkCurlyLe, tkCurlyRi,
tkBracketDotLe, tkBracketDotRi,
tkCurlyDotLe, tkCurlyDotRi,
tkParDotLe, tkParDotRi,
tkColonColon, tkDot, tkBracketLeColon:
of tkParDotLe, tkParLe, tkBracketDotLe, tkBracketLe,
tkCurlyLe, tkCurlyDotLe, tkBracketLeColon:
if tok.strongSpaceA > 0 and not em.endsInWhite:
wr(" ")
wr(TokTypeToStr[tok.tokType])
rememberSplit(splitParLe)
of tkParRi,
tkBracketRi, tkCurlyRi,
tkBracketDotRi,
tkCurlyDotRi,
tkParDotRi,
tkColonColon, tkDot:
wr(TokTypeToStr[tok.tokType])
if tok.tokType in splitters:
rememberSplit(splitParLe)
of tkEquals:
if not em.endsInWhite: wr(" ")
wr(TokTypeToStr[tok.tokType])
@@ -206,3 +212,13 @@ proc starWasExportMarker*(em: var Emitter) =
setLen(em.content, em.content.len-3)
em.content.add("*")
dec em.col, 2
proc commaWasSemicolon*(em: var Emitter) =
if em.content.endsWith(", "):
setLen(em.content, em.content.len-2)
em.content.add("; ")
proc curlyRiWasPragma*(em: var Emitter) =
if em.content.endsWith("}"):
setLen(em.content, em.content.len-1)
em.content.add(".}")

View File

@@ -408,6 +408,8 @@ proc exprColonEqExpr(p: var TParser): PNode =
proc exprList(p: var TParser, endTok: TTokType, result: PNode) =
#| exprList = expr ^+ comma
when defined(nimpretty2):
inc p.em.doIndentMore
getTok(p)
optInd(p, result)
# progress guaranteed
@@ -417,6 +419,8 @@ proc exprList(p: var TParser, endTok: TTokType, result: PNode) =
if p.tok.tokType != tkComma: break
getTok(p)
optInd(p, a)
when defined(nimpretty2):
dec p.em.doIndentMore
proc exprColonEqExprListAux(p: var TParser, endTok: TTokType, result: PNode) =
assert(endTok in {tkCurlyRi, tkCurlyDotRi, tkBracketRi, tkParRi})
@@ -837,7 +841,11 @@ proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
result = parseOperators(p, result, limit, mode)
proc simpleExpr(p: var TParser, mode = pmNormal): PNode =
when defined(nimpretty2):
inc p.em.doIndentMore
result = simpleExprAux(p, -1, mode)
when defined(nimpretty2):
dec p.em.doIndentMore
proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
#| condExpr = expr colcom expr optInd
@@ -912,8 +920,12 @@ proc parsePragma(p: var TParser): PNode =
getTok(p)
skipComment(p, a)
optPar(p)
if p.tok.tokType in {tkCurlyDotRi, tkCurlyRi}: getTok(p)
else: parMessage(p, "expected '.}'")
if p.tok.tokType in {tkCurlyDotRi, tkCurlyRi}:
when defined(nimpretty2):
curlyRiWasPragma(p.em)
getTok(p)
else:
parMessage(p, "expected '.}'")
dec p.inPragma
proc identVis(p: var TParser; allowDot=false): PNode =
@@ -1000,6 +1012,8 @@ proc parseTuple(p: var TParser, indentAllowed = false): PNode =
var a = parseIdentColonEquals(p, {})
addSon(result, a)
if p.tok.tokType notin {tkComma, tkSemiColon}: break
when defined(nimpretty2):
commaWasSemicolon(p.em)
getTok(p)
skipComment(p, a)
optPar(p)
@@ -1034,6 +1048,8 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
var a: PNode
result = newNodeP(nkFormalParams, p)
addSon(result, p.emptyNode) # return type
when defined(nimpretty2):
inc p.em.doIndentMore
let hasParLe = p.tok.tokType == tkParLe and p.tok.indent < 0
if hasParLe:
getTok(p)
@@ -1053,6 +1069,8 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
break
addSon(result, a)
if p.tok.tokType notin {tkComma, tkSemiColon}: break
when defined(nimpretty2):
commaWasSemicolon(p.em)
getTok(p)
skipComment(p, a)
optPar(p)
@@ -1066,6 +1084,8 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
elif not retColon and not hasParle:
# Mark as "not there" in order to mark for deprecation in the semantic pass:
result = p.emptyNode
when defined(nimpretty2):
dec p.em.doIndentMore
proc optPragmas(p: var TParser): PNode =
if p.tok.tokType == tkCurlyDotLe and (p.tok.indent < 0 or realInd(p)):
@@ -1668,6 +1688,8 @@ proc parseGenericParamList(p: var TParser): PNode =
var a = parseGenericParam(p)
addSon(result, a)
if p.tok.tokType notin {tkComma, tkSemiColon}: break
when defined(nimpretty2):
commaWasSemicolon(p.em)
getTok(p)
skipComment(p, a)
optPar(p)