Attach (macOS).

This commit is contained in:
Nuno Cruces 2022-06-02 12:49:31 +01:00
parent 69c05cdd0d
commit b902eebb1d
14 changed files with 73 additions and 37 deletions

View file

@ -15,6 +15,7 @@ import (
"path/filepath" "path/filepath"
"runtime" "runtime"
"runtime/debug" "runtime/debug"
"strconv"
"strings" "strings"
"syscall" "syscall"
"time" "time"
@ -51,6 +52,7 @@ var (
text string text string
icon string icon string
windowIcon string windowIcon string
attach string
multiple bool multiple bool
defaultCancel bool defaultCancel bool
@ -209,6 +211,8 @@ func setupFlags() {
flag.Func("extra-button", "Add an extra `button`", setExtraButton) flag.Func("extra-button", "Add an extra `button`", setExtraButton)
flag.StringVar(&text, "text", "", "Set the dialog `text`") flag.StringVar(&text, "text", "", "Set the dialog `text`")
flag.StringVar(&windowIcon, "window-icon", "", "Set the window `icon` (error, info, question, warning)") flag.StringVar(&windowIcon, "window-icon", "", "Set the window `icon` (error, info, question, warning)")
flag.StringVar(&attach, "attach", "", "Set the parent `window` to attach to")
flag.Bool("modal", true, "Set the modal hint")
flag.BoolVar(&multiple, "multiple", false, "Allow multiple items to be selected") flag.BoolVar(&multiple, "multiple", false, "Allow multiple items to be selected")
flag.BoolVar(&defaultCancel, "default-cancel", false, "Give Cancel button focus by default") flag.BoolVar(&defaultCancel, "default-cancel", false, "Give Cancel button focus by default")
@ -443,6 +447,14 @@ func loadFlags() []zenity.Option {
opts = append(opts, zenity.WindowIcon(ingestPath(windowIcon))) opts = append(opts, zenity.WindowIcon(ingestPath(windowIcon)))
} }
if attach != "" {
if i, err := strconv.ParseUint(attach, 0, 64); err != nil {
opts = append(opts, zenity.Attach(attach))
} else {
opts = append(opts, zenity.Attach(i))
}
}
// Message options // Message options
if noWrap { if noWrap {

View file

@ -8,7 +8,9 @@ import (
func selectColor(opts options) (color.Color, error) { func selectColor(opts options) (color.Color, error) {
var data zenutil.Color var data zenutil.Color
if i, ok := opts.windowIcon.(string); ok { if opts.attach != nil {
data.Application = opts.attach
} else if i, ok := opts.windowIcon.(string); ok {
data.WindowIcon = i data.WindowIcon = i
} }

View file

@ -14,7 +14,9 @@ func entry(text string, opts options) (string, error) {
data.Options.Answer = &opts.entryText data.Options.Answer = &opts.entryText
data.Options.Hidden = opts.hideText data.Options.Hidden = opts.hideText
data.Options.Timeout = zenutil.Timeout data.Options.Timeout = zenutil.Timeout
if i, ok := opts.windowIcon.(string); ok { if opts.attach != nil {
data.Application = opts.attach
} else if i, ok := opts.windowIcon.(string); ok {
data.WindowIcon = i data.WindowIcon = i
} }
switch i := opts.icon.(type) { switch i := opts.icon.(type) {

View file

@ -7,7 +7,9 @@ func selectFile(opts options) (string, error) {
data.Options.Prompt = opts.title data.Options.Prompt = opts.title
data.Options.Invisibles = opts.showHidden data.Options.Invisibles = opts.showHidden
data.Options.Location, _ = splitDirAndName(opts.filename) data.Options.Location, _ = splitDirAndName(opts.filename)
if i, ok := opts.windowIcon.(string); ok { if opts.attach != nil {
data.Application = opts.attach
} else if i, ok := opts.windowIcon.(string); ok {
data.WindowIcon = i data.WindowIcon = i
} }
@ -29,7 +31,9 @@ func selectFileMultiple(opts options) ([]string, error) {
data.Options.Location, _ = splitDirAndName(opts.filename) data.Options.Location, _ = splitDirAndName(opts.filename)
data.Options.Multiple = true data.Options.Multiple = true
data.Separator = zenutil.Separator data.Separator = zenutil.Separator
if i, ok := opts.windowIcon.(string); ok { if opts.attach != nil {
data.Application = opts.attach
} else if i, ok := opts.windowIcon.(string); ok {
data.WindowIcon = i data.WindowIcon = i
} }
@ -49,7 +53,9 @@ func selectFileSave(opts options) (string, error) {
data.Options.Prompt = opts.title data.Options.Prompt = opts.title
data.Options.Invisibles = opts.showHidden data.Options.Invisibles = opts.showHidden
data.Options.Location, data.Options.Name = splitDirAndName(opts.filename) data.Options.Location, data.Options.Name = splitDirAndName(opts.filename)
if i, ok := opts.windowIcon.(string); ok { if opts.attach != nil {
data.Application = opts.attach
} else if i, ok := opts.windowIcon.(string); ok {
data.WindowIcon = i data.WindowIcon = i
} }

4
go.mod
View file

@ -8,8 +8,8 @@ require (
github.com/ncruces/go-strftime v0.1.8 github.com/ncruces/go-strftime v0.1.8
github.com/randall77/makefat v0.0.0-20210315173500-7ddd0e42c844 github.com/randall77/makefat v0.0.0-20210315173500-7ddd0e42c844
go.uber.org/goleak v1.1.12 // test go.uber.org/goleak v1.1.12 // test
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 golang.org/x/image v0.0.0-20220601225756-64ec528b34cd
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
) )
require ( require (

10
go.sum
View file

@ -24,8 +24,8 @@ go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 h1:LRtI4W37N+KFebI/qV0OFiLUv4GLOWeEW5hn/KEJvxE= golang.org/x/image v0.0.0-20220601225756-64ec528b34cd h1:9NbNcTg//wfC5JskFW4Z3sqwVnjmJKHxLAol1bW2qgw=
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.0.0-20220601225756-64ec528b34cd/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
@ -42,12 +42,12 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba h1:AyHWHCBVlIYI5rgEM3o+1PLd0sLPcIAoaUckGQMaWtw= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=

View file

@ -20,6 +20,9 @@ var (
DateParse = func(s string) (time.Time, error) { return time.Parse("2006-01-02", s) } DateParse = func(s string) (time.Time, error) { return time.Parse("2006-01-02", s) }
) )
// Remove after 1.18.
type any = interface{}
type stringErr string type stringErr string
func (e stringErr) Error() string { return string(e) } func (e stringErr) Error() string { return string(e) }

View file

@ -8,7 +8,7 @@ import (
"text/template" "text/template"
) )
var scripts = template.Must(template.New("").Funcs(template.FuncMap{"json": func(v interface{}) (string, error) { var scripts = template.Must(template.New("").Funcs(template.FuncMap{"json": func(v any) (string, error) {
b, err := json.Marshal(v) b, err := json.Marshal(v)
return string(b), err return string(b), err
}}).Parse(` }}).Parse(`
@ -22,16 +22,18 @@ $.exit(-1)}
{'rgb('+res.map(x=>Math.round(x*255))+')'} {'rgb('+res.map(x=>Math.round(x*255))+')'}
{{- end}} {{- end}}
{{define "common" -}} {{define "common" -}}
{var app=Application.currentApplication() {{- if .Application}}
app.includeStandardAdditions=true var app=Application({{json .Application}})
{{- if .WindowIcon}} {{- else}}
ObjC.import('Cocoa') var app=Application.currentApplication()
{{- end}}
{{- if .WindowIcon}}{ObjC.import('Cocoa')
let nsapp=$.NSApplication.sharedApplication let nsapp=$.NSApplication.sharedApplication
let nsimg=$.NSImage.alloc.initWithContentsOfFile({{json .WindowIcon}}) let nsimg=$.NSImage.alloc.initWithContentsOfFile({{json .WindowIcon}})
nsapp.setActivationPolicy($.NSApplicationActivationPolicyRegular) nsapp.setActivationPolicy($.NSApplicationActivationPolicyRegular)
nsapp.setApplicationIconImage(nsimg) nsapp.setApplicationIconImage(nsimg)}{{- end}}
{{- end}} app.includeStandardAdditions=true
app.activate()} app.activate()
{{- end}} {{- end}}
{{define "date" -}} {{define "date" -}}
ObjC.import('Cocoa') ObjC.import('Cocoa')

View file

@ -111,7 +111,7 @@ import (
"text/template" "text/template"
) )
var scripts = template.Must(template.New("").Funcs(template.FuncMap{"json": func(v interface{}) (string, error) { var scripts = template.Must(template.New("").Funcs(template.FuncMap{"json": func(v any) (string, error) {
b, err := json.Marshal(v) b, err := json.Marshal(v)
return string(b), err return string(b), err
}}).Parse(` + "`{{.}}`))\n")) }}).Parse(` + "`{{.}}`))\n"))

View file

@ -1,14 +1,16 @@
{ {{- if .Application}}
var app = Application({{json .Application}})
{{- else}}
var app = Application.currentApplication() var app = Application.currentApplication()
app.includeStandardAdditions = true {{- end}}
{{- if .WindowIcon}} {{- if .WindowIcon}}{
ObjC.import('Cocoa') ObjC.import('Cocoa')
let nsapp = $.NSApplication.sharedApplication let nsapp = $.NSApplication.sharedApplication
let nsimg = $.NSImage.alloc.initWithContentsOfFile({{json .WindowIcon}}) let nsimg = $.NSImage.alloc.initWithContentsOfFile({{json .WindowIcon}})
nsapp.setActivationPolicy($.NSApplicationActivationPolicyRegular) nsapp.setActivationPolicy($.NSApplicationActivationPolicyRegular)
nsapp.setApplicationIconImage(nsimg) nsapp.setApplicationIconImage(nsimg)
{{- end}} }{{- end}}
app.activate() app.includeStandardAdditions = true
} app.activate()

View file

@ -10,7 +10,7 @@ import (
) )
// Run is internal. // Run is internal.
func Run(ctx context.Context, script string, data interface{}) ([]byte, error) { func Run(ctx context.Context, script string, data any) ([]byte, error) {
var buf bytes.Buffer var buf bytes.Buffer
err := scripts.ExecuteTemplate(&buf, script, data) err := scripts.ExecuteTemplate(&buf, script, data)
if err != nil { if err != nil {
@ -124,6 +124,7 @@ func RunProgress(ctx context.Context, max int, data Progress) (dlg *progressDial
} }
type common struct { type common struct {
Application any
WindowIcon string WindowIcon string
} }

View file

@ -22,7 +22,9 @@ func list(text string, items []string, opts options) (string, error) {
data.Options.Cancel = opts.cancelLabel data.Options.Cancel = opts.cancelLabel
data.Options.Default = opts.defaultItems data.Options.Default = opts.defaultItems
data.Options.Empty = !opts.disallowEmpty data.Options.Empty = !opts.disallowEmpty
if i, ok := opts.windowIcon.(string); ok { if opts.attach != nil {
data.Application = opts.attach
} else if i, ok := opts.windowIcon.(string); ok {
data.WindowIcon = i data.WindowIcon = i
} }

View file

@ -10,7 +10,9 @@ func message(kind messageKind, text string, opts options) error {
var data zenutil.Dialog var data zenutil.Dialog
data.Text = text data.Text = text
data.Options.Timeout = zenutil.Timeout data.Options.Timeout = zenutil.Timeout
if i, ok := opts.windowIcon.(string); ok { if opts.attach != nil {
data.Application = opts.attach
} else if i, ok := opts.windowIcon.(string); ok {
data.WindowIcon = i data.WindowIcon = i
} }

View file

@ -18,7 +18,9 @@ func password(opts options) (string, string, error) {
data.Separator = zenutil.Separator data.Separator = zenutil.Separator
data.Options.Title = opts.title data.Options.Title = opts.title
data.Options.Timeout = zenutil.Timeout data.Options.Timeout = zenutil.Timeout
if i, ok := opts.windowIcon.(string); ok { if opts.attach != nil {
data.Application = opts.attach
} else if i, ok := opts.windowIcon.(string); ok {
data.WindowIcon = i data.WindowIcon = i
} }
switch i := opts.icon.(type) { switch i := opts.icon.(type) {