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)
* on macOS:
* 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:
* wraps either one of `qarma`, `zenity`, `matedialog`,\
in that order of preference
* wraps either one of `zenity`, `qarma`, `matedialog`

View file

@ -13,7 +13,7 @@ func SelectColor(options ...Option) (color.Color, error) {
var data zenutil.Color
if opts.color != nil {
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)

View file

@ -3,78 +3,77 @@
package zenutil
import "html/template"
import "encoding/json"
import "text/template"
var scripts = template.Must(template.New("").Parse(`
{{define "color"}}<script>var app = Application.currentApplication()
app.includeStandardAdditions = true
app.activate()
var opts = {}
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(`
{{define "color" -}}tell application (path to frontmost application as text)
activate
{{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+')'
}
</script>{{end}}
{{define "file"}}<script>var app = Application.currentApplication()
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
{{- end}}
{{define "file" -}}var app = Application.currentApplication()
app.includeStandardAdditions = true
app.activate()
var opts = {}
{{if .Prompt -}}
opts.withPrompt = {{.Prompt}}
opts.withPrompt = {{json .Prompt}}
{{end -}}
{{if .Type -}}
opts.ofType = {{.Type}}
opts.ofType = {{json .Type}}
{{end -}}
{{if .Name -}}
opts.defaultName = {{.Name}}
opts.defaultName = {{json .Name}}
{{end -}}
{{if .Location -}}
opts.defaultLocation = {{.Location}}
opts.defaultLocation = {{json .Location}}
{{end -}}
{{if .Invisibles -}}
opts.invisibles = {{.Invisibles}}
opts.invisibles = {{json .Invisibles}}
{{end -}}
{{if .Multiple -}}
opts.multipleSelectionsAllowed = {{.Multiple}}
opts.multipleSelectionsAllowed = {{json .Multiple}}
{{end -}}
var res = app[{{.Operation}}](opts)
var res = app[{{json .Operation}}](opts)
if (Array.isArray(res)) {
res.join({{.Separator}})
res.join({{json .Separator}})
} else {
res.toString()
}
</script>{{end}}
{{define "msg"}}<script>var app = Application.currentApplication()
{{- end}}
{{define "msg" -}}var app = Application.currentApplication()
app.includeStandardAdditions = true
app.activate()
var opts = {}
{{if .Message -}}
opts.message = {{.Message}}
opts.message = {{json .Message}}
{{end -}}
{{if .As -}}
opts.as = {{.As}}
opts.as = {{json .As}}
{{end -}}
{{if .Title -}}
opts.withTitle = {{.Title}}
opts.withTitle = {{json .Title}}
{{end -}}
{{if .Icon -}}
opts.withIcon = {{.Icon}}
opts.withIcon = {{json .Icon}}
{{end -}}
{{if .Buttons -}}
opts.buttons = {{.Buttons}}
opts.buttons = {{json .Buttons}}
{{end -}}
{{if .Default -}}
opts.defaultButton = {{.Default}}
opts.defaultButton = {{json .Default}}
{{end -}}
{{if .Cancel -}}
opts.cancelButton = {{.Cancel}}
opts.cancelButton = {{json .Cancel}}
{{end -}}
var res = app[{{.Operation}}]({{.Text}}, opts).buttonReturned
res === {{.Extra}} ? res : void 0
</script>{{end}}`))
var res = app[{{json .Operation}}]({{json .Text}}, opts).buttonReturned
res === {{json .Extra}} ? res : void 0
{{- end}}`))

View file

@ -27,7 +27,7 @@ func main() {
str.WriteString("\n" + `{{define "`)
str.WriteString(strings.TrimSuffix(name, filepath.Ext(name)))
str.WriteString(`"}}<script>`)
str.WriteString(`" -}}`)
func() {
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")
@ -73,7 +73,11 @@ var generator = template.Must(template.New("").Parse(`// Code generated by zenit
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 = {}
{{if .Prompt -}}
opts.withPrompt = {{.Prompt}}
opts.withPrompt = {{json .Prompt}}
{{end -}}
{{if .Type -}}
opts.ofType = {{.Type}}
opts.ofType = {{json .Type}}
{{end -}}
{{if .Name -}}
opts.defaultName = {{.Name}}
opts.defaultName = {{json .Name}}
{{end -}}
{{if .Location -}}
opts.defaultLocation = {{.Location}}
opts.defaultLocation = {{json .Location}}
{{end -}}
{{if .Invisibles -}}
opts.invisibles = {{.Invisibles}}
opts.invisibles = {{json .Invisibles}}
{{end -}}
{{if .Multiple -}}
opts.multipleSelectionsAllowed = {{.Multiple}}
opts.multipleSelectionsAllowed = {{json .Multiple}}
{{end -}}
var res = app[{{.Operation}}](opts)
var res = app[{{json .Operation}}](opts)
if (Array.isArray(res)) {
res.join({{.Separator}})
res.join({{json .Separator}})
} else {
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
}
res := buf.String()
res = res[len("<script>") : len(res)-len("\n</script>")]
script = buf.String()
lang := "AppleScript"
if strings.HasPrefix(script, "var app") {
lang = "JavaScript"
}
if Command {
path, err := exec.LookPath("osascript")
if err == nil {
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.Stdin = strings.NewReader(res)
cmd := exec.Command("osascript", "-l", lang)
cmd.Stdin = strings.NewReader(script)
return cmd.Output()
}
@ -43,7 +46,7 @@ type File struct {
}
type Color struct {
Color []float32
Color []uint32
}
type Msg struct {