diff --git a/cmd/zenity/main.go b/cmd/zenity/main.go index 974ae9d..9b4ff2a 100644 --- a/cmd/zenity/main.go +++ b/cmd/zenity/main.go @@ -24,6 +24,7 @@ const ( var ( // Application Options notification bool + entryDlg bool errorDlg bool infoDlg bool warningDlg bool @@ -35,9 +36,13 @@ var ( title string width uint height uint + text string + + // Entry options + entryText string + hideText bool // Message options - text string icon string okLabel string cancelLabel string @@ -89,6 +94,9 @@ func main() { case notification: errResult(zenity.Notify(text, opts...)) + case entryDlg: + strResult(zenity.Entry(text, opts...)) + case errorDlg: okResult(zenity.Error(text, opts...)) case infoDlg: @@ -118,6 +126,7 @@ func main() { func setupFlags() { // Application Options flag.BoolVar(¬ification, "notification", false, "Display notification") + flag.BoolVar(&entryDlg, "entry", false, "Display text entry dialog") flag.BoolVar(&errorDlg, "error", false, "Display error dialog") flag.BoolVar(&infoDlg, "info", false, "Display info dialog") flag.BoolVar(&warningDlg, "warning", false, "Display warning dialog") @@ -130,9 +139,13 @@ func setupFlags() { flag.StringVar(&icon, "window-icon", "", "Set the window `icon` (error, info, question, warning)") flag.UintVar(&width, "width", 0, "Set the `width`") flag.UintVar(&height, "height", 0, "Set the `height`") + flag.StringVar(&text, "text", "", "Set the dialog `text`") + + // Entry options + flag.StringVar(&entryText, "entry-text", "", "Set the entry `text`") + flag.BoolVar(&hideText, "hide-text", false, "Hide the entry text") // Message options - flag.StringVar(&text, "text", "", "Set the dialog `text`") flag.StringVar(&icon, "icon-name", "", "Set the dialog `icon` (dialog-error, dialog-information, dialog-question, dialog-warning)") flag.StringVar(&okLabel, "ok-label", "", "Set the label of the OK button") flag.StringVar(&cancelLabel, "cancel-label", "", "Set the label of the Cancel button") @@ -179,6 +192,9 @@ func validateFlags() { if notification { n++ } + if entryDlg { + n++ + } if errorDlg { n++ } @@ -213,6 +229,11 @@ func loadFlags() []zenity.Option { } } switch { + case entryDlg: + setDefault(&title, "Add a new entry") + setDefault(&text, "Enter new text:") + setDefault(&okLabel, "OK") + setDefault(&cancelLabel, "Cancel") case errorDlg: setDefault(&title, "Error") setDefault(&icon, "dialog-error") @@ -246,6 +267,12 @@ func loadFlags() []zenity.Option { opts = append(opts, zenity.Width(width)) opts = append(opts, zenity.Height(height)) + // Entry options + opts = append(opts, zenity.EntryText(entryText)) + if hideText { + opts = append(opts, zenity.HideText()) + } + // Message options var ico zenity.DialogIcon diff --git a/entry.go b/entry.go new file mode 100644 index 0000000..06fdbd2 --- /dev/null +++ b/entry.go @@ -0,0 +1,20 @@ +package zenity + +// Entry displays the text entry dialog. +// +// Returns nil on cancel. +// +// Valid options: Title, Text, EntryText, HideText. +func Entry(text string, options ...Option) (string, error) { + return entry(text, applyOptions(options)) +} + +// EntryText returns an Option to set the entry text. +func EntryText(text string) Option { + return funcOption(func(o *options) { o.entryText = text }) +} + +// HideText returns an Option to hide the entry text. +func HideText() Option { + return funcOption(func(o *options) { o.hideText = true }) +} diff --git a/entry_darwin.go b/entry_darwin.go new file mode 100644 index 0000000..60a68a6 --- /dev/null +++ b/entry_darwin.go @@ -0,0 +1,58 @@ +package zenity + +import ( + "os/exec" + + "github.com/ncruces/zenity/internal/zenutil" +) + +func entry(text string, opts options) (string, error) { + var data zenutil.Dialog + data.Text = text + data.Operation = "displayDialog" + data.Options.Title = opts.title + data.Options.Answer = &opts.entryText + data.Options.Hidden = opts.hideText + data.Options.Timeout = zenutil.Timeout + + switch opts.icon { + case ErrorIcon: + data.Options.Icon = "stop" + case WarningIcon: + data.Options.Icon = "caution" + case InfoIcon, QuestionIcon: + data.Options.Icon = "note" + } + + if opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil { + if opts.okLabel == nil { + opts.okLabel = stringPtr("OK") + } + if opts.cancelLabel == nil { + opts.cancelLabel = stringPtr("Cancel") + } + if opts.extraButton == nil { + data.Options.Buttons = []string{*opts.cancelLabel, *opts.okLabel} + data.Options.Default = 2 + data.Options.Cancel = 1 + } else { + data.Options.Buttons = []string{*opts.extraButton, *opts.cancelLabel, *opts.okLabel} + data.Options.Default = 3 + data.Options.Cancel = 2 + } + data.Extra = opts.extraButton + } + + out, err := zenutil.Run(opts.ctx, "dialog", data) + if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 { + if len(out) > 0 && opts.extraButton != nil && + string(out[:len(out)-1]) == *opts.extraButton { + return "", ErrExtraButton + } + return "", nil + } + if err != nil { + return "", err + } + return string(out[:len(out)-1]), err +} diff --git a/internal/zenutil/osa_generated.go b/internal/zenutil/osa_generated.go index 555a84b..7258dd8 100644 --- a/internal/zenutil/osa_generated.go +++ b/internal/zenutil/osa_generated.go @@ -17,14 +17,7 @@ app.activate() var res=app.chooseColor({defaultColor:{{json .}}}) {"rgb("+res.map(x=>Math.round(x*255))+")"} {{- end}} -{{define "file" -}} -var app=Application.currentApplication() -app.includeStandardAdditions=true -app.activate() -var res=app.{{.Operation}}({{json .Options}}) -if(Array.isArray(res)){res.join({{json .Separator}})}else{res.toString()} -{{- end}} -{{define "msg" -}} +{{define "dialog" -}} var app=Application.currentApplication() app.includeStandardAdditions=true app.activate() @@ -34,7 +27,14 @@ var res=app.{{.Operation}}({{json .Text}},{{json .Options}}) if(res.gaveUp){$.exit(5)} if(res.buttonReturned==={{json .Extra}}){$.puts(res.buttonReturned) $.exit(1)} -void 0 +res.textReturned +{{- end}} +{{define "file" -}} +var app=Application.currentApplication() +app.includeStandardAdditions=true +app.activate() +var res=app.{{.Operation}}({{json .Options}}) +if(Array.isArray(res)){res.join({{json .Separator}})}else{res.toString()} {{- end}} {{define "notify" -}} var app=Application.currentApplication() diff --git a/internal/zenutil/osascripts/msg.gojs b/internal/zenutil/osascripts/dialog.gojs similarity index 94% rename from internal/zenutil/osascripts/msg.gojs rename to internal/zenutil/osascripts/dialog.gojs index aca3d83..c366d23 100644 --- a/internal/zenutil/osascripts/msg.gojs +++ b/internal/zenutil/osascripts/dialog.gojs @@ -12,4 +12,5 @@ if (res.gaveUp) { if (res.buttonReturned === {{json .Extra}}) { $.puts(res.buttonReturned) $.exit(1) -} \ No newline at end of file +} +res.textReturned \ No newline at end of file diff --git a/internal/zenutil/run_darwin.go b/internal/zenutil/run_darwin.go index 3764d5a..e84f134 100644 --- a/internal/zenutil/run_darwin.go +++ b/internal/zenutil/run_darwin.go @@ -64,18 +64,20 @@ type FileOptions struct { Invisibles bool `json:"invisibles,omitempty"` } -// Msg is internal. -type Msg struct { +// Dialog is internal. +type Dialog struct { Operation string Text string Extra *string - Options MsgOptions + Options DialogOptions } -// MsgOptions is internal. -type MsgOptions struct { +// DialogOptions is internal. +type DialogOptions struct { Message string `json:"message,omitempty"` As string `json:"as,omitempty"` + Answer *string `json:"defaultAnswer,omitempty"` + Hidden bool `json:"hiddenAnswer,omitempty"` Title *string `json:"withTitle,omitempty"` Icon string `json:"withIcon,omitempty"` Buttons []string `json:"buttons,omitempty"` diff --git a/msg_darwin.go b/msg_darwin.go index 1e7642e..47da5e6 100644 --- a/msg_darwin.go +++ b/msg_darwin.go @@ -7,7 +7,7 @@ import ( ) func message(kind messageKind, text string, opts options) (bool, error) { - var data zenutil.Msg + var data zenutil.Dialog data.Text = text data.Options.Timeout = zenutil.Timeout @@ -99,12 +99,12 @@ func message(kind messageKind, text string, opts options) (bool, error) { } } - out, err := zenutil.Run(opts.ctx, "msg", data) - if len(out) > 0 && opts.extraButton != nil && - string(out[:len(out)-1]) == *opts.extraButton { - return false, ErrExtraButton - } + out, err := zenutil.Run(opts.ctx, "dialog", data) if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 { + if len(out) > 0 && opts.extraButton != nil && + string(out[:len(out)-1]) == *opts.extraButton { + return false, ErrExtraButton + } return false, nil } if err != nil { diff --git a/msg_unix.go b/msg_unix.go index 79d0c78..bc9d3dc 100644 --- a/msg_unix.go +++ b/msg_unix.go @@ -65,11 +65,11 @@ func message(kind messageKind, text string, opts options) (bool, error) { } out, err := zenutil.Run(opts.ctx, args) - if len(out) > 0 && opts.extraButton != nil && - string(out[:len(out)-1]) == *opts.extraButton { - return false, ErrExtraButton - } if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 { + if len(out) > 0 && opts.extraButton != nil && + string(out[:len(out)-1]) == *opts.extraButton { + return false, ErrExtraButton + } return false, nil } if err != nil { diff --git a/zenity.go b/zenity.go index fce49cc..23e3264 100644 --- a/zenity.go +++ b/zenity.go @@ -48,6 +48,10 @@ type options struct { ellipsize bool defaultCancel bool + // Entry options + entryText string + hideText bool + // Context for timeout ctx context.Context }