Use AppleScript for color (macos).

This commit is contained in:
Nuno Cruces 2020-01-21 12:03:58 +00:00
parent 9668c61d8b
commit 9460254709
10 changed files with 102 additions and 107 deletions

View file

@ -35,8 +35,5 @@ Why reinvent this particular wheel?
* WSL/Cygwin/MSYS2 [support](https://github.com/ncruces/zenity/wiki/Zenity-for-WSL,-Cygwin,-MSYS2) * WSL/Cygwin/MSYS2 [support](https://github.com/ncruces/zenity/wiki/Zenity-for-WSL,-Cygwin,-MSYS2)
* on macOS: * on macOS:
* only dependency is `osascript` * only dependency is `osascript`
(with [JXA](https://developer.apple.com/library/archive/releasenotes/InterapplicationCommunication/RN-JavaScriptForAutomation/Articles/Introduction.html);
`html/template` makes JavaScript easy to template)
* on other Unixes: * on other Unixes:
* wraps either one of `qarma`, `zenity`, `matedialog`,\ * wraps either one of `zenity`, `qarma`, `matedialog`
in that order of preference

View file

@ -13,7 +13,7 @@ func SelectColor(options ...Option) (color.Color, error) {
var data zenutil.Color var data zenutil.Color
if opts.color != nil { if opts.color != nil {
r, g, b, _ := opts.color.RGBA() r, g, b, _ := opts.color.RGBA()
data.Color = []float32{float32(r) / 0xffff, float32(g) / 0xffff, float32(b) / 0xffff} data.Color = []uint32{r, g, b}
} }
out, err := zenutil.Run("color", data) out, err := zenutil.Run("color", data)

View file

@ -3,78 +3,77 @@
package zenutil package zenutil
import "html/template" import "encoding/json"
import "text/template"
var scripts = template.Must(template.New("").Parse(` var scripts = template.Must(template.New("").Funcs(template.FuncMap{"json": func(v interface{}) (string, error) {
{{define "color"}}<script>var app = Application.currentApplication() b, err := json.Marshal(v)
app.includeStandardAdditions = true return string(b), err
app.activate() }}).Parse(`
var opts = {} {{define "color" -}}tell application (path to frontmost application as text)
activate
{{if .Color -}} {{if .Color -}}
opts.defaultColor = {{.Color}} set c to choose color default color { {{index .Color 0}}, {{index .Color 1}}, {{index .Color 2}} }
{{end -}} {{else -}}
var res = app.chooseColor(opts) set c to choose color
if (Array.isArray(res)) { {{end}}
res[0] = Math.round(255*res[0]) "rgb(" & (item 1 of c) div 257 & "," & (item 2 of c) div 257 & "," & (item 3 of c) div 257 & ")"
res[1] = Math.round(255*res[1]) end tell
res[2] = Math.round(255*res[2]) {{- end}}
'rgb('+res+')' {{define "file" -}}var app = Application.currentApplication()
}
</script>{{end}}
{{define "file"}}<script>var app = Application.currentApplication()
app.includeStandardAdditions = true app.includeStandardAdditions = true
app.activate() app.activate()
var opts = {} var opts = {}
{{if .Prompt -}} {{if .Prompt -}}
opts.withPrompt = {{.Prompt}} opts.withPrompt = {{json .Prompt}}
{{end -}} {{end -}}
{{if .Type -}} {{if .Type -}}
opts.ofType = {{.Type}} opts.ofType = {{json .Type}}
{{end -}} {{end -}}
{{if .Name -}} {{if .Name -}}
opts.defaultName = {{.Name}} opts.defaultName = {{json .Name}}
{{end -}} {{end -}}
{{if .Location -}} {{if .Location -}}
opts.defaultLocation = {{.Location}} opts.defaultLocation = {{json .Location}}
{{end -}} {{end -}}
{{if .Invisibles -}} {{if .Invisibles -}}
opts.invisibles = {{.Invisibles}} opts.invisibles = {{json .Invisibles}}
{{end -}} {{end -}}
{{if .Multiple -}} {{if .Multiple -}}
opts.multipleSelectionsAllowed = {{.Multiple}} opts.multipleSelectionsAllowed = {{json .Multiple}}
{{end -}} {{end -}}
var res = app[{{.Operation}}](opts) var res = app[{{json .Operation}}](opts)
if (Array.isArray(res)) { if (Array.isArray(res)) {
res.join({{.Separator}}) res.join({{json .Separator}})
} else { } else {
res.toString() res.toString()
} }
</script>{{end}} {{- end}}
{{define "msg"}}<script>var app = Application.currentApplication() {{define "msg" -}}var app = Application.currentApplication()
app.includeStandardAdditions = true app.includeStandardAdditions = true
app.activate() app.activate()
var opts = {} var opts = {}
{{if .Message -}} {{if .Message -}}
opts.message = {{.Message}} opts.message = {{json .Message}}
{{end -}} {{end -}}
{{if .As -}} {{if .As -}}
opts.as = {{.As}} opts.as = {{json .As}}
{{end -}} {{end -}}
{{if .Title -}} {{if .Title -}}
opts.withTitle = {{.Title}} opts.withTitle = {{json .Title}}
{{end -}} {{end -}}
{{if .Icon -}} {{if .Icon -}}
opts.withIcon = {{.Icon}} opts.withIcon = {{json .Icon}}
{{end -}} {{end -}}
{{if .Buttons -}} {{if .Buttons -}}
opts.buttons = {{.Buttons}} opts.buttons = {{json .Buttons}}
{{end -}} {{end -}}
{{if .Default -}} {{if .Default -}}
opts.defaultButton = {{.Default}} opts.defaultButton = {{json .Default}}
{{end -}} {{end -}}
{{if .Cancel -}} {{if .Cancel -}}
opts.cancelButton = {{.Cancel}} opts.cancelButton = {{json .Cancel}}
{{end -}} {{end -}}
var res = app[{{.Operation}}]({{.Text}}, opts).buttonReturned var res = app[{{json .Operation}}]({{json .Text}}, opts).buttonReturned
res === {{.Extra}} ? res : void 0 res === {{json .Extra}} ? res : void 0
</script>{{end}}`)) {{- end}}`))

View file

@ -27,7 +27,7 @@ func main() {
str.WriteString("\n" + `{{define "`) str.WriteString("\n" + `{{define "`)
str.WriteString(strings.TrimSuffix(name, filepath.Ext(name))) str.WriteString(strings.TrimSuffix(name, filepath.Ext(name)))
str.WriteString(`"}}<script>`) str.WriteString(`" -}}`)
func() { func() {
in, err := os.Open(filepath.Join(dir, name)) in, err := os.Open(filepath.Join(dir, name))
@ -49,7 +49,7 @@ func main() {
} }
}() }()
str.WriteString("</script>{{end}}") str.WriteString("{{- end}}")
} }
out, err := os.Create("osa_generated.go") out, err := os.Create("osa_generated.go")
@ -73,7 +73,11 @@ var generator = template.Must(template.New("").Parse(`// Code generated by zenit
package zenutil package zenutil
import "html/template" import "encoding/json"
import "text/template"
var scripts = template.Must(template.New("").Parse(` + "`{{.}}`" + `)) var scripts = template.Must(template.New("").Funcs(template.FuncMap{"json": func(v interface{}) (string, error) {
b, err := json.Marshal(v)
return string(b), err
}}).Parse(` + "`{{.}}`" + `))
`)) `))

View file

@ -0,0 +1,9 @@
tell application (path to frontmost application as text)
activate
{{if .Color -}}
set c to choose color default color { {{index .Color 0}}, {{index .Color 1}}, {{index .Color 2}} }
{{else -}}
set c to choose color
{{end}}
"rgb(" & (item 1 of c) div 257 & "," & (item 2 of c) div 257 & "," & (item 3 of c) div 257 & ")"
end tell

View file

@ -1,17 +0,0 @@
var app = Application.currentApplication()
app.includeStandardAdditions = true
app.activate()
var opts = {}
{{if .Color -}}
opts.defaultColor = {{.Color}}
{{end -}}
var res = app.chooseColor(opts)
if (Array.isArray(res)) {
res[0] = Math.round(255*res[0])
res[1] = Math.round(255*res[1])
res[2] = Math.round(255*res[2])
'rgb('+res+')'
}

View file

@ -5,27 +5,27 @@ app.activate()
var opts = {} var opts = {}
{{if .Prompt -}} {{if .Prompt -}}
opts.withPrompt = {{.Prompt}} opts.withPrompt = {{json .Prompt}}
{{end -}} {{end -}}
{{if .Type -}} {{if .Type -}}
opts.ofType = {{.Type}} opts.ofType = {{json .Type}}
{{end -}} {{end -}}
{{if .Name -}} {{if .Name -}}
opts.defaultName = {{.Name}} opts.defaultName = {{json .Name}}
{{end -}} {{end -}}
{{if .Location -}} {{if .Location -}}
opts.defaultLocation = {{.Location}} opts.defaultLocation = {{json .Location}}
{{end -}} {{end -}}
{{if .Invisibles -}} {{if .Invisibles -}}
opts.invisibles = {{.Invisibles}} opts.invisibles = {{json .Invisibles}}
{{end -}} {{end -}}
{{if .Multiple -}} {{if .Multiple -}}
opts.multipleSelectionsAllowed = {{.Multiple}} opts.multipleSelectionsAllowed = {{json .Multiple}}
{{end -}} {{end -}}
var res = app[{{.Operation}}](opts) var res = app[{{json .Operation}}](opts)
if (Array.isArray(res)) { if (Array.isArray(res)) {
res.join({{.Separator}}) res.join({{json .Separator}})
} else { } else {
res.toString() res.toString()
} }

View file

@ -1,30 +0,0 @@
var app = Application.currentApplication()
app.includeStandardAdditions = true
app.activate()
var opts = {}
{{if .Message -}}
opts.message = {{.Message}}
{{end -}}
{{if .As -}}
opts.as = {{.As}}
{{end -}}
{{if .Title -}}
opts.withTitle = {{.Title}}
{{end -}}
{{if .Icon -}}
opts.withIcon = {{.Icon}}
{{end -}}
{{if .Buttons -}}
opts.buttons = {{.Buttons}}
{{end -}}
{{if .Default -}}
opts.defaultButton = {{.Default}}
{{end -}}
{{if .Cancel -}}
opts.cancelButton = {{.Cancel}}
{{end -}}
var res = app[{{.Operation}}]({{.Text}}, opts).buttonReturned
res === {{.Extra}} ? res : void 0

View file

@ -0,0 +1,30 @@
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 .Default -}}
opts.defaultButton = {{json .Default}}
{{end -}}
{{if .Cancel -}}
opts.cancelButton = {{json .Cancel}}
{{end -}}
var res = app[{{json .Operation}}]({{json .Text}}, opts).buttonReturned
res === {{json .Extra}} ? res : void 0

View file

@ -15,19 +15,22 @@ func Run(script string, data interface{}) ([]byte, error) {
return nil, err return nil, err
} }
res := buf.String() script = buf.String()
res = res[len("<script>") : len(res)-len("\n</script>")] lang := "AppleScript"
if strings.HasPrefix(script, "var app") {
lang = "JavaScript"
}
if Command { if Command {
path, err := exec.LookPath("osascript") path, err := exec.LookPath("osascript")
if err == nil { if err == nil {
os.Stderr.Close() os.Stderr.Close()
syscall.Exec(path, []string{"osascript", "-l", "JavaScript", "-e", res}, nil) syscall.Exec(path, []string{"osascript", "-l", lang, "-e", script}, nil)
} }
} }
cmd := exec.Command("osascript", "-l", "JavaScript") cmd := exec.Command("osascript", "-l", lang)
cmd.Stdin = strings.NewReader(res) cmd.Stdin = strings.NewReader(script)
return cmd.Output() return cmd.Output()
} }
@ -43,7 +46,7 @@ type File struct {
} }
type Color struct { type Color struct {
Color []float32 Color []uint32
} }
type Msg struct { type Msg struct {