1
0
mirror of https://github.com/fumiama/ReiBot.git synced 2026-06-05 00:50:25 +08:00
Files
ReiBot/shell.go
源文雨 8b6817acea add more
2022-06-02 14:36:43 +08:00

132 lines
2.3 KiB
Go

package rei
import (
"flag"
"reflect"
"strings"
)
func isSpace(r rune) bool {
switch r {
case ' ', '\t', '\r', '\n':
return true
}
return false
}
type argType int
const (
argNo argType = iota
argSingle
argQuoted
)
// ParseShell 将指令转换为指令参数.
// modified from https://github.com/mattn/go-shellwords
func ParseShell(s string) []string {
var args []string
buf := strings.Builder{}
var escaped, doubleQuoted, singleQuoted, backQuote bool
backtick := ""
got := argNo
for _, r := range s {
if escaped {
buf.WriteRune(r)
escaped = false
got = argSingle
continue
}
if r == '\\' {
if singleQuoted {
buf.WriteRune(r)
} else {
escaped = true
}
continue
}
if isSpace(r) {
if singleQuoted || doubleQuoted || backQuote {
buf.WriteRune(r)
backtick += string(r)
} else if got != argNo {
args = append(args, buf.String())
buf.Reset()
got = argNo
}
continue
}
switch r {
case '`':
if !singleQuoted && !doubleQuoted {
backtick = ""
backQuote = !backQuote
}
case '"':
if !singleQuoted {
if doubleQuoted {
got = argQuoted
}
doubleQuoted = !doubleQuoted
}
case '\'':
if !doubleQuoted {
if singleQuoted {
got = argSingle
}
singleQuoted = !singleQuoted
}
default:
got = argSingle
buf.WriteRune(r)
if backQuote {
backtick += string(r)
}
}
}
if got != argNo {
args = append(args, buf.String())
}
return args
}
var (
boolType = reflect.TypeOf(false)
intType = reflect.TypeOf(0)
stringType = reflect.TypeOf("")
float64Type = reflect.TypeOf(float64(0))
)
func registerFlag(t reflect.Type, v reflect.Value) *flag.FlagSet {
v = v.Elem()
fs := flag.NewFlagSet("", flag.ContinueOnError)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
name := field.Tag.Get("flag")
if name == "" {
continue
}
help := field.Tag.Get("help")
switch field.Type {
case boolType:
fs.BoolVar(v.Field(i).Addr().Interface().(*bool), name, false, help)
case intType:
fs.IntVar(v.Field(i).Addr().Interface().(*int), name, 0, help)
case stringType:
fs.StringVar(v.Field(i).Addr().Interface().(*string), name, "", help)
case float64Type:
fs.Float64Var(v.Field(i).Addr().Interface().(*float64), name, 0, help)
default:
panic("unsupported type")
}
}
return fs
}