2022-11-03 13:54:49 +00:00
|
|
|
package d2format
|
|
|
|
|
|
|
|
|
|
import (
|
2023-06-06 23:15:01 +00:00
|
|
|
"path"
|
2022-11-03 13:54:49 +00:00
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
"oss.terrastruct.com/d2/d2ast"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// TODO: edges with shared path should be fmted as <rel>.(x -> y)
|
|
|
|
|
func Format(n d2ast.Node) string {
|
|
|
|
|
var p printer
|
|
|
|
|
p.node(n)
|
|
|
|
|
return p.sb.String()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type printer struct {
|
|
|
|
|
sb strings.Builder
|
|
|
|
|
indentStr string
|
|
|
|
|
inKey bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) indent() {
|
|
|
|
|
p.indentStr += " " + " "
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) deindent() {
|
|
|
|
|
p.indentStr = p.indentStr[:len(p.indentStr)-2]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) newline() {
|
|
|
|
|
p.sb.WriteByte('\n')
|
|
|
|
|
p.sb.WriteString(p.indentStr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) node(n d2ast.Node) {
|
|
|
|
|
switch n := n.(type) {
|
|
|
|
|
case *d2ast.Comment:
|
|
|
|
|
p.comment(n)
|
|
|
|
|
case *d2ast.BlockComment:
|
|
|
|
|
p.blockComment(n)
|
|
|
|
|
case *d2ast.Null:
|
|
|
|
|
p.sb.WriteString("null")
|
|
|
|
|
case *d2ast.Boolean:
|
|
|
|
|
p.sb.WriteString(strconv.FormatBool(n.Value))
|
|
|
|
|
case *d2ast.Number:
|
|
|
|
|
p.sb.WriteString(n.Raw)
|
|
|
|
|
case *d2ast.UnquotedString:
|
|
|
|
|
p.interpolationBoxes(n.Value, false)
|
|
|
|
|
case *d2ast.DoubleQuotedString:
|
|
|
|
|
p.sb.WriteByte('"')
|
|
|
|
|
p.interpolationBoxes(n.Value, true)
|
|
|
|
|
p.sb.WriteByte('"')
|
|
|
|
|
case *d2ast.SingleQuotedString:
|
|
|
|
|
p.sb.WriteByte('\'')
|
|
|
|
|
if n.Raw == "" {
|
|
|
|
|
n.Raw = escapeSingleQuotedValue(n.Value)
|
|
|
|
|
}
|
|
|
|
|
p.sb.WriteString(escapeSingleQuotedValue(n.Value))
|
|
|
|
|
p.sb.WriteByte('\'')
|
|
|
|
|
case *d2ast.BlockString:
|
|
|
|
|
p.blockString(n)
|
|
|
|
|
case *d2ast.Substitution:
|
|
|
|
|
p.substitution(n)
|
2023-05-24 00:32:05 +00:00
|
|
|
case *d2ast.Import:
|
|
|
|
|
p._import(n)
|
2022-11-03 13:54:49 +00:00
|
|
|
case *d2ast.Array:
|
|
|
|
|
p.array(n)
|
|
|
|
|
case *d2ast.Map:
|
|
|
|
|
p._map(n)
|
|
|
|
|
case *d2ast.Key:
|
|
|
|
|
p.mapKey(n)
|
|
|
|
|
case *d2ast.KeyPath:
|
|
|
|
|
p.key(n)
|
|
|
|
|
case *d2ast.Edge:
|
|
|
|
|
p.edge(n)
|
|
|
|
|
case *d2ast.EdgeIndex:
|
|
|
|
|
p.edgeIndex(n)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) comment(c *d2ast.Comment) {
|
|
|
|
|
lines := strings.Split(c.Value, "\n")
|
|
|
|
|
for i, line := range lines {
|
|
|
|
|
p.sb.WriteString("#")
|
2022-12-07 16:28:40 +00:00
|
|
|
if line != "" {
|
2022-11-03 13:54:49 +00:00
|
|
|
p.sb.WriteByte(' ')
|
|
|
|
|
}
|
|
|
|
|
p.sb.WriteString(line)
|
|
|
|
|
if i < len(lines)-1 {
|
|
|
|
|
p.newline()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) blockComment(bc *d2ast.BlockComment) {
|
|
|
|
|
p.sb.WriteString(`"""`)
|
|
|
|
|
if bc.Range.OneLine() {
|
|
|
|
|
p.sb.WriteByte(' ')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lines := strings.Split(bc.Value, "\n")
|
|
|
|
|
for _, l := range lines {
|
|
|
|
|
if !bc.Range.OneLine() {
|
|
|
|
|
if l == "" {
|
|
|
|
|
p.sb.WriteByte('\n')
|
|
|
|
|
} else {
|
|
|
|
|
p.newline()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p.sb.WriteString(l)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !bc.Range.OneLine() {
|
|
|
|
|
p.newline()
|
|
|
|
|
} else {
|
|
|
|
|
p.sb.WriteByte(' ')
|
|
|
|
|
}
|
|
|
|
|
p.sb.WriteString(`"""`)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) interpolationBoxes(boxes []d2ast.InterpolationBox, isDoubleString bool) {
|
|
|
|
|
for _, b := range boxes {
|
|
|
|
|
if b.Substitution != nil {
|
|
|
|
|
p.substitution(b.Substitution)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if b.StringRaw == nil {
|
|
|
|
|
var s string
|
|
|
|
|
if isDoubleString {
|
|
|
|
|
s = escapeDoubledQuotedValue(*b.String, p.inKey)
|
|
|
|
|
} else {
|
|
|
|
|
s = escapeUnquotedValue(*b.String, p.inKey)
|
|
|
|
|
}
|
|
|
|
|
b.StringRaw = &s
|
|
|
|
|
}
|
2024-09-15 16:43:10 +00:00
|
|
|
if !isDoubleString {
|
|
|
|
|
if _, ok := d2ast.ReservedKeywords[strings.ToLower(*b.StringRaw)]; ok {
|
|
|
|
|
s := strings.ToLower(*b.StringRaw)
|
|
|
|
|
b.StringRaw = &s
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-11-03 13:54:49 +00:00
|
|
|
p.sb.WriteString(*b.StringRaw)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) blockString(bs *d2ast.BlockString) {
|
|
|
|
|
quote := bs.Quote
|
|
|
|
|
for strings.Contains(bs.Value, "|"+quote) {
|
|
|
|
|
if quote == "" {
|
|
|
|
|
quote += "|"
|
|
|
|
|
} else {
|
|
|
|
|
quote += string(quote[len(quote)-1])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for strings.Contains(bs.Value, quote+"|") {
|
|
|
|
|
quote += string(quote[len(quote)-1])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if bs.Range == (d2ast.Range{}) {
|
|
|
|
|
if strings.IndexByte(bs.Value, '\n') > -1 {
|
|
|
|
|
bs.Range = d2ast.MakeRange(",1:0:0-2:0:0")
|
|
|
|
|
}
|
|
|
|
|
bs.Value = strings.TrimSpace(bs.Value)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.sb.WriteString("|" + quote)
|
|
|
|
|
p.sb.WriteString(bs.Tag)
|
|
|
|
|
if !bs.Range.OneLine() {
|
|
|
|
|
p.indent()
|
|
|
|
|
} else {
|
|
|
|
|
p.sb.WriteByte(' ')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lines := strings.Split(bs.Value, "\n")
|
|
|
|
|
for _, l := range lines {
|
|
|
|
|
if !bs.Range.OneLine() {
|
|
|
|
|
if l == "" {
|
|
|
|
|
p.sb.WriteByte('\n')
|
|
|
|
|
} else {
|
|
|
|
|
p.newline()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p.sb.WriteString(l)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !bs.Range.OneLine() {
|
|
|
|
|
p.deindent()
|
|
|
|
|
p.newline()
|
|
|
|
|
} else if bs.Value != "" {
|
|
|
|
|
p.sb.WriteByte(' ')
|
|
|
|
|
}
|
|
|
|
|
p.sb.WriteString(quote + "|")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) path(els []*d2ast.StringBox) {
|
|
|
|
|
for i, s := range els {
|
|
|
|
|
p.node(s.Unbox())
|
|
|
|
|
if i < len(els)-1 {
|
|
|
|
|
p.sb.WriteByte('.')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) substitution(s *d2ast.Substitution) {
|
|
|
|
|
if s.Spread {
|
|
|
|
|
p.sb.WriteString("...")
|
|
|
|
|
}
|
|
|
|
|
p.sb.WriteString("${")
|
|
|
|
|
p.path(s.Path)
|
|
|
|
|
p.sb.WriteByte('}')
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-24 00:32:05 +00:00
|
|
|
func (p *printer) _import(i *d2ast.Import) {
|
|
|
|
|
if i.Spread {
|
|
|
|
|
p.sb.WriteString("...")
|
|
|
|
|
}
|
|
|
|
|
p.sb.WriteString("@")
|
2023-06-06 23:15:01 +00:00
|
|
|
pre := path.Clean(i.Pre)
|
|
|
|
|
if pre != "." {
|
|
|
|
|
p.sb.WriteString(pre)
|
|
|
|
|
p.sb.WriteRune('/')
|
|
|
|
|
}
|
2023-06-10 02:31:57 +00:00
|
|
|
if len(i.Path) > 0 {
|
|
|
|
|
i2 := *i
|
|
|
|
|
i2.Path = append([]*d2ast.StringBox{}, i.Path...)
|
|
|
|
|
i2.Path[0] = d2ast.RawStringBox(path.Clean(i.Path[0].Unbox().ScalarString()), true)
|
|
|
|
|
i = &i2
|
|
|
|
|
}
|
2023-05-24 00:32:05 +00:00
|
|
|
p.path(i.Path)
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-03 13:54:49 +00:00
|
|
|
func (p *printer) array(a *d2ast.Array) {
|
|
|
|
|
p.sb.WriteByte('[')
|
|
|
|
|
if !a.Range.OneLine() {
|
|
|
|
|
p.indent()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prev := d2ast.Node(a)
|
|
|
|
|
for i := 0; i < len(a.Nodes); i++ {
|
|
|
|
|
nb := a.Nodes[i]
|
|
|
|
|
n := nb.Unbox()
|
|
|
|
|
|
|
|
|
|
// Handle inline comments.
|
|
|
|
|
if i > 0 && (nb.Comment != nil || nb.BlockComment != nil) {
|
|
|
|
|
if n.GetRange().Start.Line == prev.GetRange().End.Line && n.GetRange().OneLine() {
|
|
|
|
|
p.sb.WriteByte(' ')
|
|
|
|
|
p.node(n)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !a.Range.OneLine() {
|
|
|
|
|
if prev != a {
|
|
|
|
|
if n.GetRange().Start.Line-prev.GetRange().End.Line > 1 {
|
|
|
|
|
p.sb.WriteByte('\n')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p.newline()
|
|
|
|
|
} else if i > 0 {
|
|
|
|
|
p.sb.WriteString("; ")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.node(n)
|
|
|
|
|
prev = n
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !a.Range.OneLine() {
|
|
|
|
|
p.deindent()
|
|
|
|
|
p.newline()
|
|
|
|
|
}
|
|
|
|
|
p.sb.WriteByte(']')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) _map(m *d2ast.Map) {
|
|
|
|
|
if !m.IsFileMap() {
|
|
|
|
|
p.sb.WriteByte('{')
|
|
|
|
|
if !m.Range.OneLine() {
|
|
|
|
|
p.indent()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 18:40:24 +00:00
|
|
|
layerNodes := []d2ast.MapNodeBox{}
|
|
|
|
|
scenarioNodes := []d2ast.MapNodeBox{}
|
|
|
|
|
stepNodes := []d2ast.MapNodeBox{}
|
|
|
|
|
|
2023-06-20 00:33:41 +00:00
|
|
|
prev := d2ast.Node(m)
|
2023-06-20 18:29:46 +00:00
|
|
|
for i := 0; i < len(m.Nodes); i++ {
|
|
|
|
|
nb := m.Nodes[i]
|
2022-11-03 13:54:49 +00:00
|
|
|
n := nb.Unbox()
|
2023-06-20 18:40:24 +00:00
|
|
|
// extract out layer, scenario, and step nodes and skip
|
2023-06-20 18:29:46 +00:00
|
|
|
if nb.IsBoardNode() {
|
2023-06-20 18:40:24 +00:00
|
|
|
switch nb.MapKey.Key.Path[0].Unbox().ScalarString() {
|
|
|
|
|
case "layers":
|
2024-10-27 05:21:30 +00:00
|
|
|
// remove useless
|
|
|
|
|
if nb.MapKey.Value.Map != nil && len(nb.MapKey.Value.Map.Nodes) > 0 {
|
|
|
|
|
layerNodes = append(layerNodes, nb)
|
|
|
|
|
}
|
2023-06-20 18:40:24 +00:00
|
|
|
case "scenarios":
|
2024-10-27 05:21:30 +00:00
|
|
|
if nb.MapKey.Value.Map != nil && len(nb.MapKey.Value.Map.Nodes) > 0 {
|
|
|
|
|
scenarioNodes = append(scenarioNodes, nb)
|
|
|
|
|
}
|
2023-06-20 18:40:24 +00:00
|
|
|
case "steps":
|
2024-10-27 05:21:30 +00:00
|
|
|
if nb.MapKey.Value.Map != nil && len(nb.MapKey.Value.Map.Nodes) > 0 {
|
|
|
|
|
stepNodes = append(stepNodes, nb)
|
|
|
|
|
}
|
2023-06-20 18:40:24 +00:00
|
|
|
}
|
2023-06-20 18:29:46 +00:00
|
|
|
prev = n
|
|
|
|
|
continue
|
|
|
|
|
}
|
2022-11-03 13:54:49 +00:00
|
|
|
|
|
|
|
|
// Handle inline comments.
|
|
|
|
|
if i > 0 && (nb.Comment != nil || nb.BlockComment != nil) {
|
|
|
|
|
if n.GetRange().Start.Line == prev.GetRange().End.Line && n.GetRange().OneLine() {
|
|
|
|
|
p.sb.WriteByte(' ')
|
|
|
|
|
p.node(n)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !m.Range.OneLine() {
|
|
|
|
|
if prev != m {
|
|
|
|
|
if n.GetRange().Start.Line-prev.GetRange().End.Line > 1 {
|
|
|
|
|
p.sb.WriteByte('\n')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if !m.IsFileMap() || i > 0 {
|
|
|
|
|
p.newline()
|
|
|
|
|
}
|
|
|
|
|
} else if i > 0 {
|
|
|
|
|
p.sb.WriteString("; ")
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 18:29:46 +00:00
|
|
|
p.node(n)
|
|
|
|
|
prev = n
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boards := []d2ast.MapNodeBox{}
|
|
|
|
|
boards = append(boards, layerNodes...)
|
|
|
|
|
boards = append(boards, scenarioNodes...)
|
|
|
|
|
boards = append(boards, stepNodes...)
|
|
|
|
|
|
|
|
|
|
// draw board nodes
|
|
|
|
|
for i := 0; i < len(boards); i++ {
|
|
|
|
|
n := boards[i].Unbox()
|
2023-06-20 20:09:17 +00:00
|
|
|
// if this board is the very first line of the file, don't add an extra newline
|
2023-06-20 18:29:46 +00:00
|
|
|
if n.GetRange().Start.Line != 0 {
|
2024-10-22 20:06:28 +00:00
|
|
|
p.sb.WriteByte('\n')
|
2023-06-20 18:29:46 +00:00
|
|
|
}
|
2023-06-20 20:09:17 +00:00
|
|
|
// if scope only has boards, don't newline the first board
|
2023-06-20 20:07:34 +00:00
|
|
|
if i != 0 || len(m.Nodes) > len(boards) {
|
2024-10-22 20:06:28 +00:00
|
|
|
p.sb.WriteByte('\n')
|
2023-06-20 00:33:41 +00:00
|
|
|
}
|
2024-10-22 20:06:28 +00:00
|
|
|
|
|
|
|
|
p.sb.WriteString(p.indentStr)
|
2022-11-03 13:54:49 +00:00
|
|
|
p.node(n)
|
|
|
|
|
prev = n
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !m.IsFileMap() {
|
|
|
|
|
if !m.Range.OneLine() {
|
|
|
|
|
p.deindent()
|
|
|
|
|
p.newline()
|
|
|
|
|
}
|
|
|
|
|
p.sb.WriteByte('}')
|
|
|
|
|
} else if len(m.Nodes) > 0 {
|
|
|
|
|
// Always write a trailing newline for nonempty file maps.
|
|
|
|
|
p.sb.WriteByte('\n')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) mapKey(mk *d2ast.Key) {
|
|
|
|
|
if mk.Ampersand {
|
|
|
|
|
p.sb.WriteByte('&')
|
2024-07-18 19:11:43 +00:00
|
|
|
} else if mk.NotAmpersand {
|
|
|
|
|
p.sb.WriteByte('!')
|
|
|
|
|
p.sb.WriteByte('&')
|
2022-11-03 13:54:49 +00:00
|
|
|
}
|
|
|
|
|
if mk.Key != nil {
|
|
|
|
|
p.key(mk.Key)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(mk.Edges) > 0 {
|
|
|
|
|
if mk.Key != nil {
|
|
|
|
|
p.sb.WriteByte('.')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if mk.Key != nil || mk.EdgeIndex != nil || mk.EdgeKey != nil {
|
|
|
|
|
p.sb.WriteByte('(')
|
|
|
|
|
}
|
|
|
|
|
if mk.Edges[0].Src != nil {
|
|
|
|
|
p.key(mk.Edges[0].Src)
|
|
|
|
|
p.sb.WriteByte(' ')
|
|
|
|
|
}
|
|
|
|
|
for i, e := range mk.Edges {
|
|
|
|
|
p.edgeArrowAndDst(e)
|
|
|
|
|
if i < len(mk.Edges)-1 {
|
|
|
|
|
p.sb.WriteByte(' ')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if mk.Key != nil || mk.EdgeIndex != nil || mk.EdgeKey != nil {
|
|
|
|
|
p.sb.WriteByte(')')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if mk.EdgeIndex != nil {
|
|
|
|
|
p.edgeIndex(mk.EdgeIndex)
|
|
|
|
|
}
|
|
|
|
|
if mk.EdgeKey != nil {
|
|
|
|
|
p.sb.WriteByte('.')
|
|
|
|
|
p.key(mk.EdgeKey)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if mk.Primary.Unbox() != nil {
|
|
|
|
|
p.sb.WriteString(": ")
|
|
|
|
|
p.node(mk.Primary.Unbox())
|
|
|
|
|
}
|
|
|
|
|
if mk.Value.Map != nil && len(mk.Value.Map.Nodes) == 0 {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if mk.Value.Unbox() != nil {
|
|
|
|
|
if mk.Primary.Unbox() == nil {
|
|
|
|
|
p.sb.WriteString(": ")
|
|
|
|
|
} else {
|
|
|
|
|
p.sb.WriteByte(' ')
|
|
|
|
|
}
|
|
|
|
|
p.node(mk.Value.Unbox())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) key(k *d2ast.KeyPath) {
|
|
|
|
|
p.inKey = true
|
|
|
|
|
if k != nil {
|
|
|
|
|
p.path(k.Path)
|
|
|
|
|
}
|
|
|
|
|
p.inKey = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) edge(e *d2ast.Edge) {
|
|
|
|
|
if e.Src != nil {
|
|
|
|
|
p.key(e.Src)
|
|
|
|
|
p.sb.WriteByte(' ')
|
|
|
|
|
}
|
|
|
|
|
p.edgeArrowAndDst(e)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) edgeArrowAndDst(e *d2ast.Edge) {
|
|
|
|
|
if e.SrcArrow == "" {
|
|
|
|
|
p.sb.WriteByte('-')
|
|
|
|
|
} else {
|
|
|
|
|
p.sb.WriteString(e.SrcArrow)
|
|
|
|
|
}
|
|
|
|
|
if e.DstArrow == "" {
|
|
|
|
|
p.sb.WriteByte('-')
|
|
|
|
|
} else {
|
|
|
|
|
if e.SrcArrow != "" {
|
|
|
|
|
p.sb.WriteByte('-')
|
|
|
|
|
}
|
|
|
|
|
p.sb.WriteString(e.DstArrow)
|
|
|
|
|
}
|
|
|
|
|
if e.Dst != nil {
|
|
|
|
|
p.sb.WriteByte(' ')
|
|
|
|
|
p.key(e.Dst)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *printer) edgeIndex(ei *d2ast.EdgeIndex) {
|
|
|
|
|
p.sb.WriteByte('[')
|
|
|
|
|
if ei.Glob {
|
|
|
|
|
p.sb.WriteByte('*')
|
|
|
|
|
} else {
|
|
|
|
|
p.sb.WriteString(strconv.Itoa(*ei.Int))
|
|
|
|
|
}
|
|
|
|
|
p.sb.WriteByte(']')
|
|
|
|
|
}
|
2023-01-11 23:50:49 +00:00
|
|
|
|
2023-01-28 01:19:12 +00:00
|
|
|
func KeyPath(kp *d2ast.KeyPath) (ida []string) {
|
2023-01-11 23:50:49 +00:00
|
|
|
for _, s := range kp.Path {
|
|
|
|
|
// We format each string of the key to ensure the resulting strings can be parsed
|
|
|
|
|
// correctly.
|
|
|
|
|
n := &d2ast.KeyPath{
|
|
|
|
|
Path: []*d2ast.StringBox{d2ast.MakeValueBox(d2ast.RawString(s.Unbox().ScalarString(), true)).StringBox()},
|
|
|
|
|
}
|
2023-01-28 01:19:12 +00:00
|
|
|
ida = append(ida, Format(n))
|
2023-01-11 23:50:49 +00:00
|
|
|
}
|
2023-01-28 01:19:12 +00:00
|
|
|
return ida
|
2023-01-11 23:50:49 +00:00
|
|
|
}
|