diff --git a/cmd/zenity/main.go b/cmd/zenity/main.go index 9bf3e6e..a0290b8 100644 --- a/cmd/zenity/main.go +++ b/cmd/zenity/main.go @@ -49,8 +49,8 @@ var ( fileFilters FileFilters // Color selection options - initColor string - palette bool + defaultColor string + showPalette bool // Windows specific options cygpath bool @@ -130,8 +130,8 @@ func setupFlags() { flag.Var(&fileFilters, "file-filter", "Set a filename filter (NAME | PATTERN1 PATTERN2 ...)") // Color selection options - flag.StringVar(&initColor, "color", "", "Set the color") - flag.BoolVar(&palette, "show-palette", false, "Show the palette") + flag.StringVar(&defaultColor, "color", "", "Set the color") + flag.BoolVar(&showPalette, "show-palette", false, "Show the palette") // Windows specific options if runtime.GOOS == "windows" { @@ -203,7 +203,7 @@ func loadFlags() []zenity.Option { // File selection options - options = append(options, fileFilters.Build()) + options = append(options, fileFilters) if filename != "" { options = append(options, zenity.Filename(ingestPath(filename))) } @@ -224,10 +224,10 @@ func loadFlags() []zenity.Option { // Color selection options - if initColor != "" { - options = append(options, zenity.Color(zenutil.ParseColor(initColor))) + if defaultColor != "" { + options = append(options, zenity.Color(zenutil.ParseColor(defaultColor))) } - if palette { + if showPalette { options = append(options, zenity.ShowPalette()) } diff --git a/color.go b/color.go index 9ce00cf..5b40397 100644 --- a/color.go +++ b/color.go @@ -13,10 +13,10 @@ func SelectColor(options ...Option) (color.Color, error) { // Color returns an Option to set the color. func Color(c color.Color) Option { - return func(o *options) { o.color = c } + return funcOption(func(o *options) { o.color = c }) } // ShowPalette returns an Option to show the palette. func ShowPalette() Option { - return func(o *options) { o.palette = true } + return funcOption(func(o *options) { o.showPalette = true }) } diff --git a/color_darwin.go b/color_darwin.go index 461a8f4..64fd225 100644 --- a/color_darwin.go +++ b/color_darwin.go @@ -8,7 +8,7 @@ import ( ) func selectColor(options ...Option) (color.Color, error) { - opts := optsParse(options) + opts := applyOptions(options) var data zenutil.Color if opts.color != nil { diff --git a/color_unix.go b/color_unix.go index 0225122..6354b4f 100644 --- a/color_unix.go +++ b/color_unix.go @@ -10,7 +10,7 @@ import ( ) func selectColor(options ...Option) (color.Color, error) { - opts := optsParse(options) + opts := applyOptions(options) args := []string{"--color-selection"} @@ -20,7 +20,7 @@ func selectColor(options ...Option) (color.Color, error) { if opts.color != nil { args = append(args, "--color", zenutil.UnparseColor(opts.color)) } - if opts.palette { + if opts.showPalette { args = append(args, "--show-palette") } diff --git a/color_windows.go b/color_windows.go index 8999ee3..dd26d78 100644 --- a/color_windows.go +++ b/color_windows.go @@ -21,7 +21,7 @@ func init() { } func selectColor(options ...Option) (color.Color, error) { - opts := optsParse(options) + opts := applyOptions(options) // load custom colors colorsMutex.Lock() @@ -37,7 +37,7 @@ func selectColor(options ...Option) (color.Color, error) { n := color.NRGBAModel.Convert(opts.color).(color.NRGBA) args.RgbResult = uint32(n.R) | (uint32(n.G) << 8) | (uint32(n.B) << 16) } - if opts.palette { + if opts.showPalette { args.Flags |= 4 // CC_PREVENTFULLOPEN } else { args.Flags |= 2 // CC_FULLOPEN diff --git a/file.go b/file.go index 7d502d1..a03a9b1 100644 --- a/file.go +++ b/file.go @@ -39,32 +39,32 @@ func SelectFileSave(options ...Option) (string, error) { // Specifying a file name, makes it the default selected file. // Specifying a directory path, makes it the default dialog location. func Filename(filename string) Option { - return func(o *options) { o.filename = filename } + return funcOption(func(o *options) { o.filename = filename }) } // Directory returns an Option to activate directory-only selection. func Directory() Option { - return func(o *options) { o.directory = true } + return funcOption(func(o *options) { o.directory = true }) } // ConfirmOverwrite returns an Option to confirm file selection if filename // already exists. func ConfirmOverwrite() Option { - return func(o *options) { o.overwrite = true } + return funcOption(func(o *options) { o.confirmOverwrite = true }) } // ConfirmCreate returns an Option to confirm file selection if filename does // not yet exist (Windows only). func ConfirmCreate() Option { - return func(o *options) { o.create = true } + return funcOption(func(o *options) { o.confirmCreate = true }) } // ShowHidden returns an Option to show hidden files (Windows and macOS only). func ShowHidden() Option { - return func(o *options) { o.hidden = true } + return funcOption(func(o *options) { o.showHidden = true }) } -// FileFilter encapsulates a filename filter. +// FileFilter is an Option that sets a filename filter. // // macOS hides filename filters from the user, // and only supports filtering by extension (or "type"). @@ -73,17 +73,15 @@ type FileFilter struct { Patterns []string // filter patterns for the display string } -// Build returns an Option to set a filename filter. -func (f FileFilter) Build() Option { - return func(o *options) { o.filters = append(o.filters, f) } +func (f FileFilter) apply(o *options) { + o.fileFilters = append(o.fileFilters, f) } -// FileFilters is a list of filename filters. +// FileFilters is an Option that sets multiple filename filters. type FileFilters []FileFilter -// Build returns an Option to set filename filters. -func (f FileFilters) Build() Option { - return func(o *options) { o.filters = append(o.filters, f...) } +func (f FileFilters) apply(o *options) { + o.fileFilters = append(o.fileFilters, f...) } func splitDirAndName(path string) (dir, name string) { diff --git a/file_darwin.go b/file_darwin.go index 4c727b4..fb774ff 100644 --- a/file_darwin.go +++ b/file_darwin.go @@ -8,17 +8,17 @@ import ( ) func selectFile(options ...Option) (string, error) { - opts := optsParse(options) + opts := applyOptions(options) data := zenutil.File{ Prompt: opts.title, - Invisibles: opts.hidden, + Invisibles: opts.showHidden, } if opts.directory { data.Operation = "chooseFolder" } else { data.Operation = "chooseFile" - data.Type = initFilters(opts.filters) + data.Type = initFilters(opts.fileFilters) } data.Location, _ = splitDirAndName(opts.filename) @@ -36,11 +36,11 @@ func selectFile(options ...Option) (string, error) { } func selectFileMutiple(options ...Option) ([]string, error) { - opts := optsParse(options) + opts := applyOptions(options) data := zenutil.File{ Prompt: opts.title, - Invisibles: opts.hidden, + Invisibles: opts.showHidden, Multiple: true, Separator: zenutil.Separator, } @@ -48,7 +48,7 @@ func selectFileMutiple(options ...Option) ([]string, error) { data.Operation = "chooseFolder" } else { data.Operation = "chooseFile" - data.Type = initFilters(opts.filters) + data.Type = initFilters(opts.fileFilters) } data.Location, _ = splitDirAndName(opts.filename) @@ -69,7 +69,7 @@ func selectFileMutiple(options ...Option) ([]string, error) { } func selectFileSave(options ...Option) (string, error) { - opts := optsParse(options) + opts := applyOptions(options) data := zenutil.File{ Prompt: opts.title, @@ -78,7 +78,7 @@ func selectFileSave(options ...Option) (string, error) { data.Operation = "chooseFolder" } else { data.Operation = "chooseFileName" - data.Type = initFilters(opts.filters) + data.Type = initFilters(opts.fileFilters) } data.Location, data.Name = splitDirAndName(opts.filename) diff --git a/file_test.go b/file_test.go index 6a48b05..502ac15 100644 --- a/file_test.go +++ b/file_test.go @@ -12,7 +12,7 @@ func ExampleSelectFile() { {"Go files", []string{"*.go"}}, {"Web files", []string{"*.html", "*.js", "*.css"}}, {"Image files", []string{"*.png", "*.gif", "*.ico", "*.jpg", "*.webp"}}, - }.Build()) + }) // Output: } @@ -23,7 +23,7 @@ func ExampleSelectFileMutiple() { {"Go files", []string{"*.go"}}, {"Web files", []string{"*.html", "*.js", "*.css"}}, {"Image files", []string{"*.png", "*.gif", "*.ico", "*.jpg", "*.webp"}}, - }.Build()) + }) // Output: } @@ -35,7 +35,7 @@ func ExampleSelectFileSave() { {"Go files", []string{"*.go"}}, {"Web files", []string{"*.html", "*.js", "*.css"}}, {"Image files", []string{"*.png", "*.gif", "*.ico", "*.jpg", "*.webp"}}, - }.Build()) + }) // Output: } diff --git a/file_unix.go b/file_unix.go index b0f1bfe..4556337 100644 --- a/file_unix.go +++ b/file_unix.go @@ -10,7 +10,7 @@ import ( ) func selectFile(options ...Option) (string, error) { - opts := optsParse(options) + opts := applyOptions(options) args := []string{"--file-selection"} if opts.directory { @@ -22,7 +22,7 @@ func selectFile(options ...Option) (string, error) { if opts.filename != "" { args = append(args, "--filename", opts.filename) } - args = append(args, initFilters(opts.filters)...) + args = append(args, initFilters(opts.fileFilters)...) out, err := zenutil.Run(args) if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 { @@ -38,7 +38,7 @@ func selectFile(options ...Option) (string, error) { } func selectFileMutiple(options ...Option) ([]string, error) { - opts := optsParse(options) + opts := applyOptions(options) args := []string{"--file-selection", "--multiple", "--separator", zenutil.Separator} if opts.directory { @@ -50,7 +50,7 @@ func selectFileMutiple(options ...Option) ([]string, error) { if opts.filename != "" { args = append(args, "--filename", opts.filename) } - args = append(args, initFilters(opts.filters)...) + args = append(args, initFilters(opts.fileFilters)...) out, err := zenutil.Run(args) if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 { @@ -66,7 +66,7 @@ func selectFileMutiple(options ...Option) ([]string, error) { } func selectFileSave(options ...Option) (string, error) { - opts := optsParse(options) + opts := applyOptions(options) args := []string{"--file-selection", "--save"} if opts.directory { @@ -78,10 +78,10 @@ func selectFileSave(options ...Option) (string, error) { if opts.filename != "" { args = append(args, "--filename", opts.filename) } - if opts.overwrite { + if opts.confirmOverwrite { args = append(args, "--confirm-overwrite") } - args = append(args, initFilters(opts.filters)...) + args = append(args, initFilters(opts.fileFilters)...) out, err := zenutil.Run(args) if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 { diff --git a/file_windows.go b/file_windows.go index 12d4096..d91c4df 100644 --- a/file_windows.go +++ b/file_windows.go @@ -18,7 +18,7 @@ var ( ) func selectFile(options ...Option) (string, error) { - opts := optsParse(options) + opts := applyOptions(options) if opts.directory { res, _, err := pickFolders(opts, false) return res, err @@ -31,11 +31,11 @@ func selectFile(options ...Option) (string, error) { if opts.title != "" { args.Title = syscall.StringToUTF16Ptr(opts.title) } - if opts.hidden { + if opts.showHidden { args.Flags |= 0x10000000 // OFN_FORCESHOWHIDDEN } - if opts.filters != nil { - args.Filter = &initFilters(opts.filters)[0] + if opts.fileFilters != nil { + args.Filter = &initFilters(opts.fileFilters)[0] } res := [32768]uint16{} @@ -54,7 +54,7 @@ func selectFile(options ...Option) (string, error) { } func selectFileMutiple(options ...Option) ([]string, error) { - opts := optsParse(options) + opts := applyOptions(options) if opts.directory { _, res, err := pickFolders(opts, true) return res, err @@ -67,11 +67,11 @@ func selectFileMutiple(options ...Option) ([]string, error) { if opts.title != "" { args.Title = syscall.StringToUTF16Ptr(opts.title) } - if opts.hidden { + if opts.showHidden { args.Flags |= 0x10000000 // OFN_FORCESHOWHIDDEN } - if opts.filters != nil { - args.Filter = &initFilters(opts.filters)[0] + if opts.fileFilters != nil { + args.Filter = &initFilters(opts.fileFilters)[0] } res := [32768 + 1024*256]uint16{} @@ -115,7 +115,7 @@ func selectFileMutiple(options ...Option) ([]string, error) { } func selectFileSave(options ...Option) (string, error) { - opts := optsParse(options) + opts := applyOptions(options) if opts.directory { res, _, err := pickFolders(opts, false) return res, err @@ -128,17 +128,17 @@ func selectFileSave(options ...Option) (string, error) { if opts.title != "" { args.Title = syscall.StringToUTF16Ptr(opts.title) } - if opts.overwrite { + if opts.confirmOverwrite { args.Flags |= 0x2 // OFN_OVERWRITEPROMPT } - if opts.create { + if opts.confirmCreate { args.Flags |= 0x2000 // OFN_CREATEPROMPT } - if opts.hidden { + if opts.showHidden { args.Flags |= 0x10000000 // OFN_FORCESHOWHIDDEN } - if opts.filters != nil { - args.Filter = &initFilters(opts.filters)[0] + if opts.fileFilters != nil { + args.Filter = &initFilters(opts.fileFilters)[0] } res := [32768]uint16{} @@ -185,7 +185,7 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error) if multi { flgs |= 0x200 // FOS_ALLOWMULTISELECT } - if opts.hidden { + if opts.showHidden { flgs |= 0x10000000 // FOS_FORCESHOWHIDDEN } hr, _, _ = dialog.Call(dialog.vtbl.SetOptions, uintptr(flgs|0x68)) // FOS_NOCHANGEDIR|FOS_PICKFOLDERS|FOS_FORCEFILESYSTEM diff --git a/msg.go b/msg.go index a370a0c..5c71aa0 100644 --- a/msg.go +++ b/msg.go @@ -63,35 +63,35 @@ const ( // Icon returns an Option to set the dialog icon. func Icon(icon MessageIcon) Option { - return func(o *options) { o.icon = icon } + return funcOption(func(o *options) { o.icon = icon }) } // OKLabel returns an Option to set the label of the OK button. func OKLabel(ok string) Option { - return func(o *options) { o.ok = ok } + return funcOption(func(o *options) { o.okLabel = ok }) } // CancelLabel returns an Option to set the label of the Cancel button. func CancelLabel(cancel string) Option { - return func(o *options) { o.cancel = cancel } + return funcOption(func(o *options) { o.cancelLabel = cancel }) } // ExtraButton returns an Option to add an extra button. func ExtraButton(extra string) Option { - return func(o *options) { o.extra = extra } + return funcOption(func(o *options) { o.extraButton = extra }) } // NoWrap returns an Option to disable enable text wrapping. func NoWrap() Option { - return func(o *options) { o.nowrap = true } + return funcOption(func(o *options) { o.noWrap = true }) } // Ellipsize returns an Option to enable ellipsizing in the dialog text. func Ellipsize() Option { - return func(o *options) { o.ellipsize = true } + return funcOption(func(o *options) { o.ellipsize = true }) } // DefaultCancel returns an Option to give Cancel button focus by default. func DefaultCancel() Option { - return func(o *options) { o.defcancel = true } + return funcOption(func(o *options) { o.defaultCancel = true }) } diff --git a/msg_darwin.go b/msg_darwin.go index 649904b..b377531 100644 --- a/msg_darwin.go +++ b/msg_darwin.go @@ -7,7 +7,7 @@ import ( ) func message(kind messageKind, text string, options []Option) (bool, error) { - opts := optsParse(options) + opts := applyOptions(options) data := zenutil.Msg{Text: text} dialog := kind == questionKind || opts.icon != 0 @@ -42,39 +42,39 @@ func message(kind messageKind, text string, options []Option) (bool, error) { if kind != questionKind { if dialog { - opts.ok = "OK" + opts.okLabel = "OK" } - opts.cancel = "" + opts.cancelLabel = "" } - if opts.ok != "" || opts.cancel != "" || opts.extra != "" { - if opts.ok == "" { - opts.ok = "OK" + if opts.okLabel != "" || opts.cancelLabel != "" || opts.extraButton != "" { + if opts.okLabel == "" { + opts.okLabel = "OK" } - if opts.cancel == "" { - opts.cancel = "Cancel" + if opts.cancelLabel == "" { + opts.cancelLabel = "Cancel" } if kind == questionKind { - if opts.extra == "" { - data.Buttons = []string{opts.cancel, opts.ok} + if opts.extraButton == "" { + data.Buttons = []string{opts.cancelLabel, opts.okLabel} data.Default = 2 data.Cancel = 1 } else { - data.Buttons = []string{opts.extra, opts.cancel, opts.ok} + data.Buttons = []string{opts.extraButton, opts.cancelLabel, opts.okLabel} data.Default = 3 data.Cancel = 2 } } else { - if opts.extra == "" { - data.Buttons = []string{opts.ok} + if opts.extraButton == "" { + data.Buttons = []string{opts.okLabel} data.Default = 1 } else { - data.Buttons = []string{opts.extra, opts.ok} + data.Buttons = []string{opts.extraButton, opts.okLabel} data.Default = 2 } } - data.Extra = opts.extra + data.Extra = opts.extraButton } - if opts.defcancel { + if opts.defaultCancel { if data.Cancel != 0 { data.Default = data.Cancel } @@ -90,7 +90,7 @@ func message(kind messageKind, text string, options []Option) (bool, error) { if err != nil { return false, err } - if len(out) > 0 && string(out[:len(out)-1]) == opts.extra { + if len(out) > 0 && string(out[:len(out)-1]) == opts.extraButton { return false, ErrExtraButton } return true, err diff --git a/msg_unix.go b/msg_unix.go index 1855e3f..25df148 100644 --- a/msg_unix.go +++ b/msg_unix.go @@ -9,7 +9,7 @@ import ( ) func message(kind messageKind, text string, options []Option) (bool, error) { - opts := optsParse(options) + opts := applyOptions(options) var args []string switch kind { @@ -28,22 +28,22 @@ func message(kind messageKind, text string, options []Option) (bool, error) { if opts.title != "" { args = append(args, "--title", opts.title) } - if opts.ok != "" { - args = append(args, "--ok-label", opts.ok) + if opts.okLabel != "" { + args = append(args, "--ok-label", opts.okLabel) } - if opts.cancel != "" { - args = append(args, "--cancel-label", opts.cancel) + if opts.cancelLabel != "" { + args = append(args, "--cancel-label", opts.cancelLabel) } - if opts.extra != "" { - args = append(args, "--extra-button", opts.extra) + if opts.extraButton != "" { + args = append(args, "--extra-button", opts.extraButton) } - if opts.nowrap { + if opts.noWrap { args = append(args, "--no-wrap") } if opts.ellipsize { args = append(args, "--ellipsize") } - if opts.defcancel { + if opts.defaultCancel { args = append(args, "--default-cancel") } switch opts.icon { @@ -59,7 +59,7 @@ func message(kind messageKind, text string, options []Option) (bool, error) { out, err := zenutil.Run(args) if err, ok := err.(*exec.ExitError); ok && err.ExitCode() != 255 { - if len(out) > 0 && string(out[:len(out)-1]) == opts.extra { + if len(out) > 0 && string(out[:len(out)-1]) == opts.extraButton { return false, ErrExtraButton } return false, nil diff --git a/msg_windows.go b/msg_windows.go index 092a097..ffeb83e 100644 --- a/msg_windows.go +++ b/msg_windows.go @@ -11,14 +11,14 @@ var ( ) func message(kind messageKind, text string, options []Option) (bool, error) { - opts := optsParse(options) + opts := applyOptions(options) var flags, caption uintptr switch { - case kind == questionKind && opts.extra != "": + case kind == questionKind && opts.extraButton != "": flags |= 0x3 // MB_YESNOCANCEL - case kind == questionKind || opts.extra != "": + case kind == questionKind || opts.extraButton != "": flags |= 0x1 // MB_OKCANCEL } @@ -33,8 +33,8 @@ func message(kind messageKind, text string, options []Option) (bool, error) { flags |= 0x40 // MB_ICONINFORMATION } - if kind == questionKind && opts.defcancel { - if opts.extra == "" { + if kind == questionKind && opts.defaultCancel { + if opts.extraButton == "" { flags |= 0x100 // MB_DEFBUTTON2 } else { flags |= 0x200 // MB_DEFBUTTON3 @@ -45,7 +45,7 @@ func message(kind messageKind, text string, options []Option) (bool, error) { caption = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(opts.title))) } - if opts.ok != "" || opts.cancel != "" || opts.extra != "" { + if opts.okLabel != "" || opts.cancelLabel != "" || opts.extraButton != "" { runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -89,17 +89,17 @@ func hookMessageLabels(kind messageKind, opts options) (hook uintptr, err error) var text string switch ctl { case 1, 6: // IDOK, IDYES - text = opts.ok + text = opts.okLabel case 2: // IDCANCEL if kind == questionKind { - text = opts.cancel - } else if opts.extra != "" { - text = opts.extra + text = opts.cancelLabel + } else if opts.extraButton != "" { + text = opts.extraButton } else { - text = opts.ok + text = opts.okLabel } case 7: // IDNO - text = opts.extra + text = opts.extraButton } if text != "" { ptr := syscall.StringToUTF16Ptr(text) diff --git a/zenity.go b/zenity.go index e7ea01a..c1c3245 100644 --- a/zenity.go +++ b/zenity.go @@ -21,39 +21,45 @@ type options struct { title string // File selection options - filename string - directory bool - overwrite bool - create bool - hidden bool - filters []FileFilter + filename string + directory bool + confirmOverwrite bool + confirmCreate bool + showHidden bool + fileFilters []FileFilter // Color selection options - color color.Color - palette bool + color color.Color + showPalette bool // Message options - icon MessageIcon - ok string - cancel string - extra string - nowrap bool - ellipsize bool - defcancel bool + icon MessageIcon + okLabel string + cancelLabel string + extraButton string + noWrap bool + ellipsize bool + defaultCancel bool } // An Option is an argument passed to dialog functions to customize their // behavior. -type Option func(*options) +type Option interface { + apply(*options) +} -func optsParse(options []Option) (res options) { +type funcOption func(*options) + +func (f funcOption) apply(o *options) { f(o) } + +func applyOptions(options []Option) (res options) { for _, o := range options { - o(&res) + o.apply(&res) } return } // Title returns an Option to set the dialog title. func Title(title string) Option { - return func(o *options) { o.title = title } + return funcOption(func(o *options) { o.title = title }) }