first commit
Some checks failed
CI/CD Pipeline / Test (push) Failing after 22m19s
CI/CD Pipeline / Security Scan (push) Failing after 5m57s
CI/CD Pipeline / Build (amd64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (amd64, linux) (push) Has been skipped
CI/CD Pipeline / Build (amd64, windows) (push) Has been skipped
CI/CD Pipeline / Build (arm64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (arm64, linux) (push) Has been skipped
CI/CD Pipeline / Build Docker Image (push) Has been skipped
CI/CD Pipeline / Create Release (push) Has been skipped

This commit is contained in:
Rogee
2025-09-28 10:05:07 +08:00
commit 7fcabe0225
481 changed files with 125127 additions and 0 deletions

565
internal/cli/command.go Normal file
View File

@@ -0,0 +1,565 @@
package cli
import (
"fmt"
"os"
"strings"
"time"
)
// CommandType 定义命令类型
type CommandType int
const (
SERVER CommandType = iota
CONFIG
TEST
VERSION
HELP
UNKNOWN
)
// Command 表示CLI命令的结构
// 该结构体包含命令的所有参数和配置
type Command struct {
// 基本命令信息
Type CommandType `json:"type"`
Name string `json:"name"`
Description string `json:"description"`
Aliases []string `json:"aliases"`
Usage string `json:"usage"`
// 位置参数
Args []string `json:"args"`
ArgsCount int `json:"args_count"`
// 标志参数
Flags map[string]string `json:"flags"`
Booleans map[string]bool `json:"booleans"`
Integers map[string]int64 `json:"integers"`
Floats map[string]float64 `json:"floats"`
// 选项参数
Options map[string][]string `json:"options"`
// 环境变量
EnvVars map[string]string `json:"env_vars"`
// 配置文件
ConfigFile string `json:"config_file"`
Config interface{} `json:"config"`
// 执行信息
Executed bool `json:"executed"`
ExecutedAt time.Time `json:"executed_at"`
Duration time.Duration `json:"duration"`
ExitCode int `json:"exit_code"`
Output string `json:"output"`
Error error `json:"error"`
// 上下文信息
WorkingDir string `json:"working_dir"`
UserID string `json:"user_id,omitempty"`
SessionID string `json:"session_id,omitempty"`
// 调试信息
Debug bool `json:"debug"`
Verbose bool `json:"verbose"`
Quiet bool `json:"quiet"`
DryRun bool `json:"dry_run"`
// 自定义数据
Custom map[string]interface{} `json:"custom,omitempty"`
}
// NewCommand 创建新的命令实例
// 返回包含基本信息的Command结构体
func NewCommand(cmdType CommandType, name, description string) *Command {
return &Command{
Type: cmdType,
Name: name,
Description: description,
Args: make([]string, 0),
Flags: make(map[string]string),
Booleans: make(map[string]bool),
Integers: make(map[string]int64),
Floats: make(map[string]float64),
Options: make(map[string][]string),
EnvVars: make(map[string]string),
WorkingDir: getCurrentWorkingDir(),
Custom: make(map[string]interface{}),
}
}
// NewServerCommand 创建服务器命令
// 返回配置好的服务器命令实例
func NewServerCommand() *Command {
cmd := NewCommand(SERVER, "server", "Start the subconverter server")
cmd.Usage = "server [flags]"
cmd.Aliases = []string{"serve", "start"}
// 默认标志
cmd.Booleans["debug"] = false
cmd.Booleans["verbose"] = false
cmd.Integers["port"] = 25500
cmd.Flags["host"] = "0.0.0.0"
cmd.Flags["config"] = ""
return cmd
}
// NewConfigCommand 创建配置命令
// 返回配置好的配置命令实例
func NewConfigCommand() *Command {
cmd := NewCommand(CONFIG, "config", "Manage configuration")
cmd.Usage = "config <subcommand> [flags]"
cmd.Aliases = []string{"conf", "cfg"}
return cmd
}
// NewTestCommand 创建测试命令
// 返回配置好的测试命令实例
func NewTestCommand() *Command {
cmd := NewCommand(TEST, "test", "Run tests")
cmd.Usage = "test <subcommand> [flags]"
cmd.Aliases = []string{"t"}
cmd.Booleans["verbose"] = false
cmd.Booleans["cover"] = false
cmd.Flags["run"] = ""
cmd.Flags["output"] = ""
return cmd
}
// NewVersionCommand 创建版本命令
// 返回配置好的版本命令实例
func NewVersionCommand() *Command {
cmd := NewCommand(VERSION, "version", "Show version information")
cmd.Usage = "version [flags]"
cmd.Aliases = []string{"v", "ver"}
cmd.Booleans["verbose"] = false
cmd.Booleans["short"] = false
return cmd
}
// NewHelpCommand 创建帮助命令
// 返回配置好的帮助命令实例
func NewHelpCommand() *Command {
cmd := NewCommand(HELP, "help", "Show help information")
cmd.Usage = "help [command]"
cmd.Aliases = []string{"h", "?"}
return cmd
}
// AddArg 添加位置参数
func (c *Command) AddArg(arg string) {
c.Args = append(c.Args, arg)
c.ArgsCount = len(c.Args)
}
// AddArgs 添加多个位置参数
func (c *Command) AddArgs(args ...string) {
c.Args = append(c.Args, args...)
c.ArgsCount = len(c.Args)
}
// SetFlag 设置字符串标志
func (c *Command) SetFlag(key, value string) {
c.Flags[key] = value
}
// SetBoolean 设置布尔标志
func (c *Command) SetBoolean(key string, value bool) {
c.Booleans[key] = value
}
// SetInteger 设置整数标志
func (c *Command) SetInteger(key string, value int64) {
c.Integers[key] = value
}
// SetFloat 设置浮点数标志
func (c *Command) SetFloat(key string, value float64) {
c.Floats[key] = value
}
// AddOption 添加选项参数
func (c *Command) AddOption(key string, values ...string) {
if c.Options == nil {
c.Options = make(map[string][]string)
}
c.Options[key] = append(c.Options[key], values...)
}
// SetEnvVar 设置环境变量
func (c *Command) SetEnvVar(key, value string) {
if c.EnvVars == nil {
c.EnvVars = make(map[string]string)
}
c.EnvVars[key] = value
}
// GetArg 获取位置参数
func (c *Command) GetArg(index int) (string, bool) {
if index < 0 || index >= len(c.Args) {
return "", false
}
return c.Args[index], true
}
// GetFlag 获取字符串标志
func (c *Command) GetFlag(key string) (string, bool) {
value, exists := c.Flags[key]
return value, exists
}
// GetBoolean 获取布尔标志
func (c *Command) GetBoolean(key string) (bool, bool) {
value, exists := c.Booleans[key]
return value, exists
}
// GetInteger 获取整数标志
func (c *Command) GetInteger(key string) (int64, bool) {
value, exists := c.Integers[key]
return value, exists
}
// GetFloat 获取浮点数标志
func (c *Command) GetFloat(key string) (float64, bool) {
value, exists := c.Floats[key]
return value, exists
}
// GetOptions 获取选项参数
func (c *Command) GetOptions(key string) ([]string, bool) {
value, exists := c.Options[key]
return value, exists
}
// GetEnvVar 获取环境变量
func (c *Command) GetEnvVar(key string) (string, bool) {
value, exists := c.EnvVars[key]
return value, exists
}
// HasFlag 检查是否有指定标志
func (c *Command) HasFlag(key string) bool {
_, exists := c.Flags[key]
return exists
}
// HasBoolean 检查是否有指定布尔标志
func (c *Command) HasBoolean(key string) bool {
_, exists := c.Booleans[key]
return exists
}
// HasOption 检查是否有指定选项
func (c *Command) HasOption(key string) bool {
_, exists := c.Options[key]
return exists
}
// ArgCount 返回位置参数数量
func (c *Command) ArgCount() int {
return len(c.Args)
}
// IsExecuted 检查命令是否已执行
func (c *Command) IsExecuted() bool {
return c.Executed
}
// IsSuccessful 检查命令是否成功执行
func (c *Command) IsSuccessful() bool {
return c.Executed && c.ExitCode == 0
}
// SetConfig 设置配置信息
func (c *Command) SetConfig(config interface{}) {
c.Config = config
}
// SetConfigFile 设置配置文件路径
func (c *Command) SetConfigFile(path string) {
c.ConfigFile = path
}
// SetOutput 设置输出信息
func (c *Command) SetOutput(output string) {
c.Output = output
}
// SetError 设置错误信息
func (c *Command) SetError(err error) {
c.Error = err
c.ExitCode = 1
}
// MarkExecuted 标记命令为已执行
func (c *Command) MarkExecuted() {
c.Executed = true
c.ExecutedAt = time.Now()
}
// MarkSuccessful 标记命令为成功执行
func (c *Command) MarkSuccessful() {
c.MarkExecuted()
c.ExitCode = 0
}
// MarkFailed 标记命令为执行失败
func (c *Command) MarkFailed(exitCode int) {
c.MarkExecuted()
c.ExitCode = exitCode
}
// SetDuration 设置执行持续时间
func (c *Command) SetDuration(duration time.Duration) {
c.Duration = duration
}
// AddCustom 添加自定义数据
func (c *Command) AddCustom(key string, value interface{}) {
if c.Custom == nil {
c.Custom = make(map[string]interface{})
}
c.Custom[key] = value
}
// GetCustom 获取自定义数据
func (c *Command) GetCustom(key string) (interface{}, bool) {
value, exists := c.Custom[key]
return value, exists
}
// Validate 验证命令的有效性
func (c *Command) Validate() error {
if c.Name == "" {
return fmt.Errorf("command name cannot be empty")
}
if c.Type < SERVER || c.Type > UNKNOWN {
return fmt.Errorf("invalid command type: %d", c.Type)
}
// 验证必需的参数
switch c.Type {
case SERVER:
if port, exists := c.Integers["port"]; exists && (port < 1 || port > 65535) {
return fmt.Errorf("invalid port number: %d", port)
}
case CONFIG:
if len(c.Args) == 0 {
return fmt.Errorf("config command requires a subcommand")
}
case TEST:
if len(c.Args) == 0 {
return fmt.Errorf("test command requires a subcommand")
}
}
return nil
}
// GetUsage 返回使用说明
func (c *Command) GetUsage() string {
if c.Usage != "" {
return c.Usage
}
return c.Name
}
// GetFullUsage 返回完整的使用说明
func (c *Command) GetFullUsage() string {
var builder strings.Builder
builder.WriteString(fmt.Sprintf("Usage: %s", c.GetUsage()))
if c.Description != "" {
builder.WriteString(fmt.Sprintf("\n\n%s", c.Description))
}
if len(c.Aliases) > 0 {
builder.WriteString(fmt.Sprintf("\n\nAliases: %s", strings.Join(c.Aliases, ", ")))
}
// 添加位置参数说明
if len(c.Args) > 0 {
builder.WriteString("\n\nArguments:")
for i, arg := range c.Args {
builder.WriteString(fmt.Sprintf("\n %d: %s", i+1, arg))
}
}
// 添加标志说明
if len(c.Flags) > 0 || len(c.Booleans) > 0 || len(c.Integers) > 0 || len(c.Floats) > 0 {
builder.WriteString("\n\nFlags:")
for key, value := range c.Flags {
builder.WriteString(fmt.Sprintf("\n --%s=%s", key, value))
}
for key, value := range c.Booleans {
builder.WriteString(fmt.Sprintf("\n --%s (default: %t)", key, value))
}
for key, value := range c.Integers {
builder.WriteString(fmt.Sprintf("\n --%s=%d", key, value))
}
for key, value := range c.Floats {
builder.WriteString(fmt.Sprintf("\n --%s=%f", key, value))
}
}
return builder.String()
}
// Clone 创建命令的副本
func (c *Command) Clone() *Command {
clone := &Command{
Type: c.Type,
Name: c.Name,
Description: c.Description,
Usage: c.Usage,
ArgsCount: c.ArgsCount,
ConfigFile: c.ConfigFile,
Config: c.Config,
Executed: c.Executed,
ExecutedAt: c.ExecutedAt,
Duration: c.Duration,
ExitCode: c.ExitCode,
Output: c.Output,
Error: c.Error,
WorkingDir: c.WorkingDir,
UserID: c.UserID,
SessionID: c.SessionID,
Debug: c.Debug,
Verbose: c.Verbose,
Quiet: c.Quiet,
DryRun: c.DryRun,
}
// 深拷贝切片
if len(c.Aliases) > 0 {
clone.Aliases = make([]string, len(c.Aliases))
copy(clone.Aliases, c.Aliases)
}
if len(c.Args) > 0 {
clone.Args = make([]string, len(c.Args))
copy(clone.Args, c.Args)
}
// 深拷贝映射
if len(c.Flags) > 0 {
clone.Flags = make(map[string]string)
for k, v := range c.Flags {
clone.Flags[k] = v
}
}
if len(c.Booleans) > 0 {
clone.Booleans = make(map[string]bool)
for k, v := range c.Booleans {
clone.Booleans[k] = v
}
}
if len(c.Integers) > 0 {
clone.Integers = make(map[string]int64)
for k, v := range c.Integers {
clone.Integers[k] = v
}
}
if len(c.Floats) > 0 {
clone.Floats = make(map[string]float64)
for k, v := range c.Floats {
clone.Floats[k] = v
}
}
if len(c.Options) > 0 {
clone.Options = make(map[string][]string)
for k, v := range c.Options {
clone.Options[k] = make([]string, len(v))
copy(clone.Options[k], v)
}
}
if len(c.EnvVars) > 0 {
clone.EnvVars = make(map[string]string)
for k, v := range c.EnvVars {
clone.EnvVars[k] = v
}
}
if len(c.Custom) > 0 {
clone.Custom = make(map[string]interface{})
for k, v := range c.Custom {
clone.Custom[k] = v
}
}
return clone
}
// String 返回命令的字符串表示
func (c *Command) String() string {
if c.Executed {
return fmt.Sprintf("%s (executed in %v, exit code: %d)", c.Name, c.Duration, c.ExitCode)
}
return fmt.Sprintf("%s (not executed)", c.Name)
}
// GetCurrentWorkingDir 获取当前工作目录
func getCurrentWorkingDir() string {
if dir, err := os.Getwd(); err == nil {
return dir
}
return "."
}
// CommandTypeToString 将命令类型转换为字符串
func CommandTypeToString(cmdType CommandType) string {
switch cmdType {
case SERVER:
return "server"
case CONFIG:
return "config"
case TEST:
return "test"
case VERSION:
return "version"
case HELP:
return "help"
default:
return "unknown"
}
}
// StringToCommandType 将字符串转换为命令类型
func StringToCommandType(s string) CommandType {
switch strings.ToLower(s) {
case "server", "serve", "start":
return SERVER
case "config", "conf", "cfg":
return CONFIG
case "test", "t":
return TEST
case "version", "v", "ver":
return VERSION
case "help", "h", "?":
return HELP
default:
return UNKNOWN
}
}