sq/cli/output/tablew/configwriter.go
Neil O'Toole db55986980
#307: Ingest cache (#354)
- Support for ingest cache, download cache, and progress bars.
2024-01-14 18:45:34 -07:00

237 lines
4.9 KiB
Go

package tablew
import (
"context"
"fmt"
"io"
"github.com/fatih/color"
"github.com/samber/lo"
"github.com/neilotoole/sq/cli/output"
"github.com/neilotoole/sq/libsq/core/errz"
"github.com/neilotoole/sq/libsq/core/options"
"github.com/neilotoole/sq/libsq/core/stringz"
)
var _ output.ConfigWriter = (*configWriter)(nil)
// configWriter implements output.ConfigWriter.
type configWriter struct {
tbl *table
}
// NewConfigWriter returns a new output.ConfigWriter.
func NewConfigWriter(out io.Writer, pr *output.Printing) output.ConfigWriter {
tbl := &table{out: out, pr: pr, header: pr.ShowHeader}
tbl.reset()
return &configWriter{tbl: tbl}
}
// Location implements output.ConfigWriter.
func (w *configWriter) Location(path, origin string) error {
fmt.Fprintln(w.tbl.out, path)
if w.tbl.pr.Verbose && origin != "" {
w.tbl.pr.Faint.Fprint(w.tbl.out, "Origin: ")
w.tbl.pr.String.Fprintln(w.tbl.out, origin)
}
return nil
}
// CacheLocation implements output.ConfigWriter.
func (w *configWriter) CacheLocation(loc string) error {
_, err := fmt.Fprintln(w.tbl.out, loc)
return errz.Err(err)
}
// CacheStat implements output.ConfigWriter.
func (w *configWriter) CacheStat(loc string, enabled bool, size int64) error {
const sp = " "
s := loc + sp
if enabled {
s += w.tbl.pr.Enabled.Sprint("enabled") + sp
} else {
s += w.tbl.pr.Disabled.Sprint("disabled") + sp
}
if size == -1 {
s += w.tbl.pr.Warning.Sprint("(size unavailable)")
} else {
s += w.tbl.pr.Faint.Sprintf("(%s)", stringz.ByteSized(size, 1, ""))
}
_, err := fmt.Fprintln(w.tbl.out, s)
return err
}
// Opt implements output.ConfigWriter.
func (w *configWriter) Opt(o options.Options, opt options.Opt) error {
if o == nil || opt == nil {
return nil
}
if !w.tbl.pr.Verbose {
if !o.IsSet(opt) {
return nil
}
clr := getOptColor(w.tbl.pr, opt)
clr.Fprintln(w.tbl.out, opt.GetAny(o))
return nil
}
o2 := options.Options{opt.Key(): o[opt.Key()]}
reg2 := &options.Registry{}
reg2.Add(opt)
return w.Options(reg2, o2)
}
// Options implements output.ConfigWriter.
func (w *configWriter) Options(reg *options.Registry, o options.Options) error {
if o == nil {
return nil
}
if w.tbl.pr.Verbose {
w.tbl.pr.ShowHeader = true
} else {
w.tbl.pr.ShowHeader = false
}
return w.doPrintOptions(reg, o, true)
}
// Options implements output.ConfigWriter.
// If printUnset is true and we're in verbose mode, unset options
// are also printed.
func (w *configWriter) doPrintOptions(reg *options.Registry, o options.Options, printUnset bool) error {
if o == nil {
return nil
}
t, pr, verbose := w.tbl.tblImpl, w.tbl.pr, w.tbl.pr.Verbose
if pr.ShowHeader {
headers := []string{"KEY", "VALUE"}
if verbose {
headers = []string{"KEY", "VALUE", "DEFAULT"}
}
t.SetHeader(headers)
}
t.SetColTrans(0, pr.Key.SprintFunc())
var rows [][]string
keys := o.Keys()
for _, k := range keys {
opt := reg.Get(k)
if opt == nil {
// Shouldn't happen, but print anyway just in case
row := []string{
k,
pr.Error.Sprintf("%v", o[k]),
}
if verbose {
// Can't know default in this situation.
row = append(row, "")
}
rows = append(rows, row)
continue
}
clr := getOptColor(pr, opt)
val, ok := o[k]
if !ok || val == nil {
if verbose {
val = ""
} else {
val = "NULL"
}
clr = pr.Null
}
row := []string{
k,
clr.Sprintf("%v", val),
}
if verbose {
defaultVal := pr.Faint.Sprintf("%v", opt.GetAny(nil))
row = append(row, defaultVal)
}
rows = append(rows, row)
}
if !printUnset || !verbose {
return w.tbl.appendRowsAndRenderAll(context.TODO(), rows)
}
// Also print the unset opts
allKeys := reg.Keys()
setKeys := o.Keys()
unsetKeys, _ := lo.Difference(allKeys, setKeys)
for _, k := range unsetKeys {
opt := reg.Get(k)
row := []string{
pr.Faint.Sprintf("%v", k),
"", // opt is unset, so it doesn't have a value
pr.Faint.Sprintf("%v", opt.GetAny(nil)),
}
rows = append(rows, row)
}
return w.tbl.appendRowsAndRenderAll(context.TODO(), rows)
}
// SetOption implements output.ConfigWriter.
func (w *configWriter) SetOption(o options.Options, opt options.Opt) error {
if !w.tbl.pr.Verbose {
// No output unless verbose
return nil
}
reg2 := &options.Registry{}
reg2.Add(opt)
o = options.Options{opt.Key(): opt.GetAny(o)}
// It's verbose
o = options.Effective(o, opt)
w.tbl.pr.ShowHeader = true
return w.doPrintOptions(reg2, o, false)
}
// UnsetOption implements output.ConfigWriter.
func (w *configWriter) UnsetOption(opt options.Opt) error {
if !w.tbl.pr.Verbose {
// No output unless verbose
return nil
}
reg := &options.Registry{}
reg.Add(opt)
o := options.Options{}
return w.doPrintOptions(reg, o, true)
}
func getOptColor(pr *output.Printing, opt options.Opt) *color.Color {
if opt == nil {
return pr.Null
}
clr := pr.String
switch opt.(type) {
case options.Bool:
clr = pr.Bool
case options.Int:
clr = pr.Number
default:
}
return clr
}