mirror of
https://github.com/fumiama/ReiBot.git
synced 2026-06-08 20:10:30 +08:00
add more
This commit is contained in:
131
shell.go
Normal file
131
shell.go
Normal file
@@ -0,0 +1,131 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user