cchat/repository/comment.go

113 lines
2.4 KiB
Go

package repository
import (
"bytes"
"go/doc"
"regexp"
"strings"
)
var (
// commentTrimSurrounding is a regex to trim surrounding new line and tabs.
// This is needed to find the correct level of indentation.
commentTrimSurrounding = regexp.MustCompile(`(^\n)|(\n\t+$)`)
)
// TabWidth is used to format comments.
var TabWidth = 4
// Comment represents a raw comment string. Most use cases should use GoString()
// to get the comment's content.
type Comment struct {
Raw string
}
// IsEmpty returns true if the comment is empty.
func (c Comment) IsEmpty() bool {
return c.Raw == ""
}
// GoString formats the documentation string in 80 columns wide paragraphs and
// prefix each line with "// ". The ident argument controls the nested level. If
// less than or equal to zero, then it is changed to 1, which is the top level.
func (c Comment) GoString(ident int) string {
if c.Raw == "" {
return ""
}
if ident < 1 {
ident = 1
}
ident-- // 0th-indexed
ident *= TabWidth
var lines = strings.Split(c.WrapText(80-len("// ")-ident), "\n")
for i, line := range lines {
if line != "" {
line = "// " + line
} else {
line = "//"
}
lines[i] = line
}
return strings.Join(lines, "\n")
}
// WrapText wraps the raw text in n columns wide paragraphs.
func (c Comment) WrapText(column int) string {
var txt = c.Unindent()
if txt == "" {
return ""
}
buf := bytes.Buffer{}
doc.ToText(&buf, txt, "", strings.Repeat(" ", TabWidth-1), column)
text := strings.TrimRight(buf.String(), "\n")
text = strings.Replace(text, "\t", strings.Repeat(" ", TabWidth), -1)
return text
}
// Unindent removes the indentations that were there for the sake of syntax in
// RawText. It gets the lowest indentation level from each line and trim it.
func (c Comment) Unindent() string {
if c.IsEmpty() {
return ""
}
// Trim new lines.
txt := commentTrimSurrounding.ReplaceAllString(c.Raw, "")
// Split the lines and rejoin them later to trim the indentation.
var lines = strings.Split(txt, "\n")
var indent = 0
// Get the minimum indentation count.
for _, line := range lines {
linedent := strings.Count(line, "\t")
if linedent < 0 {
continue
}
if linedent < indent || indent == 0 {
indent = linedent
}
}
// Trim the indentation.
if indent > 0 {
for i, line := range lines {
if len(line) > 0 {
lines[i] = line[indent-1:]
}
}
}
// Rejoin.
txt = strings.Join(lines, "\n")
return txt
}