Skip to content

Commit

Permalink
chore: interact - replace the interface{} to go1.18 any
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Sep 4, 2022
1 parent 4e9980d commit de96285
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 132 deletions.
80 changes: 17 additions & 63 deletions interact/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ package interact
import (
"fmt"
"os"
"strconv"
"strings"

"github.com/gookit/color"
"github.com/gookit/goutil/structs"
)

const (
Expand All @@ -17,64 +17,18 @@ const (
ERR = 2
)

// RunFace for interact methods
type RunFace interface {
Run() *Value
}

// Value data store
type Value struct {
val interface{} // the value(s) of the key(s)
}

// Set val
func (v Value) Set(val interface{}) {
v.val = val
}

// Val get
func (v Value) Val() interface{} {
return v.val
}

// Int value
func (v Value) Int() (val int) {
if v.val == nil {
return
}
switch tpVal := v.val.(type) {
case int:
return tpVal
case string:
val, err := strconv.Atoi(tpVal)
if err == nil {
return val
}
}
return
}

// String value
func (v Value) String() string {
if v.val == nil {
return ""
}

return fmt.Sprintf("%v", v.val)
// ComOptions struct
type ComOptions struct {
// ValidFn check input value
ValidFn func(val any) (any, error)
}

// Strings value
func (v Value) Strings() (ss []string) {
if v.val == nil {
return
}

return v.val.([]string)
}
// Value alias of structs.Value
type Value = structs.Value

// IsEmpty value
func (v Value) IsEmpty() bool {
return v.val == nil
// RunFace for interact methods
type RunFace interface {
Run() *Value
}

/*************************************************************
Expand All @@ -89,10 +43,10 @@ type SelectResult struct {
}

// create SelectResult create
func newSelectResult(key, val interface{}) *SelectResult {
func newSelectResult(key, val any) *SelectResult {
return &SelectResult{
K: Value{val: key},
Value: Value{val: val},
K: Value{V: key},
Value: Value{V: val},
}
}

Expand All @@ -107,12 +61,12 @@ func (sv *SelectResult) KeyStrings() []string {
}

// Key value get
func (sv *SelectResult) Key() interface{} {
func (sv *SelectResult) Key() any {
return sv.K.Val()
}

// WithKey value
func (sv *SelectResult) WithKey(key interface{}) *SelectResult {
func (sv *SelectResult) WithKey(key any) *SelectResult {
sv.K.Set(key)
return sv
}
Expand All @@ -121,12 +75,12 @@ func (sv *SelectResult) WithKey(key interface{}) *SelectResult {
* helper methods
*************************************************************/

func exitWithErr(format string, v ...interface{}) {
func exitWithErr(format string, v ...any) {
color.Error.Tips(format, v...)
os.Exit(ERR)
}

func exitWithMsg(exitCode int, messages ...interface{}) {
func exitWithMsg(exitCode int, messages ...any) {
fmt.Println(messages...)
os.Exit(exitCode)
}
Expand Down
72 changes: 49 additions & 23 deletions interact/interact.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
package interact

import "github.com/gookit/color"
import (
"io"
"os"

"github.com/gookit/color"
)

// the global input output stream
var (
Input io.Reader = os.Stdin
Output io.Writer = os.Stdout
)

// SetInput stream
func SetInput(in io.Reader) { Input = in }

// SetOutput stream
func SetOutput(out io.Writer) { Output = out }

// ResetIO stream
func ResetIO() {
Input = os.Stdin
Output = os.Stdout
}

// Interactive definition
type Interactive struct {
Expand All @@ -12,8 +35,8 @@ func New(name string) *Interactive {
return &Interactive{Name: name}
}

// Option definition
type Option struct {
// Options definition
type Options struct {
Quit bool
// default value
DefVal string
Expand All @@ -33,9 +56,10 @@ func Unconfirmed(message string, defVal ...bool) bool {
// Ask a question and return the result of the input.
//
// Usage:
// answer := Ask("Your name?", "", nil)
// answer := Ask("Your name?", "tom", nil)
// answer := Ask("Your name?", "", nil, 3)
//
// answer := Ask("Your name?", "", nil)
// answer := Ask("Your name?", "tom", nil)
// answer := Ask("Your name?", "", nil, 3)
func Ask(question, defVal string, fn func(ans string) error, maxTimes ...int) string {
q := &Question{Q: question, Func: fn, DefVal: defVal}
if len(maxTimes) > 0 {
Expand All @@ -51,31 +75,33 @@ func Query(question, defVal string, fn func(ans string) error, maxTimes ...int)
}

// Choice is alias of method SelectOne()
func Choice(title string, options interface{}, defOpt string, allowQuit ...bool) string {
func Choice(title string, options any, defOpt string, allowQuit ...bool) string {
return SelectOne(title, options, defOpt, allowQuit...)
}

// SingleSelect is alias of method SelectOne()
func SingleSelect(title string, options interface{}, defOpt string, allowQuit ...bool) string {
func SingleSelect(title string, options any, defOpt string, allowQuit ...bool) string {
return SelectOne(title, options, defOpt, allowQuit...)
}

// SelectOne select one of the options, returns selected option value
//
// map options:
// {
// // option value => option name
// 'a' => 'chengdu',
// 'b' => 'beijing'
// }
// Map options:
//
// {
// // option value => option name
// 'a' => 'chengdu',
// 'b' => 'beijing'
// }
//
// Array options:
//
// array options:
// {
// // only name, value will use index
// 'chengdu',
// 'beijing'
// }
func SelectOne(title string, options interface{}, defOpt string, allowQuit ...bool) string {
// {
// // only name, value will use index
// 'chengdu',
// 'beijing'
// }
func SelectOne(title string, options any, defOpt string, allowQuit ...bool) string {
s := &Select{Title: title, Options: options, DefOpt: defOpt}

if len(allowQuit) > 0 {
Expand All @@ -86,13 +112,13 @@ func SelectOne(title string, options interface{}, defOpt string, allowQuit ...bo
}

// Checkbox is alias of method MultiSelect()
func Checkbox(title string, options interface{}, defOpts []string, allowQuit ...bool) []string {
func Checkbox(title string, options any, defOpts []string, allowQuit ...bool) []string {
return MultiSelect(title, options, defOpts, allowQuit...)
}

// MultiSelect select multi of the options, returns selected option values.
// like SingleSelect(), but allow select multi option
func MultiSelect(title string, options interface{}, defOpts []string, allowQuit ...bool) []string {
func MultiSelect(title string, options any, defOpts []string, allowQuit ...bool) []string {
s := &Select{Title: title, Options: options, DefOpts: defOpts, MultiSelect: true}

if len(allowQuit) > 0 {
Expand Down
49 changes: 25 additions & 24 deletions interact/question.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

// Question definition
type Question struct {
// Q the question string
// Q the question message
Q string
// Func validate user input answer is right.
// if not set, will only check answer is empty.
Expand All @@ -22,35 +22,19 @@ type Question struct {
}

// NewQuestion instance.
//
// Usage:
// q := NewQuestion("Please input your name?")
// ans := q.Run().String()
//
// q := NewQuestion("Please input your name?")
// ans := q.Run().String()
func NewQuestion(q string, defVal ...string) *Question {
if len(defVal) > 0 {
return &Question{Q: q, DefVal: defVal[0]}
}

return &Question{Q: q}
}

func (q *Question) render() {
q.Q = strings.TrimSpace(q.Q)
if q.Q == "" {
exitWithErr("(interact.Question) must provide question message")
}

var defMsg string

q.DefVal = strings.TrimSpace(q.DefVal)
if q.DefVal != "" {
defMsg = fmt.Sprintf("[default:%s]", color.Green.Render(q.DefVal))
}

// print question
fmt.Printf("%s%s\n", color.Comment.Render(q.Q), defMsg)
}

// Run run and returns value
// Run and returns value
func (q *Question) Run() *Value {
q.render()
echoErr := color.Error.Println
Expand All @@ -64,7 +48,7 @@ DoASK:
// don't input
if ans == "" {
if q.DefVal != "" { // has default value
return &Value{q.DefVal}
return &Value{V: q.DefVal}
}

q.checkErrTimes()
Expand All @@ -82,7 +66,24 @@ DoASK:
}
}

return &Value{ans}
return &Value{V: ans}
}

func (q *Question) render() {
q.Q = strings.TrimSpace(q.Q)
if q.Q == "" {
exitWithErr("(interact.Question) must provide question message")
}

var defMsg string

q.DefVal = strings.TrimSpace(q.DefVal)
if q.DefVal != "" {
defMsg = fmt.Sprintf("[default:%s]", color.Green.Render(q.DefVal))
}

// print question
fmt.Printf("%s%s\n", color.Comment.Render(q.Q), defMsg)
}

func (q *Question) checkErrTimes() {
Expand Down
Loading

0 comments on commit de96285

Please sign in to comment.