191 lines
4.6 KiB
Go
191 lines
4.6 KiB
Go
package protofmt
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
|
|
"github.com/emicklei/proto"
|
|
)
|
|
|
|
// printDoc writes documentation is available
|
|
func (f *Formatter) printDoc(v proto.Visitee) {
|
|
if hasDoc, ok := v.(proto.Documented); ok {
|
|
if doc := hasDoc.Doc(); doc != nil {
|
|
f.printComment(doc)
|
|
}
|
|
}
|
|
}
|
|
|
|
// printComment formats a Comment.
|
|
func (f *Formatter) printComment(c *proto.Comment) {
|
|
f.nl()
|
|
if c.Cstyle {
|
|
f.indent(0)
|
|
fmt.Fprintln(f.w, "/*")
|
|
}
|
|
for i, each := range c.Lines {
|
|
each = strings.TrimRight(each, " ")
|
|
f.indent(0)
|
|
if c.Cstyle {
|
|
// only skip first and last empty lines
|
|
skip := (i == 0 && len(each) == 0) ||
|
|
(i == len(c.Lines)-1 && len(each) == 0)
|
|
if !skip {
|
|
fmt.Fprintf(f.w, "%s\n", each)
|
|
}
|
|
} else {
|
|
if c.ExtraSlash {
|
|
fmt.Fprint(f.w, "/")
|
|
}
|
|
fmt.Fprintf(f.w, "//%s\n", each)
|
|
}
|
|
}
|
|
if c.Cstyle {
|
|
fmt.Fprintf(f.w, "*/\n")
|
|
}
|
|
}
|
|
|
|
// begin writes a newline if the last statement kind is different. always indents.
|
|
// if the Visitee has comment then print it.
|
|
func (f *Formatter) begin(stmt string, v proto.Visitee) {
|
|
// if not the first statement and different from last and on same indent level.
|
|
if len(f.lastStmt) > 0 && f.lastStmt != stmt && f.lastLevel == f.indentLevel {
|
|
f.nl()
|
|
}
|
|
f.lastStmt = stmt
|
|
f.printDoc(v)
|
|
f.indent(0)
|
|
}
|
|
|
|
// beginNoDoc writes a newline if the last statement kind is different. always indents.
|
|
func (f *Formatter) beginNoDoc(stmt string, v proto.Visitee) {
|
|
// if not the first statement and different from last and on same indent level.
|
|
if len(f.lastStmt) > 0 && f.lastStmt != stmt && f.lastLevel == f.indentLevel {
|
|
f.nl()
|
|
}
|
|
f.lastStmt = stmt
|
|
f.indent(0)
|
|
}
|
|
|
|
func (f *Formatter) end(stmt string) {
|
|
f.lastStmt = stmt
|
|
}
|
|
|
|
// indent changes the indent level and writes indentation.
|
|
func (f *Formatter) indent(diff int) {
|
|
f.level(diff)
|
|
for i := 0; i < f.indentLevel; i++ {
|
|
io.WriteString(f.w, f.indentSeparator)
|
|
}
|
|
}
|
|
|
|
func (f *Formatter) printListOfColumns(list []columnsPrintable) {
|
|
if len(list) == 0 {
|
|
return
|
|
}
|
|
// collect all column values
|
|
values := [][]aligned{}
|
|
widths := map[int]int{}
|
|
for _, each := range list {
|
|
cols := each.columns()
|
|
values = append(values, cols)
|
|
// update max widths per column
|
|
for i, other := range cols {
|
|
pw := other.preferredWidth()
|
|
w, ok := widths[i]
|
|
if ok {
|
|
if pw > w {
|
|
widths[i] = pw
|
|
}
|
|
} else {
|
|
widths[i] = pw
|
|
}
|
|
}
|
|
}
|
|
// now print all values
|
|
for _, each := range values {
|
|
f.indent(0)
|
|
for c := 0; c < len(widths); c++ {
|
|
pw := widths[c]
|
|
// only print if there is a value
|
|
if c < len(each) {
|
|
// using space padding to match the max width
|
|
io.WriteString(f.w, each[c].formatted(f.indentSeparator, f.indentLevel, pw))
|
|
}
|
|
}
|
|
f.nl()
|
|
}
|
|
}
|
|
|
|
// nl writes a newline.
|
|
func (f *Formatter) nl() {
|
|
io.WriteString(f.w, "\n")
|
|
}
|
|
|
|
// level changes the current indentLevel but does not print indentation.
|
|
func (f *Formatter) level(diff int) {
|
|
f.lastLevel = f.indentLevel
|
|
f.indentLevel += diff
|
|
}
|
|
|
|
// printAsGroups prints the list in groups of the same element type.
|
|
func (f *Formatter) printAsGroups(list []proto.Visitee) {
|
|
group := []columnsPrintable{}
|
|
lastGroupName := ""
|
|
for _, each := range list {
|
|
groupName := nameOfVisitee(each)
|
|
printable, isColumnsPrintable := typeAssertColumnsPrintable(each)
|
|
if isColumnsPrintable {
|
|
if lastGroupName != groupName {
|
|
lastGroupName = groupName
|
|
// print current group
|
|
if len(group) > 0 {
|
|
f.printListOfColumns(group)
|
|
// begin new group
|
|
group = []columnsPrintable{}
|
|
}
|
|
}
|
|
// comment as a group entity
|
|
if hasDoc, ok := each.(proto.Documented); ok {
|
|
if doc := hasDoc.Doc(); doc != nil {
|
|
f.printListOfColumns(group)
|
|
// begin new group
|
|
//group = []columnsPrintable{}
|
|
//if len(doc.Lines) > 0 { // if comment then add newline before it
|
|
// group = append(group, inlineComment{line: "", extraSlash: false})
|
|
//}
|
|
group = append([]columnsPrintable{}, columnsPrintables(doc)...)
|
|
}
|
|
}
|
|
group = append(group, printable)
|
|
} else {
|
|
// not printable in group
|
|
lastGroupName = groupName
|
|
// print current group
|
|
if len(group) > 0 {
|
|
f.printListOfColumns(group)
|
|
// begin new group
|
|
group = []columnsPrintable{}
|
|
}
|
|
each.Accept(f)
|
|
}
|
|
}
|
|
// print last group
|
|
f.printListOfColumns(group)
|
|
}
|
|
|
|
// endWithComment writes a statement end (;) followed by inline comment if present.
|
|
func (f *Formatter) endWithComment(commentOrNil *proto.Comment) {
|
|
io.WriteString(f.w, ";")
|
|
if commentOrNil != nil {
|
|
if commentOrNil.ExtraSlash {
|
|
io.WriteString(f.w, " ///")
|
|
} else {
|
|
io.WriteString(f.w, " //")
|
|
}
|
|
io.WriteString(f.w, commentOrNil.Message())
|
|
}
|
|
io.WriteString(f.w, "\n")
|
|
}
|