Timeouts, cancellation (macos, linux).
This commit is contained in:
parent
e211121451
commit
1fdf2f7d73
19 changed files with 132 additions and 57 deletions
12
cmd/zenity/build.sh
Executable file
12
cmd/zenity/build.sh
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
GOOS=windows GOARCH=386 go build -ldflags="-s -w" &&
|
||||||
|
zip -9 zenity_win32.zip zenity.exe
|
||||||
|
|
||||||
|
GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" &&
|
||||||
|
zip -9 zenity_win64.zip zenity.exe
|
||||||
|
|
||||||
|
GOOS=darwin GOARCH=amd64 go build -ldflags="-s -w" &&
|
||||||
|
zip -9 zenity_macos.zip zenity
|
||||||
|
|
||||||
|
go build
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"image/color"
|
"image/color"
|
||||||
"os"
|
"os"
|
||||||
|
@ -8,6 +9,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ncruces/zenity"
|
"github.com/ncruces/zenity"
|
||||||
"github.com/ncruces/zenity/internal/zenutil"
|
"github.com/ncruces/zenity/internal/zenutil"
|
||||||
|
@ -46,7 +48,6 @@ var (
|
||||||
confirmCreate bool
|
confirmCreate bool
|
||||||
showHidden bool
|
showHidden bool
|
||||||
filename string
|
filename string
|
||||||
separator string
|
|
||||||
fileFilters FileFilters
|
fileFilters FileFilters
|
||||||
|
|
||||||
// Color selection options
|
// Color selection options
|
||||||
|
@ -58,12 +59,25 @@ var (
|
||||||
wslpath bool
|
wslpath bool
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
prevUsage := flag.Usage
|
||||||
|
flag.Usage = func() {
|
||||||
|
prevUsage()
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
setupFlags()
|
setupFlags()
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
validateFlags()
|
validateFlags()
|
||||||
opts := loadFlags()
|
opts := loadFlags()
|
||||||
zenutil.Command = true
|
zenutil.Command = true
|
||||||
|
if zenutil.Timeout > 0 {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(zenutil.Timeout)*time.Second)
|
||||||
|
opts = append(opts, zenity.Context(ctx))
|
||||||
|
_ = cancel
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case notification:
|
case notification:
|
||||||
|
@ -93,12 +107,10 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
os.Exit(-1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupFlags() {
|
func setupFlags() {
|
||||||
// Application Options
|
// Application Options
|
||||||
|
|
||||||
flag.BoolVar(¬ification, "notification", false, "Display notification")
|
flag.BoolVar(¬ification, "notification", false, "Display notification")
|
||||||
flag.BoolVar(&errorDlg, "error", false, "Display error dialog")
|
flag.BoolVar(&errorDlg, "error", false, "Display error dialog")
|
||||||
flag.BoolVar(&infoDlg, "info", false, "Display info dialog")
|
flag.BoolVar(&infoDlg, "info", false, "Display info dialog")
|
||||||
|
@ -108,12 +120,10 @@ func setupFlags() {
|
||||||
flag.BoolVar(&colorSelectionDlg, "color-selection", false, "Display color selection dialog")
|
flag.BoolVar(&colorSelectionDlg, "color-selection", false, "Display color selection dialog")
|
||||||
|
|
||||||
// General options
|
// General options
|
||||||
|
|
||||||
flag.StringVar(&title, "title", "", "Set the dialog title")
|
flag.StringVar(&title, "title", "", "Set the dialog title")
|
||||||
flag.StringVar(&icon, "window-icon", "", "Set the window icon (error, info, question, warning)")
|
flag.StringVar(&icon, "window-icon", "", "Set the window icon (error, info, question, warning)")
|
||||||
|
|
||||||
// Message options
|
// Message options
|
||||||
|
|
||||||
flag.StringVar(&text, "text", "", "Set the dialog text")
|
flag.StringVar(&text, "text", "", "Set the dialog text")
|
||||||
flag.StringVar(&icon, "icon-name", "", "Set the dialog icon (error, info, question, warning)")
|
flag.StringVar(&icon, "icon-name", "", "Set the dialog icon (error, info, question, warning)")
|
||||||
flag.StringVar(&okLabel, "ok-label", "", "Set the label of the OK button")
|
flag.StringVar(&okLabel, "ok-label", "", "Set the label of the OK button")
|
||||||
|
@ -124,7 +134,6 @@ func setupFlags() {
|
||||||
flag.BoolVar(&defaultCancel, "default-cancel", false, "Give Cancel button focus by default")
|
flag.BoolVar(&defaultCancel, "default-cancel", false, "Give Cancel button focus by default")
|
||||||
|
|
||||||
// File selection options
|
// File selection options
|
||||||
|
|
||||||
flag.BoolVar(&save, "save", false, "Activate save mode")
|
flag.BoolVar(&save, "save", false, "Activate save mode")
|
||||||
flag.BoolVar(&multiple, "multiple", false, "Allow multiple files to be selected")
|
flag.BoolVar(&multiple, "multiple", false, "Allow multiple files to be selected")
|
||||||
flag.BoolVar(&directory, "directory", false, "Activate directory-only selection")
|
flag.BoolVar(&directory, "directory", false, "Activate directory-only selection")
|
||||||
|
@ -132,7 +141,6 @@ func setupFlags() {
|
||||||
flag.BoolVar(&confirmCreate, "confirm-create", false, "Confirm file selection if filename does not yet exist (Windows only)")
|
flag.BoolVar(&confirmCreate, "confirm-create", false, "Confirm file selection if filename does not yet exist (Windows only)")
|
||||||
flag.BoolVar(&showHidden, "show-hidden", false, "Show hidden files (Windows and macOS only)")
|
flag.BoolVar(&showHidden, "show-hidden", false, "Show hidden files (Windows and macOS only)")
|
||||||
flag.StringVar(&filename, "filename", "", "Set the filename")
|
flag.StringVar(&filename, "filename", "", "Set the filename")
|
||||||
flag.StringVar(&separator, "separator", "|", "Set output separator character")
|
|
||||||
flag.Var(&fileFilters, "file-filter", "Set a filename filter (NAME | PATTERN1 PATTERN2 ...)")
|
flag.Var(&fileFilters, "file-filter", "Set a filename filter (NAME | PATTERN1 PATTERN2 ...)")
|
||||||
|
|
||||||
// Color selection options
|
// Color selection options
|
||||||
|
@ -144,6 +152,10 @@ func setupFlags() {
|
||||||
flag.BoolVar(&cygpath, "cygpath", false, "Use cygpath for path translation (Windows only)")
|
flag.BoolVar(&cygpath, "cygpath", false, "Use cygpath for path translation (Windows only)")
|
||||||
flag.BoolVar(&wslpath, "wslpath", false, "Use wslpath for path translation (Windows only)")
|
flag.BoolVar(&wslpath, "wslpath", false, "Use wslpath for path translation (Windows only)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal options
|
||||||
|
flag.IntVar(&zenutil.Timeout, "timeout", 0, "Set dialog timeout in seconds")
|
||||||
|
flag.StringVar(&zenutil.Separator, "separator", "|", "Set output separator character")
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateFlags() {
|
func validateFlags() {
|
||||||
|
@ -171,16 +183,15 @@ func validateFlags() {
|
||||||
}
|
}
|
||||||
if n != 1 {
|
if n != 1 {
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
os.Exit(-1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadFlags() []zenity.Option {
|
func loadFlags() []zenity.Option {
|
||||||
var options []zenity.Option
|
var opts []zenity.Option
|
||||||
|
|
||||||
// General options
|
// General options
|
||||||
|
|
||||||
options = append(options, zenity.Title(title))
|
opts = append(opts, zenity.Title(title))
|
||||||
|
|
||||||
// Message options
|
// Message options
|
||||||
|
|
||||||
|
@ -196,51 +207,49 @@ func loadFlags() []zenity.Option {
|
||||||
ico = zenity.WarningIcon
|
ico = zenity.WarningIcon
|
||||||
}
|
}
|
||||||
|
|
||||||
options = append(options, zenity.Icon(ico))
|
opts = append(opts, zenity.Icon(ico))
|
||||||
options = append(options, zenity.OKLabel(okLabel))
|
opts = append(opts, zenity.OKLabel(okLabel))
|
||||||
options = append(options, zenity.CancelLabel(cancelLabel))
|
opts = append(opts, zenity.CancelLabel(cancelLabel))
|
||||||
options = append(options, zenity.ExtraButton(extraButton))
|
opts = append(opts, zenity.ExtraButton(extraButton))
|
||||||
if noWrap {
|
if noWrap {
|
||||||
options = append(options, zenity.NoWrap())
|
opts = append(opts, zenity.NoWrap())
|
||||||
}
|
}
|
||||||
if ellipsize {
|
if ellipsize {
|
||||||
options = append(options, zenity.Ellipsize())
|
opts = append(opts, zenity.Ellipsize())
|
||||||
}
|
}
|
||||||
if defaultCancel {
|
if defaultCancel {
|
||||||
options = append(options, zenity.DefaultCancel())
|
opts = append(opts, zenity.DefaultCancel())
|
||||||
}
|
}
|
||||||
|
|
||||||
// File selection options
|
// File selection options
|
||||||
|
|
||||||
options = append(options, fileFilters)
|
opts = append(opts, fileFilters)
|
||||||
if filename != "" {
|
if filename != "" {
|
||||||
options = append(options, zenity.Filename(ingestPath(filename)))
|
opts = append(opts, zenity.Filename(ingestPath(filename)))
|
||||||
}
|
}
|
||||||
if directory {
|
if directory {
|
||||||
options = append(options, zenity.Directory())
|
opts = append(opts, zenity.Directory())
|
||||||
}
|
}
|
||||||
if confirmOverwrite {
|
if confirmOverwrite {
|
||||||
options = append(options, zenity.ConfirmOverwrite())
|
opts = append(opts, zenity.ConfirmOverwrite())
|
||||||
}
|
}
|
||||||
if confirmCreate {
|
if confirmCreate {
|
||||||
options = append(options, zenity.ConfirmCreate())
|
opts = append(opts, zenity.ConfirmCreate())
|
||||||
}
|
}
|
||||||
if showHidden {
|
if showHidden {
|
||||||
options = append(options, zenity.ShowHidden())
|
opts = append(opts, zenity.ShowHidden())
|
||||||
}
|
}
|
||||||
|
|
||||||
zenutil.Separator = separator
|
|
||||||
|
|
||||||
// Color selection options
|
// Color selection options
|
||||||
|
|
||||||
if defaultColor != "" {
|
if defaultColor != "" {
|
||||||
options = append(options, zenity.Color(zenutil.ParseColor(defaultColor)))
|
opts = append(opts, zenity.Color(zenutil.ParseColor(defaultColor)))
|
||||||
}
|
}
|
||||||
if showPalette {
|
if showPalette {
|
||||||
options = append(options, zenity.ShowPalette())
|
opts = append(opts, zenity.ShowPalette())
|
||||||
}
|
}
|
||||||
|
|
||||||
return options
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
func errResult(err error) {
|
func errResult(err error) {
|
||||||
|
@ -289,7 +298,7 @@ func listResult(l []string, err error) {
|
||||||
os.Stderr.WriteString(zenutil.LineBreak)
|
os.Stderr.WriteString(zenutil.LineBreak)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
os.Stdout.WriteString(strings.Join(l, separator))
|
os.Stdout.WriteString(strings.Join(l, zenutil.Separator))
|
||||||
os.Stdout.WriteString(zenutil.LineBreak)
|
os.Stdout.WriteString(zenutil.LineBreak)
|
||||||
if l == nil {
|
if l == nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
@ -16,7 +16,7 @@ func selectColor(options []Option) (color.Color, error) {
|
||||||
data.Color = []uint16{n.R, n.G, n.B}
|
data.Color = []uint16{n.R, n.G, n.B}
|
||||||
}
|
}
|
||||||
|
|
||||||
out, err := zenutil.Run("color", data)
|
out, err := zenutil.Run(opts.ctx, "color", data)
|
||||||
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 {
|
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ func selectColor(options []Option) (color.Color, error) {
|
||||||
args = append(args, "--show-palette")
|
args = append(args, "--show-palette")
|
||||||
}
|
}
|
||||||
|
|
||||||
out, err := zenutil.Run(args)
|
out, err := zenutil.Run(opts.ctx, args)
|
||||||
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 {
|
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ func selectFile(options []Option) (string, error) {
|
||||||
}
|
}
|
||||||
data.Location, _ = splitDirAndName(opts.filename)
|
data.Location, _ = splitDirAndName(opts.filename)
|
||||||
|
|
||||||
out, err := zenutil.Run("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 {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,8 @@ func selectFileMutiple(options []Option) ([]string, error) {
|
||||||
data := zenutil.File{
|
data := zenutil.File{
|
||||||
Prompt: opts.title,
|
Prompt: opts.title,
|
||||||
Invisibles: opts.showHidden,
|
Invisibles: opts.showHidden,
|
||||||
Multiple: true,
|
|
||||||
Separator: zenutil.Separator,
|
Separator: zenutil.Separator,
|
||||||
|
Multiple: true,
|
||||||
}
|
}
|
||||||
if opts.directory {
|
if opts.directory {
|
||||||
data.Operation = "chooseFolder"
|
data.Operation = "chooseFolder"
|
||||||
|
@ -52,7 +52,7 @@ func selectFileMutiple(options []Option) ([]string, error) {
|
||||||
}
|
}
|
||||||
data.Location, _ = splitDirAndName(opts.filename)
|
data.Location, _ = splitDirAndName(opts.filename)
|
||||||
|
|
||||||
out, err := zenutil.Run("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 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ func selectFileSave(options []Option) (string, error) {
|
||||||
}
|
}
|
||||||
data.Location, data.Name = splitDirAndName(opts.filename)
|
data.Location, data.Name = splitDirAndName(opts.filename)
|
||||||
|
|
||||||
out, err := zenutil.Run("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 {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ func selectFile(options []Option) (string, error) {
|
||||||
}
|
}
|
||||||
args = append(args, initFilters(opts.fileFilters)...)
|
args = append(args, initFilters(opts.fileFilters)...)
|
||||||
|
|
||||||
out, err := zenutil.Run(args)
|
out, err := zenutil.Run(opts.ctx, args)
|
||||||
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 {
|
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ func selectFileMutiple(options []Option) ([]string, error) {
|
||||||
}
|
}
|
||||||
args = append(args, initFilters(opts.fileFilters)...)
|
args = append(args, initFilters(opts.fileFilters)...)
|
||||||
|
|
||||||
out, err := zenutil.Run(args)
|
out, err := zenutil.Run(opts.ctx, args)
|
||||||
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 {
|
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ func selectFileSave(options []Option) (string, error) {
|
||||||
}
|
}
|
||||||
args = append(args, initFilters(opts.fileFilters)...)
|
args = append(args, initFilters(opts.fileFilters)...)
|
||||||
|
|
||||||
out, err := zenutil.Run(args)
|
out, err := zenutil.Run(opts.ctx, args)
|
||||||
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 {
|
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,4 +3,5 @@ package zenutil
|
||||||
const LineBreak = "\n"
|
const LineBreak = "\n"
|
||||||
|
|
||||||
var Command bool
|
var Command bool
|
||||||
|
var Timeout int
|
||||||
var Separator = "\x00"
|
var Separator = "\x00"
|
||||||
|
|
|
@ -6,4 +6,5 @@ package zenutil
|
||||||
const LineBreak = "\n"
|
const LineBreak = "\n"
|
||||||
|
|
||||||
var Command bool
|
var Command bool
|
||||||
|
var Timeout int
|
||||||
var Separator = "\x1e"
|
var Separator = "\x1e"
|
||||||
|
|
|
@ -3,4 +3,5 @@ package zenutil
|
||||||
const LineBreak = "\r\n"
|
const LineBreak = "\r\n"
|
||||||
|
|
||||||
var Command bool
|
var Command bool
|
||||||
|
var Timeout int
|
||||||
var Separator string
|
var Separator string
|
||||||
|
|
|
@ -68,14 +68,25 @@ opts.withIcon = {{json .Icon}}
|
||||||
{{if .Buttons -}}
|
{{if .Buttons -}}
|
||||||
opts.buttons = {{json .Buttons}}
|
opts.buttons = {{json .Buttons}}
|
||||||
{{end -}}
|
{{end -}}
|
||||||
{{if .Default -}}
|
|
||||||
opts.defaultButton = {{json .Default}}
|
|
||||||
{{end -}}
|
|
||||||
{{if .Cancel -}}
|
{{if .Cancel -}}
|
||||||
opts.cancelButton = {{json .Cancel}}
|
opts.cancelButton = {{json .Cancel}}
|
||||||
{{end -}}
|
{{end -}}
|
||||||
var res = app[{{json .Operation}}]({{json .Text}}, opts).buttonReturned
|
{{if .Default -}}
|
||||||
res === {{json .Extra}} ? res : void 0
|
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" -}}var app = Application.currentApplication()
|
{{define "notify" -}}var app = Application.currentApplication()
|
||||||
app.includeStandardAdditions = true
|
app.includeStandardAdditions = true
|
||||||
|
|
|
@ -19,12 +19,23 @@ var opts = {}
|
||||||
{{if .Buttons -}}
|
{{if .Buttons -}}
|
||||||
opts.buttons = {{json .Buttons}}
|
opts.buttons = {{json .Buttons}}
|
||||||
{{end -}}
|
{{end -}}
|
||||||
{{if .Default -}}
|
|
||||||
opts.defaultButton = {{json .Default}}
|
|
||||||
{{end -}}
|
|
||||||
{{if .Cancel -}}
|
{{if .Cancel -}}
|
||||||
opts.cancelButton = {{json .Cancel}}
|
opts.cancelButton = {{json .Cancel}}
|
||||||
{{end -}}
|
{{end -}}
|
||||||
|
{{if .Default -}}
|
||||||
|
opts.defaultButton = {{json .Default}}
|
||||||
|
{{end -}}
|
||||||
|
{{if .Timeout -}}
|
||||||
|
opts.givingUpAfter = {{json .Timeout}}
|
||||||
|
{{end -}}
|
||||||
|
|
||||||
var res = app[{{json .Operation}}]({{json .Text}}, opts).buttonReturned
|
var res = app[{{json .Operation}}]({{json .Text}}, opts)
|
||||||
res === {{json .Extra}} ? res : void 0
|
if (res.gaveUp) {
|
||||||
|
ObjC.import("stdlib")
|
||||||
|
$.exit(5)
|
||||||
|
}
|
||||||
|
if (res.buttonReturned === {{json .Extra}}) {
|
||||||
|
res
|
||||||
|
} else {
|
||||||
|
void 0
|
||||||
|
}
|
|
@ -1,13 +1,14 @@
|
||||||
package zenutil
|
package zenutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(script string, data interface{}) ([]byte, error) {
|
func Run(ctx context.Context, script string, data interface{}) ([]byte, error) {
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
|
|
||||||
err := scripts.ExecuteTemplate(&buf, script, data)
|
err := scripts.ExecuteTemplate(&buf, script, data)
|
||||||
|
@ -29,6 +30,11 @@ func Run(script string, data interface{}) ([]byte, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ctx != nil {
|
||||||
|
cmd := exec.CommandContext(ctx, "osascript", "-l", lang)
|
||||||
|
cmd.Stdin = strings.NewReader(script)
|
||||||
|
return cmd.Output()
|
||||||
|
}
|
||||||
cmd := exec.Command("osascript", "-l", lang)
|
cmd := exec.Command("osascript", "-l", lang)
|
||||||
cmd.Stdin = strings.NewReader(script)
|
cmd.Stdin = strings.NewReader(script)
|
||||||
return cmd.Output()
|
return cmd.Output()
|
||||||
|
@ -60,6 +66,7 @@ type Msg struct {
|
||||||
Buttons []string
|
Buttons []string
|
||||||
Cancel int
|
Cancel int
|
||||||
Default int
|
Default int
|
||||||
|
Timeout int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Notify struct {
|
type Notify struct {
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
package zenutil
|
package zenutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,9 +22,16 @@ func init() {
|
||||||
tool = "zenity"
|
tool = "zenity"
|
||||||
}
|
}
|
||||||
|
|
||||||
func Run(args []string) ([]byte, error) {
|
func Run(ctx context.Context, args []string) ([]byte, error) {
|
||||||
if Command && path != "" {
|
if Command && path != "" {
|
||||||
|
if Timeout > 0 {
|
||||||
|
args = append(args, "--timeout", strconv.Itoa(Timeout))
|
||||||
|
}
|
||||||
syscall.Exec(path, append([]string{tool}, args...), os.Environ())
|
syscall.Exec(path, append([]string{tool}, args...), os.Environ())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ctx != nil {
|
||||||
|
return exec.CommandContext(ctx, tool, args...).Output()
|
||||||
|
}
|
||||||
return exec.Command(tool, args...).Output()
|
return exec.Command(tool, args...).Output()
|
||||||
}
|
}
|
||||||
|
|
2
msg.go
2
msg.go
|
@ -2,7 +2,7 @@ package zenity
|
||||||
|
|
||||||
// ErrExtraButton is returned by dialog functions when the extra button is
|
// ErrExtraButton is returned by dialog functions when the extra button is
|
||||||
// pressed.
|
// pressed.
|
||||||
const ErrExtraButton = constError("Extra button pressed.")
|
const ErrExtraButton = constError("Extra button pressed")
|
||||||
|
|
||||||
// Question displays the question dialog.
|
// Question displays the question dialog.
|
||||||
//
|
//
|
||||||
|
|
|
@ -8,7 +8,10 @@ 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}
|
data := zenutil.Msg{
|
||||||
|
Text: text,
|
||||||
|
Timeout: zenutil.Timeout,
|
||||||
|
}
|
||||||
dialog := kind == questionKind || opts.icon != 0
|
dialog := kind == questionKind || opts.icon != 0
|
||||||
|
|
||||||
if dialog {
|
if dialog {
|
||||||
|
@ -83,7 +86,7 @@ func message(kind messageKind, text string, options []Option) (bool, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out, err := zenutil.Run("msg", data)
|
out, err := zenutil.Run(opts.ctx, "msg", data)
|
||||||
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 {
|
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ func message(kind messageKind, text string, options []Option) (bool, error) {
|
||||||
args = append(args, "--window-icon=question", "--icon-name=dialog-question")
|
args = append(args, "--window-icon=question", "--icon-name=dialog-question")
|
||||||
}
|
}
|
||||||
|
|
||||||
out, err := zenutil.Run(args)
|
out, err := zenutil.Run(opts.ctx, args)
|
||||||
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 {
|
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 {
|
||||||
if len(out) > 0 && string(out[:len(out)-1]) == opts.extraButton {
|
if len(out) > 0 && string(out[:len(out)-1]) == opts.extraButton {
|
||||||
return false, ErrExtraButton
|
return false, ErrExtraButton
|
||||||
|
|
|
@ -16,7 +16,7 @@ func notify(text string, options []Option) error {
|
||||||
data.Subtitle = text[:i]
|
data.Subtitle = text[:i]
|
||||||
data.Text = text[i+1:]
|
data.Text = text[i+1:]
|
||||||
}
|
}
|
||||||
_, err := zenutil.Run("notify", data)
|
_, err := zenutil.Run(opts.ctx, "notify", data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func notify(text string, options []Option) error {
|
||||||
args = append(args, "--window-icon=question")
|
args = append(args, "--window-icon=question")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := zenutil.Run(args)
|
_, err := zenutil.Run(opts.ctx, args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
12
zenity.go
12
zenity.go
|
@ -10,7 +10,10 @@
|
||||||
// initialization requirements.
|
// initialization requirements.
|
||||||
package zenity
|
package zenity
|
||||||
|
|
||||||
import "image/color"
|
import (
|
||||||
|
"context"
|
||||||
|
"image/color"
|
||||||
|
)
|
||||||
|
|
||||||
type constError string
|
type constError string
|
||||||
|
|
||||||
|
@ -40,6 +43,9 @@ type options struct {
|
||||||
noWrap bool
|
noWrap bool
|
||||||
ellipsize bool
|
ellipsize bool
|
||||||
defaultCancel bool
|
defaultCancel bool
|
||||||
|
|
||||||
|
// Context for timeout
|
||||||
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
// An Option is an argument passed to dialog functions to customize their
|
// An Option is an argument passed to dialog functions to customize their
|
||||||
|
@ -79,3 +85,7 @@ const (
|
||||||
func Icon(icon DialogIcon) Option {
|
func Icon(icon DialogIcon) Option {
|
||||||
return funcOption(func(o *options) { o.icon = icon })
|
return funcOption(func(o *options) { o.icon = icon })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Context(ctx context.Context) Option {
|
||||||
|
return funcOption(func(o *options) { o.ctx = ctx })
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue