Added map-lines and upgraded UCL
All checks were successful
Release Build / build (push) Successful in 1m52s

This commit is contained in:
Leon Mika 2026-09-08 22:03:41 +10:00
parent 18604ec5a6
commit add62fbfa0
7 changed files with 63 additions and 5 deletions

1
.idea/dequoter.iml generated
View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4"> <module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" /> <component name="Go" enabled="true" />
<component name="GoModuleSettings" enabled="true" />
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" /> <content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />

2
app.go
View file

@ -32,6 +32,7 @@ type App struct {
func newUCLInst(plugins *PluginFilters) *ucl.Inst { func newUCLInst(plugins *PluginFilters) *ucl.Inst {
return ucl.New( return ucl.New(
ucl.WithModule(plugins.Module()), ucl.WithModule(plugins.Module()),
ucl.WithModule(builtins.Bytes()),
ucl.WithModule(builtins.CSV(nil)), ucl.WithModule(builtins.CSV(nil)),
ucl.WithModule(builtins.Fns()), ucl.WithModule(builtins.Fns()),
ucl.WithModule(builtins.FS(nil)), ucl.WithModule(builtins.FS(nil)),
@ -41,6 +42,7 @@ func newUCLInst(plugins *PluginFilters) *ucl.Inst {
ucl.WithModule(builtins.OS()), ucl.WithModule(builtins.OS()),
ucl.WithModule(builtins.Strs()), ucl.WithModule(builtins.Strs()),
ucl.WithModule(builtins.Time()), ucl.WithModule(builtins.Time()),
ucl.WithModule(builtins.URLs()),
) )
} }

View file

@ -10,6 +10,8 @@ export function ProcessText(arg1:main.ProcessTextRequest):Promise<void>;
export function PromptUser(arg1:string,arg2:any):Promise<void>; export function PromptUser(arg1:string,arg2:any):Promise<void>;
export function ReloadPlugins():Promise<void>;
export function SaveCurrentBuffer(arg1:string):Promise<void>; export function SaveCurrentBuffer(arg1:string):Promise<void>;
export function TriggerTextProcess(arg1:string):Promise<void>; export function TriggerTextProcess(arg1:string):Promise<void>;

View file

@ -18,6 +18,10 @@ export function PromptUser(arg1, arg2) {
return window['go']['main']['App']['PromptUser'](arg1, arg2); return window['go']['main']['App']['PromptUser'](arg1, arg2);
} }
export function ReloadPlugins() {
return window['go']['main']['App']['ReloadPlugins']();
}
export function SaveCurrentBuffer(arg1) { export function SaveCurrentBuffer(arg1) {
return window['go']['main']['App']['SaveCurrentBuffer'](arg1); return window['go']['main']['App']['SaveCurrentBuffer'](arg1);
} }

2
go.mod
View file

@ -9,7 +9,7 @@ require (
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
lmika.dev/pkg/modash v0.1.0 lmika.dev/pkg/modash v0.1.0
lmika.dev/pkg/progdoc v0.0.0-20260207235039-984257fb414b lmika.dev/pkg/progdoc v0.0.0-20260207235039-984257fb414b
ucl.lmika.dev v0.1.3 ucl.lmika.dev v0.1.7
) )
require ( require (

6
go.sum
View file

@ -796,5 +796,7 @@ lmika.dev/pkg/modash v0.1.0/go.mod h1:8NDl/yR1eCCEhip9FJlVuMNXIeaztQ0Ks/tizExFcT
lmika.dev/pkg/progdoc v0.0.0-20260207235039-984257fb414b h1:uarBEkpjAnpzO98btsA6ZDw9oGnJX8zSb8gZnCFl+6Y= lmika.dev/pkg/progdoc v0.0.0-20260207235039-984257fb414b h1:uarBEkpjAnpzO98btsA6ZDw9oGnJX8zSb8gZnCFl+6Y=
lmika.dev/pkg/progdoc v0.0.0-20260207235039-984257fb414b/go.mod h1:GefQ+wxW6L0p2TfB4fzoP7ihOgEt5Lb/1qgXhruVHos= lmika.dev/pkg/progdoc v0.0.0-20260207235039-984257fb414b/go.mod h1:GefQ+wxW6L0p2TfB4fzoP7ihOgEt5Lb/1qgXhruVHos=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
ucl.lmika.dev v0.1.3 h1:Y2m+ORnLMA8boQmkXpW41VbkR3bwmnZjDLGVTYbZQic= ucl.lmika.dev v0.1.6 h1:cZocpR/IQcy9nvE8u+SSLY7/PE9fd1HIVWhZr/m+U5M=
ucl.lmika.dev v0.1.3/go.mod h1:Hjl6Udph2yuOPcBSytz4SFJVt5MZbM5JyiSAyTMTbNU= ucl.lmika.dev v0.1.6/go.mod h1:Hjl6Udph2yuOPcBSytz4SFJVt5MZbM5JyiSAyTMTbNU=
ucl.lmika.dev v0.1.7 h1:3yfvWOhBnWpQIm4NhKrUBh5PajB1wzUWzoPPa8ltaVo=
ucl.lmika.dev v0.1.7/go.mod h1:Hjl6Udph2yuOPcBSytz4SFJVt5MZbM5JyiSAyTMTbNU=

View file

@ -1,6 +1,8 @@
package main package main
import ( import (
"bufio"
"bytes"
"context" "context"
"errors" "errors"
"fmt" "fmt"
@ -18,7 +20,6 @@ const pluginKeyPrefix = "plugin:"
// PluginFilters is the registry of text filters defined by UCL plugin files. // PluginFilters is the registry of text filters defined by UCL plugin files.
type PluginFilters struct { type PluginFilters struct {
inst *ucl.Inst
filters map[string]TextProcessor filters map[string]TextProcessor
errors []error errors []error
} }
@ -34,7 +35,8 @@ func (p *PluginFilters) Module() ucl.Module {
return ucl.Module{ return ucl.Module{
Name: "d", Name: "d",
Builtins: map[string]ucl.BuiltinHandler{ Builtins: map[string]ucl.BuiltinHandler{
"filter": p.filterBuiltin, "filter": p.filterBuiltin,
"map-lines": p.mapLinesBuiltin,
}, },
} }
} }
@ -78,6 +80,51 @@ func (p *PluginFilters) filterBuiltin(ctx context.Context, args ucl.CallArgs) (a
return nil, nil return nil, nil
} }
// mapLinesBuiltin implements `d:map-lines INPUT PROC` which applies a transform for each line of the input.
func (p *PluginFilters) mapLinesBuiltin(ctx context.Context, args ucl.CallArgs) (any, error) {
var (
input string
proc ucl.Invokable
)
if err := args.Bind(&input, &proc); err != nil {
return nil, fmt.Errorf("d:map-lines: expected INPUT and PROC: %w", err)
}
var (
dst bytes.Buffer
dstLine bytes.Buffer
)
scnr := bufio.NewScanner(strings.NewReader(input))
isFirst := true
for scnr.Scan() {
dstLine.Reset()
line := scnr.Text()
out, err := proc.Invoke(ctx, line)
if err != nil {
return TextFilterResponse{}, err
} else if out == nil {
continue
} else if strOut, ok := out.(fmt.Stringer); ok {
dstLine.WriteString(strOut.String())
} else {
dstLine.WriteString(fmt.Sprint(out))
}
if isFirst {
isFirst = false
} else {
dst.WriteString("\n")
}
dst.WriteString(dstLine.String())
}
return dst.String(), nil
}
// LoadDir evaluates every *.ucl file found under dir (recursively, in lexical order). Files // LoadDir evaluates every *.ucl file found under dir (recursively, in lexical order). Files
// that fail to load are recorded in Errors() and skipped; loading continues with the rest. // that fail to load are recorded in Errors() and skipped; loading continues with the rest.
// A missing directory is not an error. // A missing directory is not an error.