master > master: code go - entwicklung für interaktiven Modus gestartet

This commit is contained in:
RD
2021-11-03 11:04:59 +01:00
parent 43f5447ed7
commit 893db52d90
11 changed files with 421 additions and 42 deletions

View File

@@ -0,0 +1,102 @@
package menus
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"strconv"
"strings"
"ads/internal/core/logging"
)
/* ---------------------------------------------------------------- *
* METHOD show menu
* ---------------------------------------------------------------- */
func (menu Menu) ShowMenu() (bool, error) {
var (
choice string
index int
meta bool
quit bool
)
var promptMessages []string
var options [][2]string
var defaultOption string
var breaks []int
// Headline einfügen
promptMessages = make([]string, len(menu.PromptMessages))
copy(promptMessages, menu.PromptMessages)
head := fmt.Sprintf("\033[2m%s\033[0m", strings.Join(menu.Path, " > "))
promptMessages = append([]string{head}, promptMessages...)
// Zurück-Option einfügen
defaultOption = fmt.Sprintf("%v", menu.DefaultOption)
options = []([2]string){}
for i, opt := range menu.Options {
key := fmt.Sprintf("%v", i+1)
subLabel := opt.SubLabel
label := opt.Label
if !(subLabel == "") {
label = fmt.Sprintf("%v (\033[2m%v\033[0m)", opt.Label, subLabel)
}
options = append(options, [2]string{key, label})
}
breaks = []int{len(menu.Options) - 1}
if !menu.IsRoot {
options = append(options, [2]string{"z", "Zurück zum vorherigen Menü"})
}
options = append(options, [2]string{"q", "Programm schließen"})
// User Response immer abfragen und abarbeiten, bis quit/return.
performClearScreen := !menu.IsRoot
for {
if performClearScreen {
logging.ClearScreen()
}
performClearScreen = true
choice, meta = PromptListOfOptions(promptMessages, options, breaks, defaultOption)
// Falls quit wählt, -> quit:
if (menu.IsRoot && meta) || choice == "q" {
return true, nil
}
// Falls User back wählt, -> return:
if (!menu.IsRoot && meta) || choice == "z" {
return false, nil
}
// sonst führe die assoziierte Methode aus
index64, _ := strconv.ParseInt(choice, 10, 64)
index = int(index64) - 1
if 0 <= index && index < len(menu.Options) {
opt := menu.Options[index]
// Entweder Untermenü öffnen oder Action ausführen
if opt.Submenu != nil {
quit, _ = opt.Submenu.ShowMenu()
if quit {
return true, nil
}
} else if opt.Action != nil {
opt.Action()
quit := logging.PromptAnyKeyToContinue()
// Falls während der Action der User Meta+D klickt, -> quit:
if quit {
return true, nil
}
} else {
logging.LogWarn("Option noch nicht implementiert.")
quit := logging.PromptAnyKeyToContinue()
if quit {
return true, nil
}
}
}
}
}

View File

@@ -0,0 +1,91 @@
package menus
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"reflect"
"ads/internal/core/logging"
"ads/internal/core/utils"
)
/* ---------------------------------------------------------------- *
* METHOD prompt options
* ---------------------------------------------------------------- */
// Zeigt Prompt mit Liste von Optionen an
func PromptListOfOptions(messages []string, options [][2]string, breaks []int, defaultChoice string) (string, bool) {
var n = len(options)
var (
choice string
cancel bool
err error
)
var lines []interface{}
var optionsMap = map[string]string{}
// Erzeuge Messages
lines = []interface{}{}
for _, message := range messages {
lines = append(lines, message)
}
lines = append(lines, "")
for i, obj := range options {
key := obj[0]
label := obj[1]
optionsMap[key] = label
if key == defaultChoice {
lines = append(lines, fmt.Sprintf("\033[91m*\033[0m\033[93;1m%v)\033[0m %v", key, label))
} else {
lines = append(lines, fmt.Sprintf(" \033[93;1m%v)\033[0m %v", key, label))
}
if i < n-1 && utils.ArrayContains(breaks, i) {
lines = append(lines, " \033[93m--------\033[0m")
}
i++
}
if !(defaultChoice == "" || defaultChoice == "-1") {
lines = append(lines, "")
lines = append(lines, "\033[91;2m*\033[0m\033[2m = Default\033[0m")
}
// Wiederhole Prompt, bis gültige Eingabe erreicht
for {
choice, cancel, err = logging.Prompt(lines...)
if cancel {
return "", true
}
if err != nil {
logging.ClearScreen()
logging.LogError(err)
continue
}
if choice == "" {
choice = defaultChoice
break
}
if _, ok := optionsMap[choice]; !ok {
logging.ClearScreen()
logging.LogError("Ungültige eingabe")
continue
}
break
}
return choice, false
}
/* ---------------------------------------------------------------- *
* METHOD prompt values
* ---------------------------------------------------------------- */
func PromptValue(varname string, typename string, example string, t reflect.Type) (bool, error) {
_, cancel, err := logging.Prompt(
fmt.Sprintf("Bitte den Wert von \033[1m%s\033[0m als \033[1m%s\033[0m eingeben.", varname, typename),
example,
)
// TODO: input parsen
return cancel, err
}

View File

@@ -0,0 +1,26 @@
package menus
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
//
/* ---------------------------------------------------------------- *
* TYPES
* ---------------------------------------------------------------- */
type MenuOption struct {
Label string
SubLabel string
Submenu *Menu
Action func() error // NOTE: in go, this is automatically a pointer type
}
type Menu struct {
IsRoot bool
Path []string
PromptMessages []string
Options []MenuOption
DefaultOption int
}