notation/notation.go
2020-10-22 20:55:32 +02:00

144 lines
2.4 KiB
Go

package notation
import (
"bytes"
"io"
"os"
"reflect"
"strconv"
"strings"
)
type opts int
const none opts = 0
const (
wrap opts = 1 << iota
types
skipTypes
allTypes
)
type node struct {
len, wlen, wlen0, wlenLast int
wrap bool
parts []interface{}
}
type wrapper struct {
sep, suffix string
items []node
}
func nodeOf(parts ...interface{}) node {
return node{parts: parts}
}
func config(name string, dflt int) int {
s := os.Getenv(name)
if s == "" {
s = os.Getenv(strings.ToLower(name))
}
if s == "" {
return dflt
}
v, err := strconv.Atoi(s)
if err != nil {
return dflt
}
return v
}
func fprintValues(w io.Writer, o opts, v []interface{}) (int, error) {
tab := config("TABWIDTH", 8)
cols0 := config("LINEWIDTH", 80-8)
cols1 := config("LINEWIDTH1", (cols0+8)*3/2-8)
wr := &writer{w: w}
for i, vi := range v {
if wr.err != nil {
return wr.n, wr.err
}
if i > 0 {
if o&wrap == 0 {
wr.write(" ")
} else {
wr.write("\n")
}
}
if vi == nil {
fprint(wr, 0, nodeOf("nil"))
continue
}
n := reflectValue(o, reflect.ValueOf(vi))
if o&wrap != 0 {
n = nodeLen(tab, n)
n = wrapNode(tab, cols0, cols1, n)
}
fprint(wr, 0, n)
}
return wr.n, wr.err
}
func sprintValues(o opts, v []interface{}) string {
var b bytes.Buffer
fprintValues(&b, o, v)
return b.String()
}
func Fprint(w io.Writer, v ...interface{}) (int, error) {
return fprintValues(w, none, v)
}
func Fprintw(w io.Writer, v ...interface{}) (int, error) {
return fprintValues(w, wrap, v)
}
func Fprintt(w io.Writer, v ...interface{}) (int, error) {
return fprintValues(w, types, v)
}
func Fprintwt(w io.Writer, v ...interface{}) (int, error) {
return fprintValues(w, wrap|types, v)
}
func Fprintv(w io.Writer, v ...interface{}) (int, error) {
return fprintValues(w, allTypes, v)
}
func Fprintwv(w io.Writer, v ...interface{}) (int, error) {
return fprintValues(w, wrap|allTypes, v)
}
func Sprint(v ...interface{}) string {
return sprintValues(none, v)
}
func Sprintw(v ...interface{}) string {
return sprintValues(wrap, v)
}
func Sprintt(v ...interface{}) string {
return sprintValues(types, v)
}
func Sprintwt(v ...interface{}) string {
return sprintValues(wrap|types, v)
}
func Sprintv(v ...interface{}) string {
return sprintValues(allTypes, v)
}
func Sprintwv(v ...interface{}) string {
return sprintValues(wrap|allTypes, v)
}