iopshell/internal/setting/setting.go

227 lines
6.0 KiB
Go

/*
Copyright (c) 2018 Rasmus Moorats (nns)
This file is part of iopshell.
iopshell is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
iopshell is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with iopshell. If not, see <https://www.gnu.org/licenses/>.
*/
package setting
import (
"fmt"
"github.com/chzyer/readline"
"github.com/nnsee/iopshell/internal/cmd"
"github.com/nnsee/iopshell/internal/connection"
"github.com/nnsee/iopshell/internal/textmutate"
)
var (
// ConnChannel listens for connection requests
ConnChannel = make(chan []string)
// ScriptIn listens for script run requests
ScriptIn = make(chan []string)
// ScriptRet houses return codes from scripts
ScriptRet = make(chan error)
// In receives incoming messages
In = make(chan interface{})
// Out houses outgoing messages
Out = make(chan interface{})
// PassBack returns a response to a command if requested
PassBack = make(chan connection.Response)
// PassBackID houses ID waiting for a response
PassBackID = -1
)
// Opt houses some options
type Opt struct {
Description string
Val interface{}
}
// ShellVars house some important structs, so they can be accessed elsewhere
type ShellVars struct {
Conn *connection.Connection
Completer readline.PrefixCompleter
Instance *readline.Instance
Opts map[string]*Opt
}
// Set sets opt to val
func (s *ShellVars) Set(opt string, val interface{}) bool {
if o, ok := s.Opts[opt]; ok {
o.Val = val
if opt == "verbose" { // there's got to be a better way to do this
textmutate.Verbose = val.(bool)
}
return true
}
return false
}
// Get returns the specified option's pointer, or false if it doesn't exist
func (s *ShellVars) Get(opt string) (*Opt, bool) {
if o, ok := s.Opts[opt]; ok {
return o, true
}
return &Opt{}, false
}
// GetS returns the specified option's value as a string, or false if it doesn't exist
func (s *ShellVars) GetS(opt string) (string, bool) {
if o, ok := s.Opts[opt]; ok {
val, err := o.Val.(string)
return val, err
}
return "", false
}
// GetB returns the specified option's value as a bool, or false if it doesn't exist
func (s *ShellVars) GetB(opt string) (bool, bool) {
if o, ok := s.Opts[opt]; ok {
val, err := o.Val.(bool)
return val, err
}
return false, false
}
// GetF returns the specified option's value as an float64, or false if it doesn't exist
func (s *ShellVars) GetF(opt string) (float64, bool) {
if o, ok := s.Opts[opt]; ok {
val, err := o.Val.(float64)
return val, err
}
return 0, false
}
// GetResponse can be used by commands to get a response
func GetResponse(id int) connection.Response {
var placeholder connection.Response
if id == -1 {
// call failed
return placeholder
}
PassBackID = id
return <-PassBack
}
// UpdatePrompt refreshes the prompt and sets it according to current status
func (s *ShellVars) UpdatePrompt() {
var prompt string
prompt = "\033[91miop\033[0;1m$\033[0m "
if s.Conn.Ws != nil {
if s.Conn.User == "" {
// Connected but not authenticated
prompt = "\033[32miop\033[0;1m$\033[0m "
} else {
// Connected and authenticated
prompt = fmt.Sprintf("\033[32miop\033[0m %s\033[0;1m$\033[0m ", s.Conn.User)
}
}
if s.Instance != nil {
s.Instance.SetPrompt(prompt)
s.Instance.Refresh()
}
}
// Helper item for call item completion
func callCompleterItem(name string) *readline.PrefixCompleter {
name += ":"
return &readline.PrefixCompleter{
Name: []rune(name),
Dynamic: false,
Children: nil,
}
}
// UpdateCompleter adds commands registered with .Register() to the autocompleter
func (s *ShellVars) UpdateCompleter(cmdlist map[string]cmd.Command) {
s.Completer = *readline.NewPrefixCompleter()
s.Completer.SetChildren(*new([]readline.PrefixCompleterInterface))
for _, c := range cmdlist {
s.Completer.Children = append(s.Completer.Children,
readline.PcItem(c.Name))
}
}
// UpdateCallCompleter generates the completer for the "call" command
// supplied via a map generated by the "list" method
func (s *ShellVars) UpdateCallCompleter(list map[string]interface{}) {
parent := readline.PcItem("call")
for k1, v1 := range list {
path := readline.PcItem(k1)
methods, ok := v1.(map[string]interface{})
if ok {
for k2, v2 := range methods {
method := readline.PcItem(k2)
items, ok := v2.(map[string]interface{})
if ok {
for k3 := range items {
method.Children = append(method.Children,
callCompleterItem(k3))
}
}
path.Children = append(path.Children, method)
}
}
parent.Children = append(parent.Children, path)
}
// remove previous "call" completer to avoid duplicates
for i, child := range s.Completer.Children {
if string(child.GetName())[:4] == "call" {
s.Completer.Children = append(s.Completer.Children[:i],
s.Completer.Children[i+1:]...)
}
}
// add new and improved completer
s.Completer.Children = append(s.Completer.Children, parent)
}
// Init values for Vars
func genVars() *ShellVars {
var vars ShellVars
vars.Opts = make(map[string]*Opt)
vars.Opts["host"] = &Opt{
Description: "Host to connect to by default",
Val: "192.168.1.1",
}
vars.Opts["user"] = &Opt{
Description: "User to authenticate as by default",
Val: "user",
}
vars.Opts["pass"] = &Opt{
Description: "Password to authenticate with by default",
Val: "user",
}
vars.Opts["verbose"] = &Opt{
Description: "Print verbose messages",
Val: textmutate.Verbose,
}
vars.Opts["script_delay"] = &Opt{
Description: "Number of seconds to wait between each command when running a script",
Val: float64(0),
}
return &vars
}
// Vars is an instance of ShellVars
var Vars = *genVars()