dialog

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 13, 2023 License: MIT Imports: 17 Imported by: 3

README

dialog

cross plattform CLI dialogs.

Features

The library is organized in screens. The following types of screens are available:

  • input

  • password

  • select

  • multiselect

  • output

  • error

  • There is also support for input validation.

  • When there is too much content for the screen, the pager is enabled.

Example

package main

import (
	"fmt"
	"os"
	"strings"
	"time"

	"gitlab.com/golang-utils/dialog"
	"gitlab.com/golang-utils/fmtdate"
)

func main() {
	err := run()

	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err.Error())
		os.Exit(1)
	}

	os.Exit(0)
}

func run() error {
	return NewApp().Run()
}

func NewApp() *App {
	var opts []dialog.Option

	opts = append(opts,
		dialog.WithBackNavigation(),
		dialog.WithFooter(),
		dialog.WithHeader(),
		dialog.WithBreadcrumb(),
	)

	a := &App{}

	a.app = dialog.New("Person", opts...)
	return a
}

type Data struct {
	Firstname string
	Lastname  string
	Password  string
	Birthday  string
	Male      bool
	Pets      []string
	Number    string
}

type App struct {
	app  dialog.App
	Data Data
}

func (a *App) Run() error {
	return a.app.Run(a.askforGender())
}

func (a *App) askforGender() dialog.Screen {
	sc := a.app.NewSelect(
		"choose your gender", []string{"female", "male"},

		func(chosen string) dialog.Screen {
			switch chosen {
			case "female":
				a.Data.Male = false
			case "male":
				a.Data.Male = true
			}

			return a.askforFirstname()
		})

	sc.SetOptions(
		dialog.WithID("gender"),
	)

	return sc
}

func (a *App) askforFirstname() dialog.Screen {
	sc := a.app.NewInput(
		"please enter your firstname",

		func(fname string) dialog.Screen {
			a.Data.Firstname = fname

			return a.askforLastname()
		})
	sc.SetOptions(
		dialog.WithID("firstname"),
		dialog.WithValidator(dialog.String),
	)
	return sc
}

func (a *App) askforLastname() dialog.Screen {
	sc := a.app.NewInput(
		"please enter your lastname",

		func(lname string) dialog.Screen {
			a.Data.Lastname = lname

			return a.askforBirthday()
		})

	sc.SetOptions(
		dialog.WithID("lastname"),
		dialog.WithValidator(dialog.String),
	)

	return sc
}

func (a *App) askforBirthday() dialog.Screen {
	sc := a.app.NewInput(
		"please enter your birthday (YYYY-MM-DD)",

		func(bday string) dialog.Screen {
			a.Data.Birthday = bday

			return a.askforPets()
		})

	prefill := fmtdate.Format("YYYY-MM-DD", time.Now())

	sc.SetOptions(
		dialog.WithID("birthday"),
		dialog.WithValidator(dialog.DateTime("YYYY-MM-DD")),
		dialog.WithPrefilled(prefill),
	)

	return sc
}

func (a *App) askforPets() dialog.Screen {
	var options []string

	for i := 1; i <= 40; i++ {
		options = append(options, fmt.Sprintf("Pet %v", i))
	}

	sc := a.app.NewMultiSelect(
		"which pets do you have", options,
		func(pets []string) dialog.Screen {
			a.Data.Pets = pets

			return a.askforNumber()
		})

	sc.SetOptions(
		dialog.WithID("pets"),
		dialog.WithValidator(dialog.And{dialog.Min(3), dialog.Max(5)}),
	)

	return sc
}

func (a *App) askforNumber() dialog.Screen {
	var options []string

	for i := 1; i <= 50; i++ {
		options = append(options, fmt.Sprintf("%v", i))
	}

	sc := a.app.NewSelect(
		"which number do you choose", options,

		func(choosen string) dialog.Screen {
			a.Data.Number = choosen

			return a.askforPassword()
		})

	sc.SetOptions(
		dialog.WithID("number"),
		dialog.WithValidator(dialog.NonEmpty),
	)

	return sc
}

func (a *App) askforPassword() dialog.Screen {
	sc := a.app.NewPassword(
		"please enter your password",
		func(pw string) dialog.Screen {
			a.Data.Password = pw

			return a.showSummary()
		})

	sc.SetOptions(
		dialog.WithID("password"),
		dialog.WithValidator(dialog.String),
	)

	return sc
}

func (a *App) showSummary() dialog.Screen {
	sc := a.app.NewOutput(
		a.summary(),
		func() dialog.Screen {
			return a.byebye()
		})

	return sc
}

func (a *App) byebye() dialog.Screen {
	sc := a.app.NewOutput(
		"Thanks and byebye",
		func() dialog.Screen {
			return dialog.QuitScreen()
		})

	return sc
}

func (a *App) summary() string {
	var g = "f"

	if a.Data.Male {
		g = "m"
	}

	var bd strings.Builder

	for i := 0; i < 5; i++ {
		s := fmt.Sprintf(`
### %v ##
%s %s (%s)
Password: %s
born %s
pets %s
number: %v
	`, i, a.Data.Firstname, a.Data.Lastname, g,
			a.Data.Password,
			a.Data.Birthday,
			strings.Join(a.Data.Pets, ", "),
			a.Data.Number)
		bd.WriteString(s)
	}

	return bd.String()
}

also, see example-app

Documentation

see https://pkg.go.dev/gitlab.com/golang-utils/dialog

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrCanceled = fmt.Errorf("operation canceled")

Functions

This section is empty.

Types

type And

type And []Validator

func (And) Validate

func (a And) Validate(v interface{}) error

type App

type App interface {
	Name() string
	Run(firstScreen Screen) error
	NewPassword(question string, hd func(string) Screen) Screen
	NewInput(question string, hd func(string) Screen) Screen
	NewMultiSelect(question string, choices []string, hd func(s []string) Screen) Screen
	NewOutput(message string, next func() Screen) Screen
	NewSelect(question string, choices []string, hd func(string) Screen) Screen
	NewError(message string) Screen
}

func New

func New(name string, opts ...Option) App

type AppExt added in v0.0.3

type AppExt interface {
	App
	GetBreadcrumb() string
	GetValue(sc Screen) interface{}
	SetValue(sc Screen, value interface{})
	ClearValues()
	HasBackNav() bool
}

type DateTime

type DateTime string

the string is the format of the expected datetime (excel format)

func (DateTime) Validate

func (d DateTime) Validate(v interface{}) error

type GUI

type GUI interface {
	Input(msg string, prefilled string, hideText bool, opts GUIOptions) (res string, back bool, err error)
	Select(msg string, items []string, selected string, opts GUIOptions) (res string, back bool, err error)
	MultiSelect(msg string, items []string, preselected []string, opts GUIOptions) (res []string, back bool, err error)
	Output(msg string, opts GUIOptions) (back bool, err error)
	Error(msg string, opts GUIOptions)
	SetApp(a AppExt)
}
var DefaultGUI GUI

type GUIOptions added in v0.2.0

type GUIOptions struct {
	Title    string
	Width    uint
	Height   uint
	HideBack bool
	OkAsBack bool
}

type Max

type Max int

func (Max) Validate

func (t Max) Validate(v interface{}) error

type Min

type Min int

func (Min) Validate

func (m Min) Validate(v interface{}) error

type Option

type Option func(s *app)

func NoQuit

func NoQuit() Option

func WithBackNavigation

func WithBackNavigation() Option

func WithBreadcrumb

func WithBreadcrumb() Option

func WithDefaultGui added in v0.0.10

func WithDefaultGui() Option

func WithFooter

func WithFooter() Option

func WithGui

func WithGui(g GUI) Option

func WithHeader

func WithHeader() Option

type Or

type Or []Validator

func (Or) Validate

func (a Or) Validate(v interface{}) error

type Regexp

type Regexp string

func (Regexp) Validate

func (d Regexp) Validate(v interface{}) error

type Screen

type Screen interface {
	Name() string

	// ID is a unique identifyer for the screen
	// it is set to a UUID by default, but can be set via the WithID option (to get defined IDs)
	// defined IDs are necessary to fill back values when navigating back and forth between screens
	ID() string

	SetOptions(opts ...ScreenOption)
}

func QuitScreen

func QuitScreen() Screen

type ScreenExt added in v0.0.4

type ScreenExt interface {
	Screen
	Body() string
	OnInput(s string) ScreenExt
	Header() string
	RunGui(isFirst bool) (sc ScreenExt, back bool, err error)
	SetValue(interface{})
	Lines() int
	AvailableLines() int
}

type ScreenOption

type ScreenOption func(*screenConfig)

func WithCharLimit added in v0.0.7

func WithCharLimit(n int) ScreenOption

WithCharLimit sets the charlimit for an (input) screen

func WithID added in v0.0.7

func WithID(s string) ScreenOption

ID is a unique identifyer for the screen it is set to a UUID by default, but can be set via the WithID option (to get defined IDs) defined IDs are necessary to fill back values when navigating back and forth between screens

func WithName added in v0.0.7

func WithName(n string) ScreenOption

WithName sets the name of the screen

func WithPrefilled added in v0.0.7

func WithPrefilled(val interface{}) ScreenOption

WithPrefilled prefills the value of a screen

func WithValidator added in v0.0.7

func WithValidator(v Validator) ScreenOption

WithValidator sets a validator for a (input) screen

type Validator

type Validator interface {
	// if the value is valid, nil is returned. otherwise we can use the error message
	Validate(v interface{}) error
}

type ValidatorFunc

type ValidatorFunc func(interface{}) error
var (
	Any      ValidatorFunc
	Int      ValidatorFunc
	Float    ValidatorFunc
	NonEmpty ValidatorFunc
	String   ValidatorFunc
)

func (ValidatorFunc) Validate

func (fn ValidatorFunc) Validate(v interface{}) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL