From 3296597158e19e23d3940e2ca36fb8236c04cf35 Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Fri, 19 Feb 2021 17:46:47 +0000 Subject: [PATCH] Streamline JXA. --- file_darwin.go | 38 +++++----- internal/zenutil/osa_generated.go | 97 +++++-------------------- internal/zenutil/osa_generator.go | 69 ++++++++++++------ internal/zenutil/osascripts/color.gojs | 7 +- internal/zenutil/osascripts/file.gojs | 23 +----- internal/zenutil/osascripts/msg.gojs | 29 +------- internal/zenutil/osascripts/notify.gojs | 11 +-- internal/zenutil/run_darwin.go | 58 ++++++++++----- msg_darwin.go | 53 +++++++------- notify_darwin.go | 11 +-- 10 files changed, 160 insertions(+), 236 deletions(-) diff --git a/file_darwin.go b/file_darwin.go index 5862a95..999d9f6 100644 --- a/file_darwin.go +++ b/file_darwin.go @@ -10,17 +10,17 @@ import ( func selectFile(options []Option) (string, error) { opts := applyOptions(options) - data := zenutil.File{ - Prompt: opts.title, - Invisibles: opts.showHidden, - } + var data zenutil.File + data.Options.Prompt = opts.title + data.Options.Invisibles = opts.showHidden + data.Options.Location, _ = splitDirAndName(opts.filename) + if opts.directory { data.Operation = "chooseFolder" } else { data.Operation = "chooseFile" - data.Type = initFilters(opts.fileFilters) + data.Options.Type = initFilters(opts.fileFilters) } - data.Location, _ = splitDirAndName(opts.filename) out, err := zenutil.Run(opts.ctx, "file", data) if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 { @@ -38,19 +38,19 @@ func selectFile(options []Option) (string, error) { func selectFileMutiple(options []Option) ([]string, error) { opts := applyOptions(options) - data := zenutil.File{ - Prompt: opts.title, - Invisibles: opts.showHidden, - Separator: zenutil.Separator, - Multiple: true, - } + var data zenutil.File + data.Options.Prompt = opts.title + data.Options.Invisibles = opts.showHidden + data.Options.Location, _ = splitDirAndName(opts.filename) + data.Options.Multiple = true + data.Separator = zenutil.Separator + if opts.directory { data.Operation = "chooseFolder" } else { data.Operation = "chooseFile" - data.Type = initFilters(opts.fileFilters) + data.Options.Type = initFilters(opts.fileFilters) } - data.Location, _ = splitDirAndName(opts.filename) out, err := zenutil.Run(opts.ctx, "file", data) if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 { @@ -71,16 +71,16 @@ func selectFileMutiple(options []Option) ([]string, error) { func selectFileSave(options []Option) (string, error) { opts := applyOptions(options) - data := zenutil.File{ - Prompt: opts.title, - Invisibles: opts.showHidden, - } + var data zenutil.File + data.Options.Prompt = opts.title + data.Options.Invisibles = opts.showHidden + data.Options.Location, data.Options.Name = splitDirAndName(opts.filename) + if opts.directory { data.Operation = "chooseFolder" } else { data.Operation = "chooseFileName" } - data.Location, data.Name = splitDirAndName(opts.filename) out, err := zenutil.Run(opts.ctx, "file", data) if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 { diff --git a/internal/zenutil/osa_generated.go b/internal/zenutil/osa_generated.go index 4e83046..b148e1e 100644 --- a/internal/zenutil/osa_generated.go +++ b/internal/zenutil/osa_generated.go @@ -11,93 +11,30 @@ var scripts = template.Must(template.New("").Funcs(template.FuncMap{"json": func return string(b), err }}).Parse(` {{define "color" -}} -var app = Application.currentApplication() -app.includeStandardAdditions = true +var app=Application.currentApplication() +app.includeStandardAdditions=true app.activate() -var opts = {} -opts.defaultColor = {{json .}} -var res = app.chooseColor(opts) -'rgb(' + res.map(x => Math.round(x * 255)) + ')' +var res=app.chooseColor({defaultColor:{{json .}}}) +{"rgb("+res.map(x=>Math.round(x*255))+")"} {{- end}} {{define "file" -}} -var app = Application.currentApplication() -app.includeStandardAdditions = true +var app=Application.currentApplication() +app.includeStandardAdditions=true app.activate() -var opts = {} -{{if .Prompt -}} -opts.withPrompt = {{json .Prompt}} -{{end -}} -{{if .Type -}} -opts.ofType = {{json .Type}} -{{end -}} -{{if .Name -}} -opts.defaultName = {{json .Name}} -{{end -}} -{{if .Location -}} -opts.defaultLocation = {{json .Location}} -{{end -}} -{{if .Invisibles -}} -opts.invisibles = {{json .Invisibles}} -{{end -}} -{{if .Multiple -}} -opts.multipleSelectionsAllowed = {{json .Multiple}} -{{end -}} -var res = app[{{json .Operation}}](opts) -if (Array.isArray(res)) { -res.join({{json .Separator}}) -} else { -res.toString() -} +var res=app[{{json .Operation}}]({{json .Options}}) +if(Array.isArray(res)){res.join({{json .Separator}})}else{res.toString()} {{- end}} {{define "msg" -}} -var app = Application.currentApplication() -app.includeStandardAdditions = true +var app=Application.currentApplication() +app.includeStandardAdditions=true app.activate() -var opts = {} -{{if .Message -}} -opts.message = {{json .Message}} -{{end -}} -{{if .As -}} -opts.as = {{json .As}} -{{end -}} -{{if .Title -}} -opts.withTitle = {{json .Title}} -{{end -}} -{{if .Icon -}} -opts.withIcon = {{json .Icon}} -{{end -}} -{{if .Buttons -}} -opts.buttons = {{json .Buttons}} -{{end -}} -{{if .Cancel -}} -opts.cancelButton = {{json .Cancel}} -{{end -}} -{{if .Default -}} -opts.defaultButton = {{json .Default}} -{{end -}} -{{if .Timeout -}} -opts.givingUpAfter = {{json .Timeout}} -{{end -}} -var res = app[{{json .Operation}}]({{json .Text}}, opts) -if (res.gaveUp) { -ObjC.import("stdlib") -$.exit(5) -} -if (res.buttonReturned === {{json .Extra}}) { -res -} else { -void 0 -} +var res=app[{{json .Operation}}]({{json .Text}},{{json .Options}}) +if(res.gaveUp){ObjC.import("stdlib") +$.exit(5)} +if(res.buttonReturned==={{json .Extra}}){res}else{void 0} {{- end}} {{define "notify" -}} -var app = Application.currentApplication() -app.includeStandardAdditions = true -var opts = {} -{{if .Title -}} -opts.withTitle = {{json .Title}} -{{end -}} -{{if .Subtitle -}} -opts.subtitle = {{json .Subtitle}} -{{end -}} -void app.displayNotification({{json .Text}}, opts) +var app=Application.currentApplication() +app.includeStandardAdditions=true +void app.displayNotification({{json .Text}},{{json .Options}}) {{- end}}`)) diff --git a/internal/zenutil/osa_generator.go b/internal/zenutil/osa_generator.go index 39a0c78..4245bd2 100644 --- a/internal/zenutil/osa_generator.go +++ b/internal/zenutil/osa_generator.go @@ -3,13 +3,15 @@ package main import ( - "bufio" + "bytes" "io/ioutil" "log" "os" "path/filepath" "strings" "text/template" + + "github.com/dchest/jsmin" ) func main() { @@ -29,27 +31,17 @@ func main() { str.WriteString(strings.TrimSuffix(name, filepath.Ext(name))) str.WriteString(`" -}}` + "\n") - func() { - in, err := os.Open(filepath.Join(dir, name)) - if err != nil { - log.Fatal(err) - } - defer in.Close() + data, err := ioutil.ReadFile(filepath.Join(dir, name)) + if err != nil { + log.Fatal(err) + } + data, err = minify(data) + if err != nil { + log.Fatal(err) + } - scanner := bufio.NewScanner(in) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if line != "" { - str.WriteString(line) - str.WriteRune('\n') - } - } - if err := scanner.Err(); err != nil { - log.Fatal(err) - } - }() - - str.WriteString("{{- end}}") + str.Write(data) + str.WriteString("\n{{- end}}") } out, err := os.Create("osa_generated.go") @@ -68,6 +60,41 @@ func main() { } } +func minify(data []byte) ([]byte, error) { + var templates [][]byte + var buf []byte + + for { + i := bytes.Index(data, []byte("{{")) + if i < 0 { + break + } + j := bytes.Index(data[i+len("{{"):], []byte("}}")) + if j < 0 { + break + } + templates = append(templates, data[i:i+j+len("{{}}")]) + buf = append(buf, data[:i]...) + buf = append(buf, []byte("TEMPLATE")...) + data = data[i+j+len("{{}}"):] + } + buf = append(buf, data...) + + buf, err := jsmin.Minify(buf) + if err != nil { + return nil, err + } + + var res []byte + for _, t := range templates { + i := bytes.Index(buf, []byte("TEMPLATE")) + res = append(res, buf[:i]...) + res = append(res, t...) + buf = buf[i+len("TEMPLATE"):] + } + return append(res, buf...), nil +} + var generator = template.Must(template.New("").Parse(`// Code generated by zenity; DO NOT EDIT. // +build darwin diff --git a/internal/zenutil/osascripts/color.gojs b/internal/zenutil/osascripts/color.gojs index d9ea9fd..ea0754c 100644 --- a/internal/zenutil/osascripts/color.gojs +++ b/internal/zenutil/osascripts/color.gojs @@ -2,8 +2,5 @@ var app = Application.currentApplication() app.includeStandardAdditions = true app.activate() -var opts = {} -opts.defaultColor = {{json .}} - -var res = app.chooseColor(opts) -'rgb(' + res.map(x => Math.round(x * 255)) + ')' \ No newline at end of file +var res = app.chooseColor({defaultColor: {{json .}}}) +{"rgb(" + res.map(x => Math.round(x * 255)) + ")"} \ No newline at end of file diff --git a/internal/zenutil/osascripts/file.gojs b/internal/zenutil/osascripts/file.gojs index 1d974d3..8d32db0 100644 --- a/internal/zenutil/osascripts/file.gojs +++ b/internal/zenutil/osascripts/file.gojs @@ -2,28 +2,7 @@ var app = Application.currentApplication() app.includeStandardAdditions = true app.activate() -var opts = {} - -{{if .Prompt -}} - opts.withPrompt = {{json .Prompt}} -{{end -}} -{{if .Type -}} - opts.ofType = {{json .Type}} -{{end -}} -{{if .Name -}} - opts.defaultName = {{json .Name}} -{{end -}} -{{if .Location -}} - opts.defaultLocation = {{json .Location}} -{{end -}} -{{if .Invisibles -}} - opts.invisibles = {{json .Invisibles}} -{{end -}} -{{if .Multiple -}} - opts.multipleSelectionsAllowed = {{json .Multiple}} -{{end -}} - -var res = app[{{json .Operation}}](opts) +var res = app[{{json .Operation}}]({{json .Options}}) if (Array.isArray(res)) { res.join({{json .Separator}}) } else { diff --git a/internal/zenutil/osascripts/msg.gojs b/internal/zenutil/osascripts/msg.gojs index a036289..347aea1 100644 --- a/internal/zenutil/osascripts/msg.gojs +++ b/internal/zenutil/osascripts/msg.gojs @@ -2,34 +2,7 @@ var app = Application.currentApplication() app.includeStandardAdditions = true app.activate() -var opts = {} - -{{if .Message -}} - opts.message = {{json .Message}} -{{end -}} -{{if .As -}} - opts.as = {{json .As}} -{{end -}} -{{if .Title -}} - opts.withTitle = {{json .Title}} -{{end -}} -{{if .Icon -}} - opts.withIcon = {{json .Icon}} -{{end -}} -{{if .Buttons -}} - opts.buttons = {{json .Buttons}} -{{end -}} -{{if .Cancel -}} - opts.cancelButton = {{json .Cancel}} -{{end -}} -{{if .Default -}} - opts.defaultButton = {{json .Default}} -{{end -}} -{{if .Timeout -}} - opts.givingUpAfter = {{json .Timeout}} -{{end -}} - -var res = app[{{json .Operation}}]({{json .Text}}, opts) +var res = app[{{json .Operation}}]({{json .Text}}, {{json .Options}}) if (res.gaveUp) { ObjC.import("stdlib") $.exit(5) diff --git a/internal/zenutil/osascripts/notify.gojs b/internal/zenutil/osascripts/notify.gojs index 4bddb25..6ac1678 100644 --- a/internal/zenutil/osascripts/notify.gojs +++ b/internal/zenutil/osascripts/notify.gojs @@ -1,13 +1,4 @@ var app = Application.currentApplication() app.includeStandardAdditions = true -var opts = {} - -{{if .Title -}} - opts.withTitle = {{json .Title}} -{{end -}} -{{if .Subtitle -}} - opts.subtitle = {{json .Subtitle}} -{{end -}} - -void app.displayNotification({{json .Text}}, opts) \ No newline at end of file +void app.displayNotification({{json .Text}}, {{json .Options}}) \ No newline at end of file diff --git a/internal/zenutil/run_darwin.go b/internal/zenutil/run_darwin.go index ac01172..4fbdd0d 100644 --- a/internal/zenutil/run_darwin.go +++ b/internal/zenutil/run_darwin.go @@ -40,33 +40,51 @@ func Run(ctx context.Context, script string, data interface{}) ([]byte, error) { return cmd.Output() } +// File is internal. type File struct { - Operation string - Prompt string - Name string - Location string - Separator string - Type []string - Invisibles bool - Multiple bool + Operation string + Separator string + Options FileOptions } +// FileOptions is internal. +type FileOptions struct { + Prompt string `json:"withPrompt,omitempty"` + Type []string `json:"ofType,omitempty"` + Name string `json:"defaultName,omitempty"` + Location string `json:"defaultLocation,omitempty"` + Multiple bool `json:"multipleSelectionsAllowed,omitempty"` + Invisibles bool `json:"invisibles,omitempty"` +} + +// Msg is internal. type Msg struct { Operation string Text string - Message string - As string - Title string - Icon string Extra string - Buttons []string - Cancel int - Default int - Timeout int + Options MsgOptions } -type Notify struct { - Text string - Title string - Subtitle string +// MsgOptions is internal. +type MsgOptions struct { + Message string `json:"message,omitempty"` + As string `json:"as,omitempty"` + Title string `json:"withTitle,omitempty"` + Icon string `json:"withIcon,omitempty"` + Buttons []string `json:"buttons,omitempty"` + Cancel int `json:"cancelButton,omitempty"` + Default int `json:"defaultButton,omitempty"` + Timeout int `json:"givingUpAfter,omitempty"` +} + +// Notify is internal. +type Notify struct { + Text string + Options NotifyOptions +} + +// NotifyOptions is internal. +type NotifyOptions struct { + Title string `json:"withTitle,omitempty"` + Subtitle string `json:"subtitle,omitempty"` } diff --git a/msg_darwin.go b/msg_darwin.go index 16bc0ac..845846c 100644 --- a/msg_darwin.go +++ b/msg_darwin.go @@ -8,38 +8,39 @@ import ( func message(kind messageKind, text string, options []Option) (bool, error) { opts := applyOptions(options) - data := zenutil.Msg{ - Text: text, - Timeout: zenutil.Timeout, - } + + var data zenutil.Msg + data.Text = text + data.Options.Timeout = zenutil.Timeout + dialog := kind == questionKind || opts.icon != 0 if dialog { data.Operation = "displayDialog" - data.Title = opts.title + data.Options.Title = opts.title switch opts.icon { case ErrorIcon: - data.Icon = "stop" + data.Options.Icon = "stop" case WarningIcon: - data.Icon = "caution" + data.Options.Icon = "caution" case InfoIcon, QuestionIcon: - data.Icon = "note" + data.Options.Icon = "note" } } else { data.Operation = "displayAlert" if opts.title != "" { - data.Message = text + data.Options.Message = text data.Text = opts.title } switch kind { case infoKind: - data.As = "informational" + data.Options.As = "informational" case warningKind: - data.As = "warning" + data.Options.As = "warning" case errorKind: - data.As = "critical" + data.Options.As = "critical" } } @@ -58,31 +59,31 @@ func message(kind messageKind, text string, options []Option) (bool, error) { } if kind == questionKind { if opts.extraButton == "" { - data.Buttons = []string{opts.cancelLabel, opts.okLabel} - data.Default = 2 - data.Cancel = 1 + data.Options.Buttons = []string{opts.cancelLabel, opts.okLabel} + data.Options.Default = 2 + data.Options.Cancel = 1 } else { - data.Buttons = []string{opts.extraButton, opts.cancelLabel, opts.okLabel} - data.Default = 3 - data.Cancel = 2 + data.Options.Buttons = []string{opts.extraButton, opts.cancelLabel, opts.okLabel} + data.Options.Default = 3 + data.Options.Cancel = 2 } } else { if opts.extraButton == "" { - data.Buttons = []string{opts.okLabel} - data.Default = 1 + data.Options.Buttons = []string{opts.okLabel} + data.Options.Default = 1 } else { - data.Buttons = []string{opts.extraButton, opts.okLabel} - data.Default = 2 + data.Options.Buttons = []string{opts.extraButton, opts.okLabel} + data.Options.Default = 2 } } data.Extra = opts.extraButton } if opts.defaultCancel { - if data.Cancel != 0 { - data.Default = data.Cancel + if data.Options.Cancel != 0 { + data.Options.Default = data.Options.Cancel } - if dialog && data.Buttons == nil { - data.Default = 1 + if dialog && data.Options.Buttons == nil { + data.Options.Default = 1 } } diff --git a/notify_darwin.go b/notify_darwin.go index 8aa9c9b..268fdbc 100644 --- a/notify_darwin.go +++ b/notify_darwin.go @@ -8,12 +8,13 @@ import ( func notify(text string, options []Option) error { opts := applyOptions(options) - data := zenutil.Notify{ - Text: text, - Title: opts.title, - } + + var data zenutil.Notify + data.Text = text + data.Options.Title = opts.title + if i := strings.IndexByte(text, '\n'); i >= 0 && i < len(text) { - data.Subtitle = text[:i] + data.Options.Subtitle = text[:i] data.Text = text[i+1:] } _, err := zenutil.Run(opts.ctx, "notify", data)