Streamline JXA.

This commit is contained in:
Nuno Cruces 2021-02-19 17:46:47 +00:00
parent 6c0e609037
commit 3296597158
10 changed files with 160 additions and 236 deletions

View file

@ -10,17 +10,17 @@ import (
func selectFile(options []Option) (string, error) { func selectFile(options []Option) (string, error) {
opts := applyOptions(options) opts := applyOptions(options)
data := zenutil.File{ var data zenutil.File
Prompt: opts.title, data.Options.Prompt = opts.title
Invisibles: opts.showHidden, data.Options.Invisibles = opts.showHidden
} data.Options.Location, _ = splitDirAndName(opts.filename)
if opts.directory { if opts.directory {
data.Operation = "chooseFolder" data.Operation = "chooseFolder"
} else { } else {
data.Operation = "chooseFile" 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) out, err := zenutil.Run(opts.ctx, "file", data)
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 { 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) { func selectFileMutiple(options []Option) ([]string, error) {
opts := applyOptions(options) opts := applyOptions(options)
data := zenutil.File{ var data zenutil.File
Prompt: opts.title, data.Options.Prompt = opts.title
Invisibles: opts.showHidden, data.Options.Invisibles = opts.showHidden
Separator: zenutil.Separator, data.Options.Location, _ = splitDirAndName(opts.filename)
Multiple: true, data.Options.Multiple = true
} data.Separator = zenutil.Separator
if opts.directory { if opts.directory {
data.Operation = "chooseFolder" data.Operation = "chooseFolder"
} else { } else {
data.Operation = "chooseFile" 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) out, err := zenutil.Run(opts.ctx, "file", data)
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 { 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) { func selectFileSave(options []Option) (string, error) {
opts := applyOptions(options) opts := applyOptions(options)
data := zenutil.File{ var data zenutil.File
Prompt: opts.title, data.Options.Prompt = opts.title
Invisibles: opts.showHidden, data.Options.Invisibles = opts.showHidden
} data.Options.Location, data.Options.Name = splitDirAndName(opts.filename)
if opts.directory { if opts.directory {
data.Operation = "chooseFolder" data.Operation = "chooseFolder"
} else { } else {
data.Operation = "chooseFileName" data.Operation = "chooseFileName"
} }
data.Location, data.Name = splitDirAndName(opts.filename)
out, err := zenutil.Run(opts.ctx, "file", data) out, err := zenutil.Run(opts.ctx, "file", data)
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 { if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 {

View file

@ -11,93 +11,30 @@ var scripts = template.Must(template.New("").Funcs(template.FuncMap{"json": func
return string(b), err return string(b), err
}}).Parse(` }}).Parse(`
{{define "color" -}} {{define "color" -}}
var app = Application.currentApplication() var app=Application.currentApplication()
app.includeStandardAdditions = true app.includeStandardAdditions=true
app.activate() app.activate()
var opts = {} var res=app.chooseColor({defaultColor:{{json .}}})
opts.defaultColor = {{json .}} {"rgb("+res.map(x=>Math.round(x*255))+")"}
var res = app.chooseColor(opts)
'rgb(' + res.map(x => Math.round(x * 255)) + ')'
{{- end}} {{- end}}
{{define "file" -}} {{define "file" -}}
var app = Application.currentApplication() var app=Application.currentApplication()
app.includeStandardAdditions = true app.includeStandardAdditions=true
app.activate() app.activate()
var opts = {} var res=app[{{json .Operation}}]({{json .Options}})
{{if .Prompt -}} if(Array.isArray(res)){res.join({{json .Separator}})}else{res.toString()}
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()
}
{{- end}} {{- end}}
{{define "msg" -}} {{define "msg" -}}
var app = Application.currentApplication() var app=Application.currentApplication()
app.includeStandardAdditions = true app.includeStandardAdditions=true
app.activate() app.activate()
var opts = {} var res=app[{{json .Operation}}]({{json .Text}},{{json .Options}})
{{if .Message -}} if(res.gaveUp){ObjC.import("stdlib")
opts.message = {{json .Message}} $.exit(5)}
{{end -}} if(res.buttonReturned==={{json .Extra}}){res}else{void 0}
{{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
}
{{- end}} {{- end}}
{{define "notify" -}} {{define "notify" -}}
var app = Application.currentApplication() var app=Application.currentApplication()
app.includeStandardAdditions = true app.includeStandardAdditions=true
var opts = {} void app.displayNotification({{json .Text}},{{json .Options}})
{{if .Title -}}
opts.withTitle = {{json .Title}}
{{end -}}
{{if .Subtitle -}}
opts.subtitle = {{json .Subtitle}}
{{end -}}
void app.displayNotification({{json .Text}}, opts)
{{- end}}`)) {{- end}}`))

View file

@ -3,13 +3,15 @@
package main package main
import ( import (
"bufio" "bytes"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"text/template" "text/template"
"github.com/dchest/jsmin"
) )
func main() { func main() {
@ -29,27 +31,17 @@ func main() {
str.WriteString(strings.TrimSuffix(name, filepath.Ext(name))) str.WriteString(strings.TrimSuffix(name, filepath.Ext(name)))
str.WriteString(`" -}}` + "\n") str.WriteString(`" -}}` + "\n")
func() { data, err := ioutil.ReadFile(filepath.Join(dir, name))
in, err := os.Open(filepath.Join(dir, name))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer in.Close() data, err = minify(data)
if err != nil {
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) log.Fatal(err)
} }
}()
str.WriteString("{{- end}}") str.Write(data)
str.WriteString("\n{{- end}}")
} }
out, err := os.Create("osa_generated.go") 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. var generator = template.Must(template.New("").Parse(`// Code generated by zenity; DO NOT EDIT.
// +build darwin // +build darwin

View file

@ -2,8 +2,5 @@ var app = Application.currentApplication()
app.includeStandardAdditions = true app.includeStandardAdditions = true
app.activate() app.activate()
var opts = {} var res = app.chooseColor({defaultColor: {{json .}}})
opts.defaultColor = {{json .}} {"rgb(" + res.map(x => Math.round(x * 255)) + ")"}
var res = app.chooseColor(opts)
'rgb(' + res.map(x => Math.round(x * 255)) + ')'

View file

@ -2,28 +2,7 @@ var app = Application.currentApplication()
app.includeStandardAdditions = true app.includeStandardAdditions = true
app.activate() app.activate()
var opts = {} var res = app[{{json .Operation}}]({{json .Options}})
{{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)) { if (Array.isArray(res)) {
res.join({{json .Separator}}) res.join({{json .Separator}})
} else { } else {

View file

@ -2,34 +2,7 @@ var app = Application.currentApplication()
app.includeStandardAdditions = true app.includeStandardAdditions = true
app.activate() app.activate()
var opts = {} var res = app[{{json .Operation}}]({{json .Text}}, {{json .Options}})
{{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) { if (res.gaveUp) {
ObjC.import("stdlib") ObjC.import("stdlib")
$.exit(5) $.exit(5)

View file

@ -1,13 +1,4 @@
var app = Application.currentApplication() var app = Application.currentApplication()
app.includeStandardAdditions = true app.includeStandardAdditions = true
var opts = {} void app.displayNotification({{json .Text}}, {{json .Options}})
{{if .Title -}}
opts.withTitle = {{json .Title}}
{{end -}}
{{if .Subtitle -}}
opts.subtitle = {{json .Subtitle}}
{{end -}}
void app.displayNotification({{json .Text}}, opts)

View file

@ -40,33 +40,51 @@ func Run(ctx context.Context, script string, data interface{}) ([]byte, error) {
return cmd.Output() return cmd.Output()
} }
// File is internal.
type File struct { type File struct {
Operation string Operation string
Prompt string
Name string
Location string
Separator string Separator string
Type []string Options FileOptions
Invisibles bool
Multiple bool
} }
// 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 { type Msg struct {
Operation string Operation string
Text string Text string
Message string
As string
Title string
Icon string
Extra string Extra string
Buttons []string Options MsgOptions
Cancel int
Default int
Timeout int
} }
// 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 { type Notify struct {
Text string Text string
Title string Options NotifyOptions
Subtitle string }
// NotifyOptions is internal.
type NotifyOptions struct {
Title string `json:"withTitle,omitempty"`
Subtitle string `json:"subtitle,omitempty"`
} }

View file

@ -8,38 +8,39 @@ import (
func message(kind messageKind, text string, options []Option) (bool, error) { func message(kind messageKind, text string, options []Option) (bool, error) {
opts := applyOptions(options) opts := applyOptions(options)
data := zenutil.Msg{
Text: text, var data zenutil.Msg
Timeout: zenutil.Timeout, data.Text = text
} data.Options.Timeout = zenutil.Timeout
dialog := kind == questionKind || opts.icon != 0 dialog := kind == questionKind || opts.icon != 0
if dialog { if dialog {
data.Operation = "displayDialog" data.Operation = "displayDialog"
data.Title = opts.title data.Options.Title = opts.title
switch opts.icon { switch opts.icon {
case ErrorIcon: case ErrorIcon:
data.Icon = "stop" data.Options.Icon = "stop"
case WarningIcon: case WarningIcon:
data.Icon = "caution" data.Options.Icon = "caution"
case InfoIcon, QuestionIcon: case InfoIcon, QuestionIcon:
data.Icon = "note" data.Options.Icon = "note"
} }
} else { } else {
data.Operation = "displayAlert" data.Operation = "displayAlert"
if opts.title != "" { if opts.title != "" {
data.Message = text data.Options.Message = text
data.Text = opts.title data.Text = opts.title
} }
switch kind { switch kind {
case infoKind: case infoKind:
data.As = "informational" data.Options.As = "informational"
case warningKind: case warningKind:
data.As = "warning" data.Options.As = "warning"
case errorKind: 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 kind == questionKind {
if opts.extraButton == "" { if opts.extraButton == "" {
data.Buttons = []string{opts.cancelLabel, opts.okLabel} data.Options.Buttons = []string{opts.cancelLabel, opts.okLabel}
data.Default = 2 data.Options.Default = 2
data.Cancel = 1 data.Options.Cancel = 1
} else { } else {
data.Buttons = []string{opts.extraButton, opts.cancelLabel, opts.okLabel} data.Options.Buttons = []string{opts.extraButton, opts.cancelLabel, opts.okLabel}
data.Default = 3 data.Options.Default = 3
data.Cancel = 2 data.Options.Cancel = 2
} }
} else { } else {
if opts.extraButton == "" { if opts.extraButton == "" {
data.Buttons = []string{opts.okLabel} data.Options.Buttons = []string{opts.okLabel}
data.Default = 1 data.Options.Default = 1
} else { } else {
data.Buttons = []string{opts.extraButton, opts.okLabel} data.Options.Buttons = []string{opts.extraButton, opts.okLabel}
data.Default = 2 data.Options.Default = 2
} }
} }
data.Extra = opts.extraButton data.Extra = opts.extraButton
} }
if opts.defaultCancel { if opts.defaultCancel {
if data.Cancel != 0 { if data.Options.Cancel != 0 {
data.Default = data.Cancel data.Options.Default = data.Options.Cancel
} }
if dialog && data.Buttons == nil { if dialog && data.Options.Buttons == nil {
data.Default = 1 data.Options.Default = 1
} }
} }

View file

@ -8,12 +8,13 @@ import (
func notify(text string, options []Option) error { func notify(text string, options []Option) error {
opts := applyOptions(options) opts := applyOptions(options)
data := zenutil.Notify{
Text: text, var data zenutil.Notify
Title: opts.title, data.Text = text
} data.Options.Title = opts.title
if i := strings.IndexByte(text, '\n'); i >= 0 && i < len(text) { 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:] data.Text = text[i+1:]
} }
_, err := zenutil.Run(opts.ctx, "notify", data) _, err := zenutil.Run(opts.ctx, "notify", data)