From 6108e4d61405143e2b9071c0a9672218273759fb Mon Sep 17 00:00:00 2001 From: micah Date: Sat, 28 Mar 2026 19:27:32 +0800 Subject: [PATCH] feat: init --- .gitignore | 2 + Makefile | 20 ++++++ README.md | 24 +++++++ command/code/decode.go | 31 +++++++++ command/code/encode.go | 28 ++++++++ command/command.go | 24 +++++++ command/datex/date.go | 69 ++++++++++++++++++ command/gourl/gourl.go | 120 ++++++++++++++++++++++++++++++++ command/help/help.go | 22 ++++++ dist/Command Hub.alfredworkflow | Bin 0 -> 11261 bytes go.mod | 17 +++++ go.sum | 46 ++++++++++++ main.go | 9 +++ model/model.go | 22 ++++++ pkg/logx/log.go | 10 +++ pkg/stringx/string.go | 5 ++ workflow/workflow.go | 98 ++++++++++++++++++++++++++ 17 files changed, 547 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 command/code/decode.go create mode 100644 command/code/encode.go create mode 100644 command/command.go create mode 100644 command/datex/date.go create mode 100644 command/gourl/gourl.go create mode 100644 command/help/help.go create mode 100644 dist/Command Hub.alfredworkflow create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 model/model.go create mode 100644 pkg/logx/log.go create mode 100644 pkg/stringx/string.go create mode 100644 workflow/workflow.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..015bc30 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +alfred-micah-workflow \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4e714f2 --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +export CGO_CXXFLAGS_ALLOW:=.* +export CGO_LDFLAGS_ALLOW:=.* +export CGO_CFLAGS_ALLOW:=.* +# 跨平台开发,设置交叉编译 +#export GOOS=linux +#export GOARCH=amd64 + +app:="alfred-micah-workflow" + +.PHONY: all test clean + +all: build + +build: + @echo "\033[32m <============== making app ${app} =============> \033[0m" + go build -ldflags='-w -s' $(FLAGS) -o ./${app} ./ +clean: + @echo -e "\033[32m ============== cleaning files =============> \033[0m" + rm -fv ${TARGET} + diff --git a/README.md b/README.md new file mode 100644 index 0000000..92ca164 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# Alfred Workflow +## 打包 +```shell +make +``` + +## 测试 +```markdown +* 打开 Alfred → 点击左侧「Workflows」→ 右下角「+」→ 新建一个空白 Workflow; +* 给 Workflow 命名(比如「Command Hub」),设置标识符(唯一即可); +* 添加「Trigger」(触发方式): + 右侧点击 ---> Inputs ---> Script Filter; + 设置关键词(比如 m),勾选「with space」(输入关键词后按空格输入参数); + 添加「Run Script」(执行脚本):/Users/xxx/xxx/alfred-micah-workflow $1 $2 $3 $4 $5 $6 $7 $8 + +从 Trigger 拖出连线,选择 Actions → Run Script; +「Language」选择「/bin/bash」; +脚本内容填写:/path/to/your/alfred-micah-workflow "$1" "$2"(替换为你编译后的可执行文件绝对路径,$1 是 Alfred 传入的输入参数); +勾选「with input as argv」; +(可选)添加「Copy to Clipboard」(选中后复制): +从 Run Script 拖出连线,选择 Actions → Copy to Clipboard; +「Clipboard」选择「Argv」(即我们代码中 Arg(url) 传递的参数); +保存后,在 Alfred 输入 gtest go,就能看到匹配的结果,选中后会自动复制对应的 URL 到剪贴板。 +``` diff --git a/command/code/decode.go b/command/code/decode.go new file mode 100644 index 0000000..4af54e3 --- /dev/null +++ b/command/code/decode.go @@ -0,0 +1,31 @@ +package code + +import ( + "encoding/base64" + + aw "github.com/deanishe/awgo" + + "gitea.micah.wiki/pandora/alfred/model" + "gitea.micah.wiki/pandora/alfred/pkg/stringx" +) + +func DecodeDo(args []string) []*model.Item { + if len(args) == 0 { + return nil + } + value := args[0] + bytes, err := base64.RawURLEncoding.DecodeString(value) + if err != nil { + return nil + } + val := string(bytes) + items := make([]*model.Item, 0) + items = append(items, &model.Item{ + Title: val, + Subtitle: stringx.NewStrPoint("URL Decode"), + Icon: aw.IconInfo, + Arg: []string{"copytext", val}, + Valid: true, + }) + return items +} diff --git a/command/code/encode.go b/command/code/encode.go new file mode 100644 index 0000000..610d9f9 --- /dev/null +++ b/command/code/encode.go @@ -0,0 +1,28 @@ +package code + +import ( + "encoding/base64" + + aw "github.com/deanishe/awgo" + + "gitea.micah.wiki/pandora/alfred/model" + "gitea.micah.wiki/pandora/alfred/pkg/stringx" +) + +func EncodeDo(args []string) []*model.Item { + if len(args) == 0 { + return nil + } + encodeStr := args[0] + val := base64.RawURLEncoding.EncodeToString([]byte(encodeStr)) + + items := make([]*model.Item, 0) + items = append(items, &model.Item{ + Title: val, + Subtitle: stringx.NewStrPoint("URL Encode"), + Icon: aw.IconInfo, + Arg: []string{"copytext", val}, + Valid: true, + }) + return items +} diff --git a/command/command.go b/command/command.go new file mode 100644 index 0000000..ffb1ac9 --- /dev/null +++ b/command/command.go @@ -0,0 +1,24 @@ +package command + +import ( + "gitea.micah.wiki/pandora/alfred/command/code" + "gitea.micah.wiki/pandora/alfred/command/datex" + "gitea.micah.wiki/pandora/alfred/command/gourl" + "gitea.micah.wiki/pandora/alfred/command/help" + "gitea.micah.wiki/pandora/alfred/model" +) + +func Do(command string, args []string) []*model.Item { + switch command { + case "date": + return datex.Do(args) + case "url", "go": + return gourl.Do(args) + case "encode": + return code.EncodeDo(args) + case "decode": + return code.DecodeDo(args) + default: + return help.Do(args) + } +} diff --git a/command/datex/date.go b/command/datex/date.go new file mode 100644 index 0000000..66401ee --- /dev/null +++ b/command/datex/date.go @@ -0,0 +1,69 @@ +package datex + +import ( + "fmt" + "regexp" + "strconv" + "strings" + "time" + + aw "github.com/deanishe/awgo" + + "gitea.micah.wiki/pandora/alfred/model" + "gitea.micah.wiki/pandora/alfred/pkg/stringx" +) + +var ( + regexpTimestamp = regexp.MustCompile(`^[1-9]{1}\d+$`) + yyyyMMddHHMMSSLayout = "2006-01-02 15:04:05" + moreLayouts = []string{ + "2006-01-02", + "2006-01-02 15:04", + "2006-01-02 15:04:05", + } +) + +func Do(args []string) []*model.Item { + if len(args) == 0 { + return nil + } + // 处理 now + input := strings.Join(args, " ") + if input == "now" || input == "" { + input = fmt.Sprintf("%d", time.Now().Unix()) + } + items := make([]*model.Item, 0) + if regexpTimestamp.MatchString(input) { + v, err := strconv.ParseInt(input, 10, 32) + if err != nil { + return nil + } + value := time.Unix(v, 0).Format(yyyyMMddHHMMSSLayout) + items = append(items, &model.Item{ + Title: value, + Subtitle: stringx.NewStrPoint(yyyyMMddHHMMSSLayout), + Arg: []string{"copytext", value}, + Valid: true, + Icon: aw.IconClock, + }) + } else { + for _, layout := range moreLayouts { + v, err := time.Parse(layout, input) + if err != nil { + continue + } + value := fmt.Sprintf("%d", v.Unix()) + items = append(items, &model.Item{ + Title: value, + Subtitle: stringx.NewStrPoint(layout), + Arg: []string{"copytext", value}, + Valid: true, + Icon: aw.IconClock, + }) + } + } + if len(items) == 0 { + return nil + } + return items +} diff --git a/command/gourl/gourl.go b/command/gourl/gourl.go new file mode 100644 index 0000000..be629bd --- /dev/null +++ b/command/gourl/gourl.go @@ -0,0 +1,120 @@ +package gourl + +import ( + "fmt" + "os" + + aw "github.com/deanishe/awgo" + "gopkg.in/yaml.v3" + + "gitea.micah.wiki/pandora/alfred/model" + "gitea.micah.wiki/pandora/alfred/pkg/logx" + "gitea.micah.wiki/pandora/alfred/pkg/stringx" +) + +func getDefault() map[string][]*URLInfo { + return map[string][]*URLInfo{ + "github": {{ + Key: "github", + Title: "Github", + URL: "https://github.com/", + }}, + "doubao": {{ + Key: "doubao", + Title: "豆包", + URL: "https://www.doubao.com/chat", + }}, + } +} + +func Do(args []string) []*model.Item { + if len(args) == 0 { + return nil + } + logx.Info("gourl: %s", args[0]) + urlMap := GetConfig() + if len(urlMap) == 0 { + logx.Info("配置文件未找到") + urlMap = getDefault() + } + if urls, ok := urlMap[args[0]]; ok { + logx.Info("go value: %+v", urls) + items := make([]*model.Item, 0) + if len(urls) > 0 { + for _, v := range urls { + items = append(items, &model.Item{ + Title: fmt.Sprintf("回车 → 在浏览器打开 %s", v.Title), + Subtitle: stringx.NewStrPoint(v.URL), + UID: stringx.NewStrPoint("gourl-open-url"), + Arg: []string{"goto", v.URL}, + Valid: true, + Icon: aw.IconNetwork, + }) + } + } + return items + } + gotoConfigFile := os.Getenv("goto_config") + return []*model.Item{ + { + Title: fmt.Sprintf("未找到 %s 相关跳转url配置", args[0]), + Subtitle: stringx.NewStrPoint(fmt.Sprintf("配置地址: %s", gotoConfigFile)), + UID: stringx.NewStrPoint("gourl-open-url"), + Arg: []string{"copytext", gotoConfigFile}, + Valid: true, + Icon: aw.IconNetwork, + }, + } +} + +type URLInfo struct { + Key string `yaml:"key"` + Title string `yaml:"title"` + URL string `yaml:"url"` +} +type Config struct { + GoToConfig map[string][]*URLInfo `yaml:"goto_config"` +} + +func GetConfig() map[string][]*URLInfo { + logx.Info("GetConfig start.") + cfgFile := os.Getenv("goto_config") + if cfgFile == "" { + logx.Info("读取配置文件为空") + return getDefault() + } + logx.Info(cfgFile) + // 读取配置文件内容 + data, err := os.ReadFile(cfgFile) + if err != nil { + logx.Info("读取配置文件失败: %v", err) + return getDefault() + } + // 解析 YAML 到结构体 + var cfg Config + if err = yaml.Unmarshal(data, &cfg); err != nil { + logx.Info("解析 YAML 失败: %v", err) + return getDefault() + } + if len(cfg.GoToConfig) == 0 { + logx.Info("读取配置文件未找到数据") + return getDefault() + } + + c := make(map[string][]*URLInfo) + for _, list := range cfg.GoToConfig { + for _, info := range list { + for i := 1; i <= len(info.Key); i++ { + key := info.Key[:i] + v, ok := c[key] + if !ok { + v = make([]*URLInfo, 0) + } + v = append(v, info) + c[key] = v + } + } + } + logx.Info("config size: ", len(c)) + return c +} diff --git a/command/help/help.go b/command/help/help.go new file mode 100644 index 0000000..d0a7752 --- /dev/null +++ b/command/help/help.go @@ -0,0 +1,22 @@ +package help + +import ( + aw "github.com/deanishe/awgo" + + "gitea.micah.wiki/pandora/alfred/model" + "gitea.micah.wiki/pandora/alfred/pkg/stringx" +) + +func Do(_ []string) []*model.Item { + return []*model.Item{ + { + Title: "目前支持命令(goto、decode、encode、date等)", // 主提示词 + Subtitle: stringx.NewStrPoint("subtitle"), // 副提示词 + Match: stringx.NewStrPoint("match"), + UID: stringx.NewStrPoint("help-goto"), + Arg: []string{"copytext", "help"}, // alfred 输出内容 回车会在剪切板 + Valid: true, + Icon: aw.IconHelp, + }, + } +} diff --git a/dist/Command Hub.alfredworkflow b/dist/Command Hub.alfredworkflow new file mode 100644 index 0000000000000000000000000000000000000000..bfd7c7ae53d00008dd8a0b1108dccc561ed9b622 GIT binary patch literal 11261 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 literal 0 HcmV?d00001 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4d31479 --- /dev/null +++ b/go.mod @@ -0,0 +1,17 @@ +module gitea.micah.wiki/pandora/alfred + +go 1.24.0 + +toolchain go1.24.12 + +require ( + github.com/deanishe/awgo v0.29.1 + gopkg.in/yaml.v3 v3.0.1 +) + +require ( + github.com/magefile/mage v1.15.0 // indirect + go.deanishe.net/env v0.5.1 // indirect + go.deanishe.net/fuzzy v1.0.0 // indirect + golang.org/x/text v0.33.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..4a1f3ee --- /dev/null +++ b/go.sum @@ -0,0 +1,46 @@ +github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deanishe/awgo v0.29.1 h1:yKAyy0e+HR60iPxaKHhY3hdTM5GCsECpWTP79j04bHg= +github.com/deanishe/awgo v0.29.1/go.mod h1:1yGF+uQfWXX99TiDfAYYKjJpHTq5lHEmvHFEVCHo6KA= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= +github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= +github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg= +github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +go.deanishe.net/env v0.5.1 h1:WiOncK5uJj8Um57Vj2dc1bq1lMN7fgRag9up7I3LZy0= +go.deanishe.net/env v0.5.1/go.mod h1:ihEYfDm0K0hq3f5ACTCQDrMTWxH9fTiA1lh1i0aMqm0= +go.deanishe.net/fuzzy v1.0.0 h1:3Qp6PCX0DLb9z03b5OHwAGsbRSkgJpSLncsiDdXDt4Y= +go.deanishe.net/fuzzy v1.0.0/go.mod h1:2yEEMfG7jWgT1s5EO0TteVWmx2MXFBRMr5cMm84bQNY= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +howett.net/plist v0.0.0-20201203080718-1454fab16a06/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= diff --git a/main.go b/main.go new file mode 100644 index 0000000..2df4526 --- /dev/null +++ b/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "gitea.micah.wiki/pandora/alfred/workflow" +) + +func main() { + workflow.Do() +} diff --git a/model/model.go b/model/model.go new file mode 100644 index 0000000..6583da0 --- /dev/null +++ b/model/model.go @@ -0,0 +1,22 @@ +package model + +import aw "github.com/deanishe/awgo" + +type Item struct { + Title string + Subtitle *string + Match *string + UID *string + Autocomplete *string + Arg []string + Valid bool + File bool + Copytext *string + LargeType *string + QL *string + Vars map[string]string + Mods map[string]*aw.Modifier + Actions map[string][]string + Icon *aw.Icon + NoUID bool // Suppress UID in JSON +} diff --git a/pkg/logx/log.go b/pkg/logx/log.go new file mode 100644 index 0000000..8ebb733 --- /dev/null +++ b/pkg/logx/log.go @@ -0,0 +1,10 @@ +package logx + +import ( + "fmt" + "os" +) + +func Info(template string, args ...interface{}) { + _, _ = fmt.Fprintf(os.Stderr, template, args) +} diff --git a/pkg/stringx/string.go b/pkg/stringx/string.go new file mode 100644 index 0000000..9598239 --- /dev/null +++ b/pkg/stringx/string.go @@ -0,0 +1,5 @@ +package stringx + +func NewStrPoint(val string) *string { + return &val +} diff --git a/workflow/workflow.go b/workflow/workflow.go new file mode 100644 index 0000000..ada42e5 --- /dev/null +++ b/workflow/workflow.go @@ -0,0 +1,98 @@ +package workflow + +import ( + aw "github.com/deanishe/awgo" + + "gitea.micah.wiki/pandora/alfred/command" +) + +// 初始化 aw 实例,这是 awgo 库的核心对象 +var wf *aw.Workflow + +func Do() { + // 初始化 Workflow,启用日志(方便调试,日志会输出到 Alfred 的调试面板) + wf = aw.New() + // 初始化错误及校验参数 + var err error + args := wf.Args() + if len(args) <= 1 { + return + } + + // 默认返回 SendFeed + defer func() { + if err == nil { + wf.SendFeedback() + return + } + }() + + // 命令获取 + cmd := args[0] + params := make([]string, 0) + if len(args) > 1 { + params = args[1:] + } + + items := command.Do(cmd, params) + wfItems := make([]*aw.Item, len(items)) + for i, item := range items { + wfItem := &aw.Item{} + if item.Title != "" { + wfItem.Title(item.Title) + } + if item.Subtitle != nil { + wfItem.Subtitle(*item.Subtitle) + } + if item.Match != nil { + wfItem.Match(*item.Match) + } + if item.UID != nil { + wfItem.UID(*item.UID) + } + if item.Autocomplete != nil { + wfItem.Autocomplete(*item.Autocomplete) + } + if len(item.Arg) > 0 { + wfItem.Arg(item.Arg...) + } + if item.Valid { + wfItem.Valid(item.Valid) + } + if item.File { + wfItem.IsFile(item.File) + } + if item.Copytext != nil { + wfItem.Copytext(*item.Copytext) + } + if item.LargeType != nil { + wfItem.Largetype(*item.LargeType) + } + if item.QL != nil { + wfItem.Quicklook(*item.QL) + } + if len(item.Vars) > 0 { + for key, value := range item.Vars { + wfItem.Var(key, value) + } + } + if len(item.Mods) > 0 { + for _, mod := range item.Mods { + wfItem.SetModifier(mod) + } + } + if len(item.Actions) > 0 { + for t, action := range item.Actions { + wfItem.ActionForType(t, action...) + } + } + if item.Icon != nil { + wfItem.Icon(item.Icon) + } + wfItems[i] = wfItem + + } + if len(items) > 0 { + wf.Feedback.Items = wfItems + } +}