Canceled error.

This commit is contained in:
Nuno Cruces 2021-04-29 16:05:28 +01:00
parent 7b98716a20
commit 8db7926394
33 changed files with 139 additions and 194 deletions

View file

@ -100,27 +100,27 @@ func main() {
switch {
case errorDlg:
okResult(zenity.Error(text, opts...))
errResult(zenity.Error(text, opts...))
case infoDlg:
okResult(zenity.Info(text, opts...))
errResult(zenity.Info(text, opts...))
case warningDlg:
okResult(zenity.Warning(text, opts...))
errResult(zenity.Warning(text, opts...))
case questionDlg:
okResult(zenity.Question(text, opts...))
errResult(zenity.Question(text, opts...))
case entryDlg:
strOKResult(zenity.Entry(text, opts...))
strResult(zenity.Entry(text, opts...))
case listDlg:
if multiple {
listResult(zenity.ListMultiple(text, flag.Args(), opts...))
lstResult(zenity.ListMultiple(text, flag.Args(), opts...))
} else {
strOKResult(zenity.List(text, flag.Args(), opts...))
strResult(zenity.List(text, flag.Args(), opts...))
}
case passwordDlg:
_, pw, ok, err := zenity.Password(opts...)
strOKResult(pw, ok, err)
_, pw, err := zenity.Password(opts...)
strResult(pw, err)
case fileSelectionDlg:
switch {
@ -129,11 +129,11 @@ func main() {
case save:
strResult(egestPath(zenity.SelectFileSave(opts...)))
case multiple:
listResult(egestPaths(zenity.SelectFileMutiple(opts...)))
lstResult(egestPaths(zenity.SelectFileMutiple(opts...)))
}
case colorSelectionDlg:
colorResult(zenity.SelectColor(opts...))
colResult(zenity.SelectColor(opts...))
case notification:
errResult(zenity.Notify(text, opts...))
@ -395,6 +395,9 @@ func errResult(err error) {
if os.IsTimeout(err) {
os.Exit(5)
}
if err == zenity.ErrCanceled {
os.Exit(1)
}
if err == zenity.ErrExtraButton {
os.Stdout.WriteString(extraButton)
os.Stdout.WriteString(zenutil.LineBreak)
@ -408,64 +411,33 @@ func errResult(err error) {
os.Exit(0)
}
func okResult(ok bool, err error) {
if err != nil {
errResult(err)
}
if ok {
os.Exit(0)
}
os.Exit(1)
}
func strResult(s string, err error) {
if err != nil {
errResult(err)
}
if s == "" {
os.Exit(1)
}
os.Stdout.WriteString(s)
os.Stdout.WriteString(zenutil.LineBreak)
os.Exit(0)
}
func listResult(l []string, err error) {
func lstResult(l []string, err error) {
if err != nil {
errResult(err)
}
if l == nil {
os.Exit(1)
}
os.Stdout.WriteString(strings.Join(l, zenutil.Separator))
os.Stdout.WriteString(zenutil.LineBreak)
os.Exit(0)
}
func colorResult(c color.Color, err error) {
func colResult(c color.Color, err error) {
if err != nil {
errResult(err)
}
if c == nil {
os.Exit(1)
}
os.Stdout.WriteString(zenutil.UnparseColor(c))
os.Stdout.WriteString(zenutil.LineBreak)
os.Exit(0)
}
func strOKResult(s string, ok bool, err error) {
if err != nil {
errResult(err)
}
if !ok {
os.Exit(1)
}
os.Stdout.WriteString(s)
os.Stdout.WriteString(zenutil.LineBreak)
os.Exit(0)
}
func ingestPath(path string) string {
if runtime.GOOS == "windows" && path != "" {
var args []string

View file

@ -4,8 +4,6 @@ import "image/color"
// SelectColor displays the color selection dialog.
//
// Returns nil on cancel.
//
// Valid options: Title, Color, ShowPalette.
func SelectColor(options ...Option) (color.Color, error) {
return selectColor(applyOptions(options))

View file

@ -20,9 +20,9 @@ func selectColor(opts options) (color.Color, error) {
float32(g) / 0xffff,
float32(b) / 0xffff,
})
str, ok, err := strResult(opts, out, err)
if ok {
return zenutil.ParseColor(str), nil
}
str, err := strResult(opts, out, err)
if err != nil {
return nil, err
}
return zenutil.ParseColor(str), nil
}

View file

@ -20,9 +20,9 @@ func selectColor(opts options) (color.Color, error) {
}
out, err := zenutil.Run(opts.ctx, args)
str, ok, err := strResult(opts, out, err)
if ok {
return zenutil.ParseColor(str), nil
}
str, err := strResult(opts, out, err)
if err != nil {
return nil, err
}
return zenutil.ParseColor(str), nil
}

View file

@ -2,11 +2,9 @@ package zenity
// Entry displays the text entry dialog.
//
// Returns false on cancel, or ErrExtraButton.
//
// Valid options: Title, Width, Height, OKLabel, CancelLabel, ExtraButton,
// Icon, EntryText, HideText.
func Entry(text string, options ...Option) (string, bool, error) {
func Entry(text string, options ...Option) (string, error) {
return entry(text, applyOptions(options))
}

View file

@ -4,7 +4,7 @@ import (
"github.com/ncruces/zenity/internal/zenutil"
)
func entry(text string, opts options) (string, bool, error) {
func entry(text string, opts options) (string, error) {
var data zenutil.Dialog
data.Text = text
data.Operation = "displayDialog"

View file

@ -19,7 +19,7 @@ func ExampleEntry() {
func TestEntryTimeout(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second/10)
_, _, err := zenity.Entry("", zenity.Context(ctx))
_, err := zenity.Entry("", zenity.Context(ctx))
if !os.IsTimeout(err) {
t.Error("did not timeout:", err)
}
@ -31,7 +31,7 @@ func TestEntryCancel(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
_, _, err := zenity.Entry("", zenity.Context(ctx))
_, err := zenity.Entry("", zenity.Context(ctx))
if !errors.Is(err, context.Canceled) {
t.Error("was not canceled:", err)
}

View file

@ -6,7 +6,7 @@ import (
"github.com/ncruces/zenity/internal/zenutil"
)
func entry(text string, opts options) (string, bool, error) {
func entry(text string, opts options) (string, error) {
args := []string{"--entry", "--text", text}
args = appendTitle(args, opts)
args = appendButtons(args, opts)

View file

@ -4,7 +4,7 @@ import (
"syscall"
)
func entry(text string, opts options) (out string, ok bool, err error) {
func entry(text string, opts options) (out string, err error) {
if opts.title == nil {
opts.title = stringPtr("")
}
@ -49,6 +49,7 @@ func entry(text string, opts options) (out string, ok bool, err error) {
postQuitMessage.Call(0)
case 0x0010: // WM_CLOSE
err = ErrCanceled
destroyWindow.Call(wnd)
case 0x0111: // WM_COMMAND
@ -57,8 +58,8 @@ func entry(text string, opts options) (out string, ok bool, err error) {
return 1
case 1, 6: // IDOK, IDYES
out = getWindowString(editCtl)
ok = true
case 2: // IDCANCEL
err = ErrCanceled
case 7: // IDNO
err = ErrExtraButton
}
@ -76,17 +77,17 @@ func entry(text string, opts options) (out string, ok bool, err error) {
}
if opts.ctx != nil && opts.ctx.Err() != nil {
return "", false, opts.ctx.Err()
return "", opts.ctx.Err()
}
instance, _, err := getModuleHandle.Call(0)
if instance == 0 {
return "", false, err
return "", err
}
cls, err := registerClass(instance, syscall.NewCallback(proc))
if cls == 0 {
return "", false, err
return "", err
}
defer unregisterClass.Call(cls, instance)
@ -145,13 +146,13 @@ func entry(text string, opts options) (out string, ok bool, err error) {
}
// set default values
out, ok, err = "", false, nil
out, err = "", nil
if err := messageLoop(wnd); err != nil {
return "", false, err
return "", err
}
if opts.ctx != nil && opts.ctx.Err() != nil {
return "", false, opts.ctx.Err()
return "", opts.ctx.Err()
}
return out, ok, err
return out, err
}

View file

@ -8,8 +8,6 @@ import (
// SelectFile displays the file selection dialog.
//
// Returns an empty string on cancel.
//
// Valid options: Title, Directory, Filename, ShowHidden, FileFilter(s).
func SelectFile(options ...Option) (string, error) {
return selectFile(applyOptions(options))
@ -17,8 +15,6 @@ func SelectFile(options ...Option) (string, error) {
// SelectFileMutiple displays the multiple file selection dialog.
//
// Returns a nil slice on cancel.
//
// Valid options: Title, Directory, Filename, ShowHidden, FileFilter(s).
func SelectFileMutiple(options ...Option) ([]string, error) {
return selectFileMutiple(applyOptions(options))
@ -26,8 +22,6 @@ func SelectFileMutiple(options ...Option) ([]string, error) {
// SelectFileSave displays the save file selection dialog.
//
// Returns an empty string on cancel.
//
// Valid options: Title, Filename, ConfirmOverwrite, ConfirmCreate, ShowHidden,
// FileFilter(s).
func SelectFileSave(options ...Option) (string, error) {

View file

@ -18,8 +18,7 @@ func selectFile(opts options) (string, error) {
}
out, err := zenutil.Run(opts.ctx, "file", data)
str, _, err := strResult(opts, out, err)
return str, err
return strResult(opts, out, err)
}
func selectFileMutiple(opts options) ([]string, error) {
@ -54,6 +53,5 @@ func selectFileSave(opts options) (string, error) {
}
out, err := zenutil.Run(opts.ctx, "file", data)
str, _, err := strResult(opts, out, err)
return str, err
return strResult(opts, out, err)
}

View file

@ -14,8 +14,7 @@ func selectFile(opts options) (string, error) {
args = appendFileArgs(args, opts)
out, err := zenutil.Run(opts.ctx, args)
str, _, err := strResult(opts, out, err)
return str, err
return strResult(opts, out, err)
}
func selectFileMutiple(opts options) ([]string, error) {
@ -33,8 +32,7 @@ func selectFileSave(opts options) (string, error) {
args = appendFileArgs(args, opts)
out, err := zenutil.Run(opts.ctx, args)
str, _, err := strResult(opts, out, err)
return str, err
return strResult(opts, out, err)
}
func initFilters(filters []FileFilter) []string {

View file

@ -251,7 +251,7 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
return "", nil, opts.ctx.Err()
}
if hr == 0x800704c7 { // ERROR_CANCELLED
return "", nil, nil
return "", nil, ErrCanceled
}
if int32(hr) < 0 {
return "", nil, syscall.Errno(hr)
@ -335,7 +335,7 @@ func browseForFolder(opts options) (string, []string, error) {
return "", nil, opts.ctx.Err()
}
if ptr == 0 {
return "", nil, nil
return "", nil, ErrCanceled
}
defer coTaskMemFree.Call(ptr)

View file

@ -51,7 +51,7 @@ func Run(ctx context.Context, script string, data interface{}) ([]byte, error) {
}
// RunProgress is internal.
func RunProgress(ctx context.Context, max int, env []string) (m *progressDialog, err error) {
func RunProgress(ctx context.Context, max int, env []string) (*progressDialog, error) {
t, err := ioutil.TempDir("", "")
if err != nil {
return nil, err
@ -98,14 +98,14 @@ func RunProgress(ctx context.Context, max int, env []string) (m *progressDialog,
if err != nil {
return nil, err
}
if err = cmd.Start(); err != nil {
if err := cmd.Start(); err != nil {
return nil, err
}
if ctx == nil {
ctx = context.Background()
}
m = &progressDialog{
dlg := &progressDialog{
done: make(chan struct{}),
lines: make(chan string),
max: max,
@ -115,8 +115,8 @@ func RunProgress(ctx context.Context, max int, env []string) (m *progressDialog,
if cerr := ctx.Err(); cerr != nil {
err = cerr
}
m.err = err
close(m.done)
dlg.err = err
close(dlg.done)
os.RemoveAll(t)
}()
go func() {
@ -124,7 +124,7 @@ func RunProgress(ctx context.Context, max int, env []string) (m *progressDialog,
for {
var line string
select {
case s, ok := <-m.lines:
case s, ok := <-dlg.lines:
if !ok {
return
}
@ -138,7 +138,7 @@ func RunProgress(ctx context.Context, max int, env []string) (m *progressDialog,
}
}
}()
return
return dlg, nil
}
// Dialog is internal.

View file

@ -14,37 +14,37 @@ type progressDialog struct {
max int
}
func (m *progressDialog) send(line string) error {
func (d *progressDialog) send(line string) error {
select {
case m.lines <- line:
case d.lines <- line:
return nil
case <-m.done:
return m.err
case <-d.done:
return d.err
}
}
func (m *progressDialog) Close() error {
close(m.lines)
<-m.done
return m.err
func (d *progressDialog) Close() error {
close(d.lines)
<-d.done
return d.err
}
func (m *progressDialog) Text(text string) error {
return m.send("#" + text)
func (d *progressDialog) Text(text string) error {
return d.send("#" + text)
}
func (m *progressDialog) Value(value int) error {
if m.percent {
return m.send(strconv.FormatFloat(100*float64(value)/float64(m.max), 'f', -1, 64))
func (d *progressDialog) Value(value int) error {
if d.percent {
return d.send(strconv.FormatFloat(100*float64(value)/float64(d.max), 'f', -1, 64))
} else {
return m.send(strconv.Itoa(value))
return d.send(strconv.Itoa(value))
}
}
func (m *progressDialog) MaxValue() int {
return m.max
func (d *progressDialog) MaxValue() int {
return d.max
}
func (m *progressDialog) Done() <-chan struct{} {
return m.done
func (d *progressDialog) Done() <-chan struct{} {
return d.done
}

View file

@ -42,7 +42,7 @@ func Run(ctx context.Context, args []string) ([]byte, error) {
}
// RunProgress is internal.
func RunProgress(ctx context.Context, max int, args []string) (m *progressDialog, err error) {
func RunProgress(ctx context.Context, max int, args []string) (*progressDialog, error) {
if Command && path != "" {
if Timeout > 0 {
args = append(args, "--timeout", strconv.Itoa(Timeout))
@ -55,14 +55,14 @@ func RunProgress(ctx context.Context, max int, args []string) (m *progressDialog
if err != nil {
return nil, err
}
if err = cmd.Start(); err != nil {
if err := cmd.Start(); err != nil {
return nil, err
}
if ctx == nil {
ctx = context.Background()
}
m = &progressDialog{
dlg := &progressDialog{
done: make(chan struct{}),
lines: make(chan string),
percent: true,
@ -71,7 +71,7 @@ func RunProgress(ctx context.Context, max int, args []string) (m *progressDialog
go func() {
err := cmd.Wait()
select {
case _, ok := <-m.lines:
case _, ok := <-dlg.lines:
if !ok {
err = nil
}
@ -80,15 +80,15 @@ func RunProgress(ctx context.Context, max int, args []string) (m *progressDialog
if cerr := ctx.Err(); cerr != nil {
err = cerr
}
m.err = err
close(m.done)
dlg.err = err
close(dlg.done)
}()
go func() {
defer cmd.Process.Signal(syscall.SIGTERM)
for {
var line string
select {
case s, ok := <-m.lines:
case s, ok := <-dlg.lines:
if !ok {
return
}
@ -101,5 +101,5 @@ func RunProgress(ctx context.Context, max int, args []string) (m *progressDialog
}
}
}()
return
return dlg, nil
}

12
list.go
View file

@ -2,25 +2,19 @@ package zenity
// List displays the list dialog.
//
// Returns false on cancel, or ErrExtraButton.
//
// Valid options: Title, Width, Height, OKLabel, CancelLabel, ExtraButton,
// Icon, DefaultItems, DisallowEmpty.
func List(text string, items []string, options ...Option) (string, bool, error) {
func List(text string, items []string, options ...Option) (string, error) {
return list(text, items, applyOptions(options))
}
// ListItems displays the list dialog.
//
// Returns false on cancel, or ErrExtraButton.
func ListItems(text string, items ...string) (string, bool, error) {
func ListItems(text string, items ...string) (string, error) {
return List(text, items)
}
// ListMultiple displays the list dialog, allowing multiple items to be selected.
//
// Returns a nil slice on cancel, or ErrExtraButton.
//
// Valid options: Title, Width, Height, OKLabel, CancelLabel, ExtraButton,
// Icon, DefaultItems, DisallowEmpty.
func ListMultiple(text string, items []string, options ...Option) ([]string, error) {
@ -28,8 +22,6 @@ func ListMultiple(text string, items []string, options ...Option) ([]string, err
}
// ListMultipleItems displays the list dialog, allowing multiple items to be selected.
//
// Returns a nil slice on cancel, or ErrExtraButton.
func ListMultipleItems(text string, items ...string) ([]string, error) {
return ListMultiple(text, items)
}

View file

@ -4,7 +4,7 @@ import (
"github.com/ncruces/zenity/internal/zenutil"
)
func list(text string, items []string, opts options) (string, bool, error) {
func list(text string, items []string, opts options) (string, error) {
var data zenutil.List
data.Items = items
data.Options.Prompt = &text

View file

@ -47,7 +47,7 @@ func ExampleListMultipleItems() {
func TestListTimeout(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second/10)
_, _, err := zenity.List("", nil, zenity.Context(ctx))
_, err := zenity.List("", nil, zenity.Context(ctx))
if !os.IsTimeout(err) {
t.Error("did not timeout:", err)
}
@ -59,7 +59,7 @@ func TestListCancel(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
_, _, err := zenity.List("", nil, zenity.Context(ctx))
_, err := zenity.List("", nil, zenity.Context(ctx))
if !errors.Is(err, context.Canceled) {
t.Error("was not canceled:", err)
}

View file

@ -6,7 +6,7 @@ import (
"github.com/ncruces/zenity/internal/zenutil"
)
func list(text string, items []string, opts options) (string, bool, error) {
func list(text string, items []string, opts options) (string, error) {
args := []string{"--list", "--column=", "--hide-header", "--text", text}
args = appendTitle(args, opts)
args = appendButtons(args, opts)

View file

@ -5,12 +5,12 @@ import (
"unsafe"
)
func list(text string, items []string, opts options) (string, bool, error) {
func list(text string, items []string, opts options) (string, error) {
items, err := listDlg(text, items, false, opts)
if len(items) == 1 {
return items[0], true, err
return items[0], err
}
return "", false, err
return "", err
}
func listMultiple(text string, items []string, opts options) ([]string, error) {
@ -62,6 +62,7 @@ func listDlg(text string, items []string, multiple bool, opts options) (out []st
postQuitMessage.Call(0)
case 0x0010: // WM_CLOSE
err = ErrCanceled
destroyWindow.Call(wnd)
case 0x0111: // WM_COMMAND
@ -88,6 +89,7 @@ func listDlg(text string, items []string, multiple bool, opts options) (out []st
}
}
case 2: // IDCANCEL
err = ErrCanceled
case 7: // IDNO
err = ErrExtraButton
}

20
msg.go
View file

@ -1,46 +1,34 @@
package zenity
// ErrExtraButton is returned by dialog functions when the extra button is
// pressed.
const ErrExtraButton = stringErr("extra button pressed")
// Question displays the question dialog.
//
// Returns true on OK, false on Cancel, or ErrExtraButton.
//
// Valid options: Title, Width, Height, OKLabel, CancelLabel, ExtraButton,
// Icon, NoWrap, Ellipsize, DefaultCancel.
func Question(text string, options ...Option) (bool, error) {
func Question(text string, options ...Option) error {
return message(questionKind, text, applyOptions(options))
}
// Info displays the info dialog.
//
// Returns true on OK, false on dismiss, or ErrExtraButton.
//
// Valid options: Title, Width, Height, OKLabel, ExtraButton, Icon,
// NoWrap, Ellipsize.
func Info(text string, options ...Option) (bool, error) {
func Info(text string, options ...Option) error {
return message(infoKind, text, applyOptions(options))
}
// Warning displays the warning dialog.
//
// Returns true on OK, false on dismiss, or ErrExtraButton.
//
// Valid options: Title, Width, Height, OKLabel, ExtraButton, Icon,
// NoWrap, Ellipsize.
func Warning(text string, options ...Option) (bool, error) {
func Warning(text string, options ...Option) error {
return message(warningKind, text, applyOptions(options))
}
// Error displays the error dialog.
//
// Returns true on OK, false on dismiss, or ErrExtraButton.
//
// Valid options: Title, Width, Height, OKLabel, ExtraButton, Icon,
// NoWrap, Ellipsize.
func Error(text string, options ...Option) (bool, error) {
func Error(text string, options ...Option) error {
return message(errorKind, text, applyOptions(options))
}

View file

@ -4,7 +4,7 @@ import (
"github.com/ncruces/zenity/internal/zenutil"
)
func message(kind messageKind, text string, opts options) (bool, error) {
func message(kind messageKind, text string, opts options) error {
var data zenutil.Dialog
data.Text = text
data.Options.Timeout = zenutil.Timeout
@ -33,6 +33,6 @@ func message(kind messageKind, text string, opts options) (bool, error) {
data.SetButtons(getButtons(dialog, kind == questionKind, opts))
out, err := zenutil.Run(opts.ctx, "dialog", data)
_, ok, err := strResult(opts, out, err)
return ok, err
_, err = strResult(opts, out, err)
return err
}

View file

@ -38,7 +38,7 @@ func ExampleQuestion() {
// Output:
}
var msgFuncs = []func(string, ...zenity.Option) (bool, error){
var msgFuncs = []func(string, ...zenity.Option) error{
zenity.Error,
zenity.Info,
zenity.Warning,
@ -49,7 +49,7 @@ func TestMessageTimeout(t *testing.T) {
for _, f := range msgFuncs {
ctx, cancel := context.WithTimeout(context.Background(), time.Second/10)
_, err := f("text", zenity.Context(ctx))
err := f("text", zenity.Context(ctx))
if !os.IsTimeout(err) {
t.Error("did not timeout:", err)
}
@ -63,7 +63,7 @@ func TestMessageCancel(t *testing.T) {
cancel()
for _, f := range msgFuncs {
_, err := f("text", zenity.Context(ctx))
err := f("text", zenity.Context(ctx))
if !errors.Is(err, context.Canceled) {
t.Error("was not canceled:", err)
}

View file

@ -6,7 +6,7 @@ import (
"github.com/ncruces/zenity/internal/zenutil"
)
func message(kind messageKind, text string, opts options) (bool, error) {
func message(kind messageKind, text string, opts options) error {
args := []string{"--text", text, "--no-markup"}
switch kind {
case questionKind:
@ -47,6 +47,6 @@ func message(kind messageKind, text string, opts options) (bool, error) {
}
out, err := zenutil.Run(opts.ctx, args)
_, ok, err := strResult(opts, out, err)
return ok, err
_, err = strResult(opts, out, err)
return err
}

View file

@ -12,7 +12,7 @@ var (
getDlgCtrlID = user32.NewProc("GetDlgCtrlID")
)
func message(kind messageKind, text string, opts options) (bool, error) {
func message(kind messageKind, text string, opts options) error {
var flags uintptr
switch {
@ -48,7 +48,7 @@ func message(kind messageKind, text string, opts options) (bool, error) {
if opts.ctx != nil || opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil {
unhook, err := hookMessageLabels(kind, opts)
if err != nil {
return false, err
return err
}
defer unhook()
}
@ -62,17 +62,17 @@ func message(kind messageKind, text string, opts options) (bool, error) {
s, _, err := messageBox.Call(0, strptr(text), title, flags)
if opts.ctx != nil && opts.ctx.Err() != nil {
return false, opts.ctx.Err()
return opts.ctx.Err()
}
switch s {
case 1, 6: // IDOK, IDYES
return true, nil
return nil
case 2: // IDCANCEL
return false, nil
return ErrCanceled
case 7: // IDNO
return false, ErrExtraButton
return ErrExtraButton
default:
return false, err
return err
}
}
@ -89,11 +89,7 @@ func hookMessageLabels(kind messageKind, opts options) (unhook context.CancelFun
case 1, 6: // IDOK, IDYES
text = opts.okLabel
case 2: // IDCANCEL
if kind == questionKind {
text = opts.cancelLabel
} else {
text = opts.okLabel
}
case 7: // IDNO
text = opts.extraButton
}

4
pwd.go
View file

@ -2,10 +2,8 @@ package zenity
// Password displays the password dialog.
//
// Returns false on cancel, or ErrExtraButton.
//
// Valid options: Title, OKLabel, CancelLabel, ExtraButton, Icon, Username.
func Password(options ...Option) (usr string, pw string, ok bool, err error) {
func Password(options ...Option) (usr string, pw string, err error) {
return password(applyOptions(options))
}

View file

@ -2,8 +2,8 @@
package zenity
func password(opts options) (string, string, bool, error) {
func password(opts options) (string, string, error) {
opts.hideText = true
str, ok, err := entry("Password:", opts)
return "", str, ok, err
str, err := entry("Password:", opts)
return "", str, err
}

View file

@ -18,7 +18,7 @@ func ExamplePassword() {
func TestPasswordTimeout(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second/10)
_, _, _, err := zenity.Password(zenity.Context(ctx))
_, _, err := zenity.Password(zenity.Context(ctx))
if !os.IsTimeout(err) {
t.Error("did not timeout:", err)
}
@ -30,7 +30,7 @@ func TestPasswordCancel(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
_, _, _, err := zenity.Password(zenity.Context(ctx))
_, _, err := zenity.Password(zenity.Context(ctx))
if !errors.Is(err, context.Canceled) {
t.Error("was not canceled:", err)
}

View file

@ -8,7 +8,7 @@ import (
"github.com/ncruces/zenity/internal/zenutil"
)
func password(opts options) (string, string, bool, error) {
func password(opts options) (string, string, error) {
args := []string{"--password"}
args = appendTitle(args, opts)
args = appendButtons(args, opts)
@ -17,11 +17,11 @@ func password(opts options) (string, string, bool, error) {
}
out, err := zenutil.Run(opts.ctx, args)
str, ok, err := strResult(opts, out, err)
if ok && opts.username {
str, err := strResult(opts, out, err)
if err == nil && opts.username {
if split := strings.SplitN(string(out), "|", 2); len(split) == 2 {
return split[0], split[1], true, nil
return split[0], split[1], nil
}
}
return "", str, ok, err
return "", str, err
}

View file

@ -55,23 +55,23 @@ func appendIcon(args []string, opts options) []string {
return args
}
func strResult(opts options, out []byte, err error) (string, bool, error) {
func strResult(opts options, out []byte, err error) (string, error) {
out = bytes.TrimSuffix(out, []byte{'\n'})
if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 1 {
if opts.extraButton != nil && *opts.extraButton == string(out) {
return "", false, ErrExtraButton
return "", ErrExtraButton
}
return "", false, nil
return "", ErrCanceled
}
if err != nil {
return "", false, err
return "", err
}
return string(out), true, nil
return string(out), nil
}
func lstResult(opts options, out []byte, err error) ([]string, error) {
str, ok, err := strResult(opts, out, err)
if ok {
str, err := strResult(opts, out, err)
if err == nil {
return strings.Split(str, zenutil.Separator), nil
}
return nil, err

View file

@ -137,7 +137,7 @@ func setup() context.CancelFunc {
func commDlgError() error {
s, _, _ := commDlgExtendedError.Call()
if s == 0 {
return nil
return ErrCanceled
} else {
return fmt.Errorf("Common Dialog error: %x", s)
}

View file

@ -21,6 +21,16 @@ func (e stringErr) Error() string { return string(e) }
func stringPtr(s string) *string { return &s }
// ErrCanceled is returned when the cancel button is pressed,
// or window functions are used to close the dialog.
const ErrCanceled = stringErr("dialog canceled")
// ErrExtraButton is returned when the extra button is pressed.
const ErrExtraButton = stringErr("extra button pressed")
// ErrUnsupported is returned when a combination of options is not supported.
const ErrUnsupported = stringErr("unsupported option")
type options struct {
// General options
title *string