structure.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // Copyright 2013 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package pretty
  15. import (
  16. "bufio"
  17. "bytes"
  18. "fmt"
  19. "io"
  20. "strconv"
  21. "strings"
  22. )
  23. // a formatter stores stateful formatting information as well as being
  24. // an io.Writer for simplicity.
  25. type formatter struct {
  26. *bufio.Writer
  27. *Config
  28. // Self-referential structure tracking
  29. tagNumbers map[int]int // tagNumbers[id] = <#n>
  30. }
  31. // newFormatter creates a new buffered formatter. For the output to be written
  32. // to the given writer, this must be accompanied by a call to write (or Flush).
  33. func newFormatter(cfg *Config, w io.Writer) *formatter {
  34. return &formatter{
  35. Writer: bufio.NewWriter(w),
  36. Config: cfg,
  37. tagNumbers: make(map[int]int),
  38. }
  39. }
  40. func (f *formatter) write(n node) {
  41. defer f.Flush()
  42. n.format(f, "")
  43. }
  44. func (f *formatter) tagFor(id int) int {
  45. if tag, ok := f.tagNumbers[id]; ok {
  46. return tag
  47. }
  48. if f.tagNumbers == nil {
  49. return 0
  50. }
  51. tag := len(f.tagNumbers) + 1
  52. f.tagNumbers[id] = tag
  53. return tag
  54. }
  55. type node interface {
  56. format(f *formatter, indent string)
  57. }
  58. func (f *formatter) compactString(n node) string {
  59. switch k := n.(type) {
  60. case stringVal:
  61. return string(k)
  62. case rawVal:
  63. return string(k)
  64. }
  65. buf := new(bytes.Buffer)
  66. f2 := newFormatter(&Config{Compact: true}, buf)
  67. f2.tagNumbers = f.tagNumbers // reuse tagNumbers just in case
  68. f2.write(n)
  69. return buf.String()
  70. }
  71. type stringVal string
  72. func (str stringVal) format(f *formatter, indent string) {
  73. f.WriteString(strconv.Quote(string(str)))
  74. }
  75. type rawVal string
  76. func (r rawVal) format(f *formatter, indent string) {
  77. f.WriteString(string(r))
  78. }
  79. type keyval struct {
  80. key string
  81. val node
  82. }
  83. type keyvals []keyval
  84. func (l keyvals) format(f *formatter, indent string) {
  85. f.WriteByte('{')
  86. switch {
  87. case f.Compact:
  88. // All on one line:
  89. for i, kv := range l {
  90. if i > 0 {
  91. f.WriteByte(',')
  92. }
  93. f.WriteString(kv.key)
  94. f.WriteByte(':')
  95. kv.val.format(f, indent)
  96. }
  97. case f.Diffable:
  98. f.WriteByte('\n')
  99. inner := indent + " "
  100. // Each value gets its own line:
  101. for _, kv := range l {
  102. f.WriteString(inner)
  103. f.WriteString(kv.key)
  104. f.WriteString(": ")
  105. kv.val.format(f, inner)
  106. f.WriteString(",\n")
  107. }
  108. f.WriteString(indent)
  109. default:
  110. keyWidth := 0
  111. for _, kv := range l {
  112. if kw := len(kv.key); kw > keyWidth {
  113. keyWidth = kw
  114. }
  115. }
  116. alignKey := indent + " "
  117. alignValue := strings.Repeat(" ", keyWidth)
  118. inner := alignKey + alignValue + " "
  119. // First and last line shared with bracket:
  120. for i, kv := range l {
  121. if i > 0 {
  122. f.WriteString(",\n")
  123. f.WriteString(alignKey)
  124. }
  125. f.WriteString(kv.key)
  126. f.WriteString(": ")
  127. f.WriteString(alignValue[len(kv.key):])
  128. kv.val.format(f, inner)
  129. }
  130. }
  131. f.WriteByte('}')
  132. }
  133. type list []node
  134. func (l list) format(f *formatter, indent string) {
  135. if max := f.ShortList; max > 0 {
  136. short := f.compactString(l)
  137. if len(short) <= max {
  138. f.WriteString(short)
  139. return
  140. }
  141. }
  142. f.WriteByte('[')
  143. switch {
  144. case f.Compact:
  145. // All on one line:
  146. for i, v := range l {
  147. if i > 0 {
  148. f.WriteByte(',')
  149. }
  150. v.format(f, indent)
  151. }
  152. case f.Diffable:
  153. f.WriteByte('\n')
  154. inner := indent + " "
  155. // Each value gets its own line:
  156. for _, v := range l {
  157. f.WriteString(inner)
  158. v.format(f, inner)
  159. f.WriteString(",\n")
  160. }
  161. f.WriteString(indent)
  162. default:
  163. inner := indent + " "
  164. // First and last line shared with bracket:
  165. for i, v := range l {
  166. if i > 0 {
  167. f.WriteString(",\n")
  168. f.WriteString(inner)
  169. }
  170. v.format(f, inner)
  171. }
  172. }
  173. f.WriteByte(']')
  174. }
  175. type ref struct {
  176. id int
  177. }
  178. func (r ref) format(f *formatter, indent string) {
  179. fmt.Fprintf(f, "<see #%d>", f.tagFor(r.id))
  180. }
  181. type target struct {
  182. id int
  183. value node
  184. }
  185. func (t target) format(f *formatter, indent string) {
  186. tag := fmt.Sprintf("<#%d> ", f.tagFor(t.id))
  187. switch {
  188. case f.Diffable, f.Compact:
  189. // no indent changes
  190. default:
  191. indent += strings.Repeat(" ", len(tag))
  192. }
  193. f.WriteString(tag)
  194. t.value.format(f, indent)
  195. }