Files
teai/internal/cli/cli.go
T
ceoandchenyunda218 bc46620d04 初始化專案:Go 模組骨架、CLI 進入點、README、測試
- go.mod(module gitea.alterminal.com/alterminal/teai,Go 1.26)
- cmd/teai/main.go:程式進入點,結束碼交由 internal/cli.Run 處理
- internal/cli:命令列架構(引數剖析、子命令分派、version 命令)
- internal/cli/cli_test.go:用法輸出、version、未知命令等基本測試
- README.md:專案說明、建置與開發慣例(繁體中文)
- .gitignore:建置產物、測試輸出、環境檔
- 僅使用標準庫,可離線建置;授權待維護者選定

Refs #1
2026-09-09 23:06:39 +08:00

115 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 套件 cli 提供 teai 的命令列架構:引數剖析、子命令分派與輸出。
//
// 設計目標是讓之後新增子命令時只需註冊一個 command 結構,
// 不需要改動分派邏輯;也讓核心功能可以被測試(Run 接受 io.Writer)。
package cli
import (
"flag"
"fmt"
"io"
"sort"
)
// Version 是目前開發中的版本號。採用語意化版本;正式發佈前以 0 開頭。
var Version = "0.1.0-dev"
// ExitCode 是 Run 回傳的行程結束碼。
type ExitCode int
// 常見的結束碼定義。0 表示成功,其餘對應常見的命令列錯誤情境。
const (
ExitOK ExitCode = iota // 成功
ExitUsage // 引數或子命令錯誤
ExitInternal // 內部錯誤(不該發生)
)
// command 定義一個子命令:名稱、一行說明與實作。
type command struct {
name string
usage string
run func(env *Env, args []string) error
}
// Env 聚集一次執行所需的輸出目標,便於測試時替換。
type Env struct {
// Out 是一般輸出(命令結果)。
Out io.Writer
// Err 是診斷輸出(錯誤、警告)。
Err io.Writer
}
// commands 是已註冊的子命令表。新增功能時在這裡註冊即可。
var commands = map[string]*command{
"version": {
name: "version",
usage: "顯示版本資訊",
run: runVersion,
},
}
// Run 剖析引數並分派到對應子命令,回傳行程結束碼。
//
// 無引數或要求說明(-h/--help)時印出用法;未知子命令回 ExitUsage。
func Run(stdout, stderr io.Writer, args []string) int {
env := &Env{Out: stdout, Err: stderr}
if len(args) == 0 {
printUsage(env.Out)
return int(ExitOK)
}
switch args[0] {
case "-h", "--help", "help":
printUsage(env.Out)
return int(ExitOK)
case "-v", "--version", "version":
return dispatch(env, "version", args[1:])
default:
name := args[0]
if _, ok := commands[name]; !ok {
fmt.Fprintf(stderr, "teai: unknown command %q\n\n", name)
printUsage(stderr)
return int(ExitUsage)
}
return dispatch(env, name, args[1:])
}
}
// dispatch 執行已註冊的子命令,把錯誤轉成結束碼並輸出。
func dispatch(env *Env, name string, args []string) int {
cmd := commands[name]
fs := flag.NewFlagSet("teai "+name, flag.ContinueOnError)
fs.SetOutput(env.Err)
if err := fs.Parse(args); err != nil {
return int(ExitUsage)
}
if err := cmd.run(env, fs.Args()); err != nil {
fmt.Fprintf(env.Err, "teai %s: %v\n", name, err)
return int(ExitInternal)
}
return int(ExitOK)
}
// runVersion 輸出版本資訊。
func runVersion(env *Env, args []string) error {
fmt.Fprintf(env.Out, "teai version %s\n", Version)
return nil
}
// printUsage 印出用法與已註冊的子命令清單(依名稱排序)。
func printUsage(w io.Writer) {
fmt.Fprintf(w, "teai — Gitea CLI 輔助工具(tea + AI)\n\n")
fmt.Fprintf(w, "用法:\n teai [命令] [參數]\n\n命令:\n")
names := make([]string, 0, len(commands))
for name := range commands {
names = append(names, name)
}
sort.Strings(names)
for _, name := range names {
fmt.Fprintf(w, " %-10s %s\n", name, commands[name].usage)
}
fmt.Fprintf(w, "\n說明:\n -h, --help 顯示說明\n -v, --version 顯示版本\n")
fmt.Fprintf(w, "\n更多資訊:https://gitea.alterminal.com/alterminal/teai\n")
}