📃 docs: 部分完成
This commit is contained in:
554
aide-program/docs/01-入口脚本设计.md
Normal file
554
aide-program/docs/01-入口脚本设计.md
Normal file
@@ -0,0 +1,554 @@
|
||||
# 入口脚本设计
|
||||
|
||||
## 一、概述
|
||||
|
||||
### 1.1 设计目标
|
||||
|
||||
提供跨平台的统一命令行入口,使用户可以通过 `aide <command>` 的方式调用所有功能。
|
||||
|
||||
### 1.2 入口脚本清单
|
||||
|
||||
| 脚本 | 平台 | 说明 |
|
||||
|------|------|------|
|
||||
| `aide.sh` | Linux/macOS | Shell 脚本入口 |
|
||||
| `aide.bat` | Windows | 批处理脚本入口 |
|
||||
| `main.py` | 所有平台 | Python 主程序 |
|
||||
|
||||
---
|
||||
|
||||
## 二、aide.sh 设计(Linux/macOS)
|
||||
|
||||
### 2.1 功能要求
|
||||
|
||||
1. **定位 Python**:查找可用的 Python 3.10+ 解释器
|
||||
2. **定位脚本目录**:确定 main.py 的位置
|
||||
3. **传递参数**:将所有命令行参数传递给 Python 程序
|
||||
4. **处理错误**:Python 未找到时给出明确提示
|
||||
|
||||
### 2.2 实现示例
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
# Aide 命令行工具入口脚本(Linux/macOS)
|
||||
# 版本: 1.0
|
||||
|
||||
set -e # 遇到错误立即退出
|
||||
|
||||
# 获取脚本所在目录
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Python 主程序路径
|
||||
MAIN_PY="${SCRIPT_DIR}/main.py"
|
||||
|
||||
# 查找 Python 解释器
|
||||
find_python() {
|
||||
# 尝试查找 Python 3.10+
|
||||
for cmd in python3.12 python3.11 python3.10 python3 python; do
|
||||
if command -v "$cmd" &> /dev/null; then
|
||||
# 检查版本
|
||||
version=$("$cmd" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
|
||||
major=$(echo "$version" | cut -d. -f1)
|
||||
minor=$(echo "$version" | cut -d. -f2)
|
||||
|
||||
if [ "$major" -eq 3 ] && [ "$minor" -ge 10 ]; then
|
||||
echo "$cmd"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# 查找 Python
|
||||
PYTHON=$(find_python)
|
||||
|
||||
if [ -z "$PYTHON" ]; then
|
||||
echo "✗ Python 3.10+ 未找到" >&2
|
||||
echo " 建议: 安装 Python 3.10 或更高版本" >&2
|
||||
echo " 文档: https://www.python.org/downloads/" >&2
|
||||
exit 3
|
||||
fi
|
||||
|
||||
# 检查 main.py 是否存在
|
||||
if [ ! -f "$MAIN_PY" ]; then
|
||||
echo "✗ 找不到 main.py" >&2
|
||||
echo " 位置: $MAIN_PY" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 执行 Python 程序
|
||||
exec "$PYTHON" "$MAIN_PY" "$@"
|
||||
```
|
||||
|
||||
### 2.3 安装方式
|
||||
|
||||
```bash
|
||||
# 方式1:添加到 PATH
|
||||
export PATH="/path/to/aide:$PATH"
|
||||
|
||||
# 方式2:创建符号链接
|
||||
ln -s /path/to/aide/aide.sh /usr/local/bin/aide
|
||||
|
||||
# 方式3:添加别名
|
||||
alias aide='/path/to/aide/aide.sh'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、aide.bat 设计(Windows)
|
||||
|
||||
### 3.1 功能要求
|
||||
|
||||
1. **定位 Python**:查找可用的 Python 3.10+ 解释器
|
||||
2. **定位脚本目录**:确定 main.py 的位置
|
||||
3. **传递参数**:将所有命令行参数传递给 Python 程序
|
||||
4. **处理错误**:Python 未找到时给出明确提示
|
||||
|
||||
### 3.2 实现示例
|
||||
|
||||
```batch
|
||||
@echo off
|
||||
REM Aide 命令行工具入口脚本(Windows)
|
||||
REM 版本: 1.0
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM 获取脚本所在目录
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
|
||||
REM Python 主程序路径
|
||||
set "MAIN_PY=%SCRIPT_DIR%main.py"
|
||||
|
||||
REM 查找 Python 解释器
|
||||
set "PYTHON="
|
||||
for %%p in (python3.12 python3.11 python3.10 python3 python py) do (
|
||||
where %%p >nul 2>&1
|
||||
if !errorlevel! equ 0 (
|
||||
REM 检查版本
|
||||
for /f "delims=" %%v in ('%%p -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"') do (
|
||||
set "version=%%v"
|
||||
)
|
||||
|
||||
REM 解析版本号
|
||||
for /f "tokens=1,2 delims=." %%a in ("!version!") do (
|
||||
set "major=%%a"
|
||||
set "minor=%%b"
|
||||
)
|
||||
|
||||
REM 检查是否满足要求(3.10+)
|
||||
if !major! equ 3 if !minor! geq 10 (
|
||||
set "PYTHON=%%p"
|
||||
goto :found
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
:found
|
||||
if "%PYTHON%"=="" (
|
||||
echo ✗ Python 3.10+ 未找到 >&2
|
||||
echo 建议: 安装 Python 3.10 或更高版本 >&2
|
||||
echo 文档: https://www.python.org/downloads/ >&2
|
||||
exit /b 3
|
||||
)
|
||||
|
||||
REM 检查 main.py 是否存在
|
||||
if not exist "%MAIN_PY%" (
|
||||
echo ✗ 找不到 main.py >&2
|
||||
echo 位置: %MAIN_PY% >&2
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM 执行 Python 程序
|
||||
"%PYTHON%" "%MAIN_PY%" %*
|
||||
exit /b %errorlevel%
|
||||
```
|
||||
|
||||
### 3.3 安装方式
|
||||
|
||||
```batch
|
||||
REM 方式1:添加到 PATH
|
||||
set PATH=C:\path\to\aide;%PATH%
|
||||
|
||||
REM 方式2:创建批处理文件到系统目录
|
||||
copy aide.bat C:\Windows\System32\aide.bat
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、main.py 设计
|
||||
|
||||
### 4.1 功能要求
|
||||
|
||||
1. **命令分发**:根据第一个参数分发到对应的命令处理函数
|
||||
2. **参数解析**:解析命令行参数
|
||||
3. **错误处理**:统一的错误处理和退出码
|
||||
4. **帮助信息**:提供 `--help` 和 `--version` 支持
|
||||
|
||||
### 4.2 实现框架
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Aide 命令行工具主程序
|
||||
版本: 1.0
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# 添加 src 目录到 Python 路径
|
||||
SCRIPT_DIR = Path(__file__).parent
|
||||
sys.path.insert(0, str(SCRIPT_DIR))
|
||||
|
||||
from core.output import ok, warn, err, info
|
||||
from commands.init import cmd_init
|
||||
from commands.env import cmd_env
|
||||
from commands.config_cmd import cmd_config
|
||||
|
||||
|
||||
VERSION = "1.0.0"
|
||||
|
||||
|
||||
def show_help():
|
||||
"""显示帮助信息"""
|
||||
help_text = """Aide - AI 辅助开发工作流工具
|
||||
|
||||
用法:
|
||||
aide <command> [options]
|
||||
|
||||
命令:
|
||||
init 初始化 .aide 目录和配置文件
|
||||
env ensure 检测并修复项目开发环境
|
||||
env ensure --runtime 检测 aide 运行时环境
|
||||
config get <key> 获取配置值
|
||||
config set <key> <value> 设置配置值
|
||||
|
||||
选项:
|
||||
-h, --help 显示帮助信息
|
||||
-v, --version 显示版本信息
|
||||
|
||||
示例:
|
||||
aide init
|
||||
aide env ensure
|
||||
aide config get task.source
|
||||
aide config set task.source "new-task.md"
|
||||
|
||||
文档: https://github.com/your-org/aide
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
||||
def show_version():
|
||||
"""显示版本信息"""
|
||||
print(f"Aide v{VERSION}")
|
||||
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
# 解析参数
|
||||
args = sys.argv[1:]
|
||||
|
||||
# 无参数或帮助
|
||||
if not args or args[0] in ["-h", "--help", "help"]:
|
||||
show_help()
|
||||
return 0
|
||||
|
||||
# 版本信息
|
||||
if args[0] in ["-v", "--version", "version"]:
|
||||
show_version()
|
||||
return 0
|
||||
|
||||
# 获取命令
|
||||
command = args[0]
|
||||
|
||||
try:
|
||||
# 命令分发
|
||||
if command == "init":
|
||||
return cmd_init(args[1:])
|
||||
elif command == "env":
|
||||
return cmd_env(args[1:])
|
||||
elif command == "config":
|
||||
return cmd_config(args[1:])
|
||||
else:
|
||||
err(
|
||||
f"未知命令: {command}",
|
||||
[
|
||||
"可用命令: init, env, config",
|
||||
"使用 'aide --help' 查看帮助"
|
||||
]
|
||||
)
|
||||
return 2
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n")
|
||||
info("操作已取消")
|
||||
return 130 # 128 + SIGINT(2)
|
||||
|
||||
except Exception as e:
|
||||
err(
|
||||
"命令执行失败",
|
||||
[
|
||||
f"原因: {str(e)}",
|
||||
"使用 'aide --help' 查看帮助"
|
||||
]
|
||||
)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
```
|
||||
|
||||
### 4.3 命令处理函数接口
|
||||
|
||||
每个命令处理函数应该遵循以下接口:
|
||||
|
||||
```python
|
||||
def cmd_<command>(args: list[str]) -> int:
|
||||
"""命令处理函数
|
||||
|
||||
Args:
|
||||
args: 命令参数列表(不包含命令本身)
|
||||
|
||||
Returns:
|
||||
退出码(0 表示成功)
|
||||
"""
|
||||
pass
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、参数解析
|
||||
|
||||
### 5.1 简单参数解析
|
||||
|
||||
对于简单的命令,可以手动解析参数:
|
||||
|
||||
```python
|
||||
def cmd_env(args: list[str]) -> int:
|
||||
"""env 命令处理"""
|
||||
if not args:
|
||||
err("缺少子命令", ["使用 'aide env ensure' 检测环境"])
|
||||
return 2
|
||||
|
||||
subcommand = args[0]
|
||||
|
||||
if subcommand == "ensure":
|
||||
# 检查 --runtime 参数
|
||||
runtime_only = "--runtime" in args
|
||||
return env_ensure(runtime_only=runtime_only)
|
||||
else:
|
||||
err(f"未知子命令: {subcommand}", ["可用子命令: ensure"])
|
||||
return 2
|
||||
```
|
||||
|
||||
### 5.2 使用 argparse(可选)
|
||||
|
||||
对于复杂的命令,可以使用 argparse:
|
||||
|
||||
```python
|
||||
import argparse
|
||||
|
||||
def cmd_config(args: list[str]) -> int:
|
||||
"""config 命令处理"""
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="aide config",
|
||||
description="配置管理"
|
||||
)
|
||||
|
||||
subparsers = parser.add_subparsers(dest="subcommand")
|
||||
|
||||
# get 子命令
|
||||
parser_get = subparsers.add_parser("get", help="获取配置值")
|
||||
parser_get.add_argument("key", help="配置键")
|
||||
|
||||
# set 子命令
|
||||
parser_set = subparsers.add_parser("set", help="设置配置值")
|
||||
parser_set.add_argument("key", help="配置键")
|
||||
parser_set.add_argument("value", help="配置值")
|
||||
|
||||
try:
|
||||
parsed = parser.parse_args(args)
|
||||
except SystemExit:
|
||||
return 2
|
||||
|
||||
if parsed.subcommand == "get":
|
||||
return config_get(parsed.key)
|
||||
elif parsed.subcommand == "set":
|
||||
return config_set(parsed.key, parsed.value)
|
||||
else:
|
||||
parser.print_help()
|
||||
return 2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、错误处理
|
||||
|
||||
### 6.1 异常捕获
|
||||
|
||||
```python
|
||||
def main():
|
||||
"""主函数"""
|
||||
try:
|
||||
# 命令执行
|
||||
return execute_command()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
# Ctrl+C 中断
|
||||
print("\n")
|
||||
info("操作已取消")
|
||||
return 130
|
||||
|
||||
except FileNotFoundError as e:
|
||||
# 文件不存在
|
||||
err("文件不存在", [f"路径: {e.filename}"])
|
||||
return 5
|
||||
|
||||
except PermissionError as e:
|
||||
# 权限错误
|
||||
err("权限不足", [f"路径: {e.filename}"])
|
||||
return 1
|
||||
|
||||
except Exception as e:
|
||||
# 其他错误
|
||||
err("命令执行失败", [f"原因: {str(e)}"])
|
||||
return 1
|
||||
```
|
||||
|
||||
### 6.2 退出码规范
|
||||
|
||||
| 退出码 | 含义 |
|
||||
|-------|------|
|
||||
| 0 | 成功 |
|
||||
| 1 | 一般错误 |
|
||||
| 2 | 参数错误 |
|
||||
| 3 | 环境错误 |
|
||||
| 4 | 配置错误 |
|
||||
| 5 | 文件错误 |
|
||||
| 130 | 用户中断(Ctrl+C) |
|
||||
|
||||
---
|
||||
|
||||
## 七、测试
|
||||
|
||||
### 7.1 入口脚本测试
|
||||
|
||||
```bash
|
||||
# 测试 aide.sh
|
||||
./aide.sh --version
|
||||
./aide.sh --help
|
||||
./aide.sh init
|
||||
./aide.sh env ensure
|
||||
|
||||
# 测试 aide.bat(Windows)
|
||||
aide.bat --version
|
||||
aide.bat --help
|
||||
aide.bat init
|
||||
aide.bat env ensure
|
||||
```
|
||||
|
||||
### 7.2 main.py 测试
|
||||
|
||||
```python
|
||||
def test_main_help(capsys):
|
||||
"""测试帮助信息"""
|
||||
sys.argv = ["aide", "--help"]
|
||||
result = main()
|
||||
|
||||
assert result == 0
|
||||
captured = capsys.readouterr()
|
||||
assert "用法:" in captured.out
|
||||
|
||||
def test_main_version(capsys):
|
||||
"""测试版本信息"""
|
||||
sys.argv = ["aide", "--version"]
|
||||
result = main()
|
||||
|
||||
assert result == 0
|
||||
captured = capsys.readouterr()
|
||||
assert "Aide v" in captured.out
|
||||
|
||||
def test_main_unknown_command(capsys):
|
||||
"""测试未知命令"""
|
||||
sys.argv = ["aide", "unknown"]
|
||||
result = main()
|
||||
|
||||
assert result == 2
|
||||
captured = capsys.readouterr()
|
||||
assert "未知命令" in captured.out
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、安装和分发
|
||||
|
||||
### 8.1 目录结构
|
||||
|
||||
```
|
||||
aide/
|
||||
├── aide.sh # Linux/macOS 入口
|
||||
├── aide.bat # Windows 入口
|
||||
├── main.py # Python 主程序
|
||||
├── core/ # 核心模块
|
||||
├── commands/ # 命令实现
|
||||
└── utils/ # 工具函数
|
||||
```
|
||||
|
||||
### 8.2 安装脚本(可选)
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
# install.sh - Aide 安装脚本
|
||||
|
||||
set -e
|
||||
|
||||
INSTALL_DIR="${HOME}/.local/bin"
|
||||
|
||||
# 创建安装目录
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
|
||||
# 复制文件
|
||||
cp -r aide "$INSTALL_DIR/"
|
||||
|
||||
# 创建符号链接
|
||||
ln -sf "$INSTALL_DIR/aide/aide.sh" "$INSTALL_DIR/aide"
|
||||
|
||||
# 添加到 PATH
|
||||
if ! echo "$PATH" | grep -q "$INSTALL_DIR"; then
|
||||
echo "export PATH=\"$INSTALL_DIR:\$PATH\"" >> ~/.bashrc
|
||||
echo "✓ 已添加到 PATH"
|
||||
echo " 请运行: source ~/.bashrc"
|
||||
fi
|
||||
|
||||
echo "✓ Aide 安装完成"
|
||||
echo " 使用 'aide --help' 查看帮助"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 九、总结
|
||||
|
||||
### 9.1 核心要点
|
||||
|
||||
1. 提供跨平台的统一入口
|
||||
2. 自动查找合适的 Python 解释器
|
||||
3. 统一的命令分发和错误处理
|
||||
4. 清晰的帮助和版本信息
|
||||
|
||||
### 9.2 实现检查清单
|
||||
|
||||
- [ ] 实现 aide.sh(Linux/macOS)
|
||||
- [ ] 实现 aide.bat(Windows)
|
||||
- [ ] 实现 main.py 命令分发
|
||||
- [ ] 实现帮助和版本信息
|
||||
- [ ] 实现错误处理和退出码
|
||||
- [ ] 编写入口脚本测试
|
||||
- [ ] 验证跨平台兼容性
|
||||
- [ ] 编写安装脚本(可选)
|
||||
|
||||
---
|
||||
|
||||
**版本**:v1.0
|
||||
**更新日期**:2025-12-13
|
||||
Reference in New Issue
Block a user