refactor(format): subqueries and CTE lists on Doc-IR; fix CTE commas with trailing style
This commit is contained in:
+29
-3
@@ -13,7 +13,7 @@ type Doc interface{ isDoc() }
|
||||
|
||||
type (
|
||||
docText string
|
||||
docLine struct{ soft bool }
|
||||
docLine struct{ soft, hard bool }
|
||||
docConcat []Doc
|
||||
docIndent struct{ d Doc }
|
||||
docGroup struct{ d Doc }
|
||||
@@ -37,6 +37,24 @@ func Line() Doc { return docLine{} }
|
||||
// SoftLine is nothing when flat and a newline (plus indentation) when broken.
|
||||
func SoftLine() Doc { return docLine{soft: true} }
|
||||
|
||||
// HardLine is always a newline (plus indentation), even inside a flat group; a
|
||||
// group containing one can never be printed flat.
|
||||
func HardLine() Doc { return docLine{hard: true} }
|
||||
|
||||
// Lines turns multi-line text into Text pieces joined by HardLines so that each
|
||||
// line picks up the surrounding Indent. Empty lines carry no indentation.
|
||||
func Lines(s, nl string) Doc {
|
||||
parts := strings.Split(s, nl)
|
||||
ds := make([]Doc, 0, 2*len(parts))
|
||||
for i, p := range parts {
|
||||
if i > 0 {
|
||||
ds = append(ds, HardLine())
|
||||
}
|
||||
ds = append(ds, Text(p))
|
||||
}
|
||||
return Concat(ds...)
|
||||
}
|
||||
|
||||
// Concat joins docs in order.
|
||||
func Concat(ds ...Doc) Doc { return docConcat(ds) }
|
||||
|
||||
@@ -59,12 +77,17 @@ type docCmd struct {
|
||||
func Render(d Doc, width int, unit, nl string) string {
|
||||
var b strings.Builder
|
||||
col := 0
|
||||
pending := "" // indentation owed to the next non-empty text
|
||||
stack := []docCmd{{"", false, d}}
|
||||
for len(stack) > 0 {
|
||||
c := stack[len(stack)-1]
|
||||
stack = stack[:len(stack)-1]
|
||||
switch v := c.d.(type) {
|
||||
case docText:
|
||||
if len(v) > 0 {
|
||||
b.WriteString(pending)
|
||||
pending = ""
|
||||
}
|
||||
b.WriteString(string(v))
|
||||
if i := strings.LastIndexByte(string(v), '\n'); i >= 0 {
|
||||
col = len(v) - i - 1
|
||||
@@ -84,7 +107,7 @@ func Render(d Doc, width int, unit, nl string) string {
|
||||
stack = append(stack, docCmd{c.indent, c.flat, v.broken})
|
||||
}
|
||||
case docLine:
|
||||
if c.flat {
|
||||
if c.flat && !v.hard {
|
||||
if !v.soft {
|
||||
b.WriteByte(' ')
|
||||
col++
|
||||
@@ -92,7 +115,7 @@ func Render(d Doc, width int, unit, nl string) string {
|
||||
break
|
||||
}
|
||||
b.WriteString(nl)
|
||||
b.WriteString(c.indent)
|
||||
pending = c.indent
|
||||
col = len(c.indent)
|
||||
case docGroup:
|
||||
flat := c.flat || width <= 0 || fitsFlat(v.d, width-col, c.indent, unit, stack)
|
||||
@@ -146,6 +169,9 @@ func fitsFlat(d Doc, rem int, indent, unit string, rest []docCmd) bool {
|
||||
work = append(work, item{v.broken, it.flat})
|
||||
}
|
||||
case docLine:
|
||||
if v.hard {
|
||||
return false
|
||||
}
|
||||
if !it.flat {
|
||||
return true // a real line break ends the measured run
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user