mirror of
https://github.com/zrepl/zrepl.git
synced 2024-11-22 08:23:50 +01:00
a58ce74ed0
Primary goals: - Scrollable output ( fixes #245 ) - Sending job signals from status view - Filtering of output by filesystem Implementation: - original TUI framework: github.com/rivo/tview - but: tview is quasi-unmaintained, didn't support some features - => use fork https://gitlab.com/tslocum/cview - however, don't buy into either too much to avoid lock-in - instead: **port over the existing status UI drawing code and adjust it to produce strings instead of directly drawing into the termbox buffer** Co-authored-by: Calistoc <calistoc@protonmail.com> Co-authored-by: InsanePrawn <insane.prawny@gmail.com> fixes #245 fixes #220
99 lines
2.0 KiB
Go
99 lines
2.0 KiB
Go
// Package choice implements a flag.Value type that accepts a set of choices.
|
|
//
|
|
// See test cases or grep the code base for usage hints.
|
|
package choices
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type Choices struct {
|
|
choices map[string]interface{}
|
|
typeString string
|
|
value interface{}
|
|
}
|
|
|
|
var _ flag.Value = (*Choices)(nil)
|
|
|
|
func new(pairs ...interface{}) Choices {
|
|
if (len(pairs) % 2) != 0 {
|
|
panic("must provide a sequence of key value pairs")
|
|
}
|
|
c := Choices{
|
|
choices: make(map[string]interface{}, len(pairs)/2),
|
|
value: nil,
|
|
}
|
|
for i := 0; i < len(pairs); {
|
|
key, ok := pairs[i].(string)
|
|
if !ok {
|
|
panic(fmt.Sprintf("argument %d is %T but should be a string, value: %#v", i, pairs[i], pairs[i]))
|
|
}
|
|
c.choices[key] = pairs[i+1]
|
|
i += 2
|
|
}
|
|
c.typeString = strings.Join(c.choicesList(true), ",") // overrideable by setter
|
|
return c
|
|
}
|
|
|
|
func (c *Choices) Init(pairs ...interface{}) {
|
|
*c = new(pairs...)
|
|
}
|
|
|
|
func (c Choices) choicesList(escaped bool) []string {
|
|
keys := make([]string, len(c.choices))
|
|
i := 0
|
|
for k := range c.choices {
|
|
e := k
|
|
if escaped {
|
|
e = fmt.Sprintf("%q", k)
|
|
}
|
|
keys[i] = e
|
|
i += 1
|
|
}
|
|
return keys
|
|
}
|
|
|
|
func (c Choices) Usage() string {
|
|
return fmt.Sprintf("one of %s", strings.Join(c.choicesList(true), ","))
|
|
}
|
|
|
|
func (c Choices) InputForChoice(v interface{}) (string, error) {
|
|
for input, choice := range c.choices {
|
|
if choice == v {
|
|
return input, nil
|
|
}
|
|
}
|
|
return "", fmt.Errorf("choice not registered at .Init(): %v", v)
|
|
}
|
|
|
|
func (c *Choices) SetDefaultValue(v interface{}) {
|
|
c.value = v
|
|
}
|
|
|
|
func (c Choices) Value() interface{} {
|
|
return c.value
|
|
}
|
|
|
|
func (c *Choices) Set(input string) error {
|
|
v, ok := c.choices[input]
|
|
if !ok {
|
|
return fmt.Errorf("invalid value %q: must be one of %s", input, c.Usage())
|
|
}
|
|
c.value = v
|
|
return nil
|
|
}
|
|
|
|
func (c *Choices) String() string {
|
|
return "" // c.value.(fmt.Stringer).String()
|
|
}
|
|
|
|
func (c *Choices) SetTypeString(ts string) {
|
|
c.typeString = ts
|
|
}
|
|
|
|
func (c *Choices) Type() string {
|
|
return c.typeString
|
|
}
|