Added go template processor
All checks were successful
Build / build (push) Successful in 34s

This commit is contained in:
Leon Mika 2026-03-14 22:47:56 +11:00
parent d64779f660
commit 855a0aa114
2 changed files with 87 additions and 22 deletions

59
app.go
View file

@ -91,6 +91,33 @@ func (a *App) ProcessText(req ProcessTextRequest) {
return
}
applyFilter := func(filter TextFilter) {
resp, err := moslice.MapWithError(req.Input, func(span TextSpan) (TextSpan, error) {
outRes, err := filter(a.ctx, span.Text)
if err != nil {
return TextSpan{}, err
}
return TextSpan{
Text: outRes.Output,
Pos: span.Pos,
Len: span.Len,
Append: outRes.Append,
}, nil
})
if err != nil {
runtime.EventsEmit(a.ctx, "set-statusbar-message", SetStatusbarMessage{
Message: fmt.Sprintf("Error running filter: %v", err.Error()),
Error: true,
})
return
}
runtime.EventsEmit(a.ctx, "process-text-response", ProcessTextResponse{
Output: resp,
})
}
switch {
case filter.Analyze != nil:
inBfr := strings.Builder{}
@ -114,30 +141,18 @@ func (a *App) ProcessText(req ProcessTextRequest) {
Message: msg,
})
case filter.Filter != nil:
resp, err := moslice.MapWithError(req.Input, func(span TextSpan) (TextSpan, error) {
outRes, err := filter.Filter(a.ctx, span.Text)
applyFilter(filter.Filter)
case filter.FilterWithArg != nil:
a.PromptUser(filter.FilterWithArg.Label, func(ans string) {
filter, err := filter.FilterWithArg.OnConfirm(a.ctx, ans)
if err != nil {
return TextSpan{}, err
runtime.EventsEmit(a.ctx, "set-statusbar-message", SetStatusbarMessage{
Message: fmt.Sprintf("Error running filter: %v", err.Error()),
Error: true,
})
return
}
return TextSpan{
Text: outRes.Output,
Pos: span.Pos,
Len: span.Len,
Append: outRes.Append,
}, nil
})
if err != nil {
runtime.EventsEmit(a.ctx, "set-statusbar-message", SetStatusbarMessage{
Message: fmt.Sprintf("Error running filter: %v", err.Error()),
Error: true,
})
return
}
runtime.EventsEmit(a.ctx, "process-text-response", ProcessTextResponse{
Output: resp,
applyFilter(filter)
})
}
}

View file

@ -10,6 +10,8 @@ import (
"strconv"
"strings"
"text/template"
"gopkg.in/yaml.v3"
"ucl.lmika.dev/ucl"
)
@ -24,11 +26,20 @@ type TextProcessor struct {
// Analyses the supplied text. This is used for extracting information from the text input. The result
// will be displayed in the status bar. Multiple selected regions will be returned as a single string separated by line numbers.
Analyze TextAnalyzer
// FilterWithArg requests some input from the user. If the user supplies it, it will return a text filter
// to process the input.
FilterWithArg *FilterWithArg
}
type TextFilter func(ctx context.Context, input string) (resp TextFilterResponse, err error)
type TextAnalyzer func(ctx context.Context, input string) (resp string, err error)
type FilterWithArg struct {
Label string
OnConfirm func(ctx context.Context, input string) (filter TextFilter, err error)
}
type TextFilterResponse struct {
Output string
Append bool
@ -165,6 +176,45 @@ var TextFilters = map[string]TextProcessor{
},
},
"template-each-line": {
Label: "Lines: Go Template…",
Description: "Evaluates the input as a Go template and replaces each line with the result.",
FilterWithArg: &FilterWithArg{
Label: "Template",
OnConfirm: func(ctx context.Context, prompt string) (filter TextFilter, err error) {
tmpl, err := template.New("").Parse(prompt)
if err != nil {
return nil, err
}
return func(ctx context.Context, input string) (resp TextFilterResponse, err error) {
var (
dst bytes.Buffer
dstLine bytes.Buffer
)
scnr := bufio.NewScanner(strings.NewReader(input))
isFirst := true
for scnr.Scan() {
if isFirst {
isFirst = false
} else {
dst.WriteString("\n")
}
dstLine.Reset()
line := scnr.Text()
if err := tmpl.Execute(&dstLine, line); err != nil {
return TextFilterResponse{}, err
}
dst.WriteString(dstLine.String())
}
return TextFilterResponse{Output: dst.String()}, nil
}, nil
},
},
},
"ucl-evaluate": {
Label: "UCL: Evaluate",
Description: "Evaluates the input as a UCL expression and displays the result in the status bar.",