diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec99aa1..f0ee911 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,110 +2,41 @@ name: CI on: push: - branches: [main, master] + branches: [main] pull_request: - branches: [main, master] - -concurrency: - group: ci-${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true jobs: - build-linux: + build: name: build + test (linux x86_64, mcpp) - runs-on: ubuntu-24.04 - timeout-minutes: 30 - env: - MCPP_HOME: /home/runner/.mcpp + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - # mcpp's sandbox (musl-gcc + ninja + binutils) is multi-hundred-MB; - # key on mcpp.toml so toolchain changes refresh the cache. - - name: Cache mcpp sandbox - uses: actions/cache@v4 - with: - path: ~/.mcpp - key: mcpp-sandbox-${{ runner.os }}-${{ hashFiles('mcpp.toml') }} - restore-keys: | - mcpp-sandbox-${{ runner.os }}- - - - name: Cache xlings - uses: actions/cache@v4 - with: - path: ~/.xlings - key: xlings-${{ runner.os }} - restore-keys: | - xlings-${{ runner.os }}- - - - name: Bootstrap mcpp via xlings + - name: Install xlings env: - XLINGS_NON_INTERACTIVE: '1' + XLINGS_VERSION: 0.4.30 run: | - if [ ! -x "$HOME/.xlings/subos/default/bin/xlings" ]; then - curl -fsSL https://d2learn.org/xlings-install.sh | bash - fi - export PATH="$HOME/.xlings/subos/default/bin:$PATH" - xlings --version - xlings install mcpp -y - mcpp --version - echo "$HOME/.xlings/subos/default/bin" >> "$GITHUB_PATH" - - - name: Cache target/ (build artifacts + BMIs) + tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz" + curl -fsSL -o "/tmp/${tarball}" \ + "https://github.com/d2learn/xlings/releases/download/v${XLINGS_VERSION}/${tarball}" + tar -xzf "/tmp/${tarball}" -C /tmp + "/tmp/xlings-${XLINGS_VERSION}-linux-x86_64/subos/default/bin/xlings" self install + echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH" + + - name: Install workspace tools (.xlings.json → mcpp 0.0.11) + run: xlings install -y + + # Cache mcpp's self-bootstrapped sandbox (musl-gcc + binutils + + # glibc + ninja + patchelf, ~800 MB). Toolchain set is pinned by + # mcpp 0.0.11, so a fixed key suffices. + - name: Cache mcpp sandbox uses: actions/cache@v4 with: - path: target - key: mcpp-target-${{ runner.os }}-${{ hashFiles('src/**', 'tests/**', 'mcpp.toml') }} - restore-keys: | - mcpp-target-${{ runner.os }}- + path: ~/.xlings/data/xpkgs/xim-x-mcpp/0.0.11/registry + key: mcpp-sandbox-${{ runner.os }}-mcpp0.0.11 - - name: Build + - name: Build with mcpp run: mcpp build - - name: Test + - name: Run tests run: mcpp test - - # mcpp is Linux-x86_64 first; macOS/Windows support is still WIP, so the - # cross-platform xmake build keeps coverage for those targets. - build-macos: - name: build (macOS, xmake) - runs-on: macos-latest - steps: - - uses: actions/checkout@v4 - - - name: Setup xmake - uses: xmake-io/github-action-setup-xmake@v1 - with: - xmake-version: latest - package-cache: true - - - name: Install LLVM 20 - run: brew install llvm@20 - - - name: Build - run: | - xmake f --toolchain=llvm --sdk=/opt/homebrew/opt/llvm@20 - xmake -y -vv - - build-windows: - name: build + test (Windows, xmake) - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - - name: Setup xmake - uses: xmake-io/github-action-setup-xmake@v1 - with: - xmake-version: latest - package-cache: true - - - name: Build - run: xmake -y -vv - - - name: Test - run: xmake run cmdline_test - - - name: Run examples (smoke) - run: | - xmake run with_dispatch -- add python 3.12 - xmake run with_dispatch -- remove foo diff --git a/.xlings.json b/.xlings.json new file mode 100644 index 0000000..86555db --- /dev/null +++ b/.xlings.json @@ -0,0 +1,5 @@ +{ + "workspace": { + "mcpp": "0.0.89" + } +} diff --git a/README.md b/README.md index 1c765cf..cdef3ae 100644 --- a/README.md +++ b/README.md @@ -112,14 +112,31 @@ target("mytool") ### mcpp -在项目的 `mcpp.toml` 中声明依赖: +#### 添加依赖 + +```bash +mcpp add cmdline@0.0.2 +``` + +或在 `mcpp.toml` 中手动添加: ```toml [dependencies] -"mcpplibs.cmdline" = "^0.0.2" +cmdline = "0.0.2" +``` + +#### 构建 + +```bash +mcpp build ``` -然后在源码中 `import mcpplibs.cmdline;` 即可使用。 +#### 代码示例 + +```cpp +import mcpplibs.cmdline; +// ... 参见上方"快速开始" +``` ## 相关链接 diff --git a/docs/api.md b/docs/api.md index 33b2433..3a2d1e1 100644 --- a/docs/api.md +++ b/docs/api.md @@ -11,6 +11,8 @@ | `OptionValue` | 单个选项取值(flag 计数 + values) | | `ParseError` | 解析错误(kind + message) | | `Argv` | `std::vector` 的别名,用于 `parse_from` | +| `Shell` | 目标 shell 枚举:`bash` / `fish` / `zsh` | +| `Command` | 命令树快照,用于生成补全脚本 | 解析返回 `ParseResult`,即 `std::expected`。`-h`/`--help`、`--version` 时,`ParseError::kind` 分别为 `help` / `version`,不携带 `message`,通过 `is_error()` 可区分真实错误。 @@ -40,6 +42,14 @@ --- +## Shell + +| 函数 | 说明 | +|------|------| +| `shell_from_string(sv)` | 字符串 → `std::optional`(如 `"fish"` → `Shell::fish`) | +| `to_string(shell)` | `Shell` → `std::string_view` | +| `shell_supported(shell)` | 该 shell 补全是否已实现(fish / bash / zsh) | + ## ParseError | 成员 | 说明 | @@ -168,3 +178,66 @@ app.option(cmdline::Option("yes").long_opt("yes").global().help("Auto confirm")) app.arg(cmdline::Arg("input").required().help("Input file")); app.subcommand(cmdline::App("add").description("Add").arg(cmdline::Arg("x").required()).action([](const cmdline::ParsedArgs&) {})); ``` + +--- + +## Shell 补全 + +### 生成流程 + +1. 从 `App` 构建 `completions::Command` 树(`snapshot(app)` 或自动由 `generate_completions` 调用) +2. `Command` 包含名称、描述、版本、`Arg`/`Option` 列表、子命令列表 +3. 选择目标 `Shell` 后调用 `generate_completions`,输出补全脚本文本 + +### completions::Command + +| 成员 | 说明 | +|------|------| +| `name` | 命令名 | +| `description` | 描述文本 | +| `version` | 版本号 | +| `args` / `options` / `subcommands` | `vector` / `vector