Move configuration reports to shared rendering
This commit is contained in:
@@ -4,8 +4,6 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"unicode"
|
||||
|
||||
commandkit "go.maximumdirect.net/commandkit"
|
||||
)
|
||||
@@ -23,13 +21,9 @@ func runConfigShow[I, S any](invocation commandkit.Invocation, plan *configOpera
|
||||
return configFailure("Configuration show was canceled.", commandkit.Explanation{}, err)
|
||||
}
|
||||
if selected.scope.scope.Acquire == nil {
|
||||
message := fmt.Sprintf("Configuration scope %q has no acquisition callback.", selected.scope.scope.Name)
|
||||
return commandkit.Failure(message)
|
||||
return commandkit.Failure(fmt.Sprintf("Configuration scope %q has no acquisition callback.", selected.scope.scope.Name))
|
||||
}
|
||||
acquired, acquireErr := selected.scope.scope.Acquire(invocation.Context, Request{
|
||||
Operation: Show,
|
||||
Selection: plan.selection,
|
||||
}, selected.input, state)
|
||||
acquired, acquireErr := selected.scope.scope.Acquire(invocation.Context, Request{Operation: Show, Selection: plan.selection}, selected.input, state)
|
||||
if acquireErr != nil {
|
||||
return configAcquisitionFailure(reporter, "show", selected.scope.scope.Name, acquired, acquireErr)
|
||||
}
|
||||
@@ -38,26 +32,17 @@ func runConfigShow[I, S any](invocation commandkit.Invocation, plan *configOpera
|
||||
return configFailure("Configuration show was canceled.", acquired.Explanation, err)
|
||||
}
|
||||
if acquired.Value.Effective == nil {
|
||||
message := fmt.Sprintf("Configuration scope %q did not provide an effective configuration writer.", selected.scope.scope.Name)
|
||||
return commandkit.Failure(message)
|
||||
return commandkit.Failure(fmt.Sprintf("Configuration scope %q did not provide an effective configuration writer.", selected.scope.scope.Name))
|
||||
}
|
||||
documents = append(documents, effectiveDocument{name: selected.scope.scope.Name, view: acquired.Value})
|
||||
}
|
||||
if err := invocation.Context.Err(); err != nil {
|
||||
return configFailure("Configuration show was canceled.", commandkit.Explanation{}, err)
|
||||
}
|
||||
if len(documents) == 1 && plan.scopeName != "all" {
|
||||
err := reporter.RenderOutput(func(writer io.Writer) error {
|
||||
return documents[0].view.Effective.WriteEffective(writer)
|
||||
})
|
||||
if err != nil && invocation.Context.Err() != nil {
|
||||
return configFailure("Configuration show was canceled.", commandkit.Explanation{}, invocation.Context.Err())
|
||||
}
|
||||
return commandkit.Success()
|
||||
}
|
||||
|
||||
err := reporter.RenderOutput(func(writer io.Writer) error {
|
||||
for index, document := range documents {
|
||||
var value any
|
||||
err := reporter.RenderOutput(func(io.Writer) error {
|
||||
values := make(map[string]any, len(documents))
|
||||
for _, document := range documents {
|
||||
if err := invocation.Context.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -65,112 +50,28 @@ func runConfigShow[I, S any](invocation commandkit.Invocation, plan *configOpera
|
||||
if err := document.view.Effective.WriteEffective(&native); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := invocation.Context.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
framed, hasDirective := frameEffectiveYAML(document.name, native.Bytes())
|
||||
if index > 0 && hasDirective {
|
||||
if _, err := io.WriteString(writer, "...\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if index < len(documents)-1 && len(framed) > 0 && framed[len(framed)-1] != '\n' {
|
||||
framed = append(framed, '\n')
|
||||
}
|
||||
if _, err := writer.Write(framed); err != nil {
|
||||
decoded, err := commandkit.DecodeYAMLReport(&native)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
values[document.name] = decoded
|
||||
}
|
||||
if plan.scopeName == "all" {
|
||||
value = values
|
||||
} else {
|
||||
value = values[documents[0].name]
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil && invocation.Context.Err() != nil {
|
||||
return configFailure("Configuration show was canceled.", commandkit.Explanation{}, invocation.Context.Err())
|
||||
if err != nil {
|
||||
if canceled := invocation.Context.Err(); canceled != nil {
|
||||
return configFailure("Configuration show was canceled.", commandkit.Explanation{}, canceled)
|
||||
}
|
||||
return commandkit.Success()
|
||||
}
|
||||
if err := invocation.Context.Err(); err != nil {
|
||||
return configFailure("Configuration show was canceled.", commandkit.Explanation{}, err)
|
||||
}
|
||||
_ = reporter.Report(commandkit.Report{Value: value})
|
||||
return commandkit.Success()
|
||||
}
|
||||
|
||||
type yamlPreamble struct {
|
||||
markerStart int
|
||||
markerEnd int
|
||||
markerFound bool
|
||||
inlineMarker bool
|
||||
preambleEnd int
|
||||
hasDirective bool
|
||||
}
|
||||
|
||||
func analyzeYAMLPreamble(native []byte) yamlPreamble {
|
||||
var analysis yamlPreamble
|
||||
for start := 0; start < len(native); {
|
||||
end := len(native)
|
||||
if newline := bytes.IndexByte(native[start:], '\n'); newline >= 0 {
|
||||
end = start + newline + 1
|
||||
}
|
||||
lineEnd := end
|
||||
if lineEnd > start && native[lineEnd-1] == '\n' {
|
||||
lineEnd--
|
||||
}
|
||||
trimmed := bytes.TrimSpace(native[start:lineEnd])
|
||||
if isYAMLDocumentStart(trimmed) {
|
||||
content := bytes.TrimSpace(trimmed[3:])
|
||||
analysis.markerStart = start
|
||||
analysis.markerEnd = end
|
||||
analysis.markerFound = true
|
||||
analysis.inlineMarker = len(content) > 0 && content[0] != '#'
|
||||
return analysis
|
||||
}
|
||||
if bytes.HasPrefix(trimmed, []byte("%YAML ")) || bytes.HasPrefix(trimmed, []byte("%TAG ")) {
|
||||
analysis.hasDirective = true
|
||||
}
|
||||
if len(trimmed) == 0 || trimmed[0] == '#' || bytes.HasPrefix(trimmed, []byte("%YAML ")) || bytes.HasPrefix(trimmed, []byte("%TAG ")) {
|
||||
analysis.preambleEnd = end
|
||||
} else {
|
||||
return analysis
|
||||
}
|
||||
start = end
|
||||
}
|
||||
return analysis
|
||||
}
|
||||
|
||||
func frameEffectiveYAML(scope string, native []byte) ([]byte, bool) {
|
||||
analysis := analyzeYAMLPreamble(native)
|
||||
label := scope
|
||||
for _, character := range scope {
|
||||
if unicode.IsControl(character) {
|
||||
label = strconv.Quote(scope)
|
||||
break
|
||||
}
|
||||
}
|
||||
comment := []byte("# scope: " + label + "\n")
|
||||
if analysis.markerFound {
|
||||
out := make([]byte, 0, len(native)+len(comment))
|
||||
if analysis.inlineMarker {
|
||||
out = append(out, native[:analysis.markerStart]...)
|
||||
out = append(out, comment...)
|
||||
out = append(out, native[analysis.markerStart:]...)
|
||||
return out, analysis.hasDirective
|
||||
}
|
||||
out = append(out, native[:analysis.markerEnd]...)
|
||||
if analysis.markerEnd > analysis.markerStart && native[analysis.markerEnd-1] != '\n' {
|
||||
out = append(out, '\n')
|
||||
}
|
||||
out = append(out, comment...)
|
||||
out = append(out, native[analysis.markerEnd:]...)
|
||||
return out, analysis.hasDirective
|
||||
}
|
||||
result := make([]byte, 0, len(native)+len(comment)+5)
|
||||
if analysis.hasDirective {
|
||||
result = append(result, native[:analysis.preambleEnd]...)
|
||||
}
|
||||
result = append(result, []byte("---\n")...)
|
||||
result = append(result, comment...)
|
||||
if analysis.hasDirective {
|
||||
result = append(result, native[analysis.preambleEnd:]...)
|
||||
} else {
|
||||
result = append(result, native...)
|
||||
}
|
||||
return result, analysis.hasDirective
|
||||
}
|
||||
|
||||
func isYAMLDocumentStart(line []byte) bool {
|
||||
return bytes.HasPrefix(line, []byte("---")) && (len(line) == 3 || line[3] == ' ' || line[3] == '\t')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user