feat: add shell completion generation (bash, fish, zsh)#8
Open
johanvx wants to merge 8 commits into
Open
Conversation
Author
|
@Sunrisepeak Would you mind checking this PR? |
Member
需要适配一下gcc 15 musl 工具链 |
Sunrisepeak
reviewed
Jul 13, 2026
Member
There was a problem hiding this comment.
已做了本地验证,建议优先按以下方向处理(CI 已可复现):
- 结论:问题更像是代码层的模块化链接性设计问题,而非单纯某个编译器"偶发"行为。
- 在
src/completions/bash.cppm中SubCmdEntry在匿名 namespace(TU-local) ScBranch在subcommand_details()函数体内(function-local)- 在
src/completions/zsh.cppm中也有SubCmdEntry在匿名 namespace std::vector<...>及其相关std::allocator实例化会把这些局部类型暴露到模块接口可见语义,gcc 15.1.0-musl 报exposes TU-local entity,该链路在 CI 上失败。
- 建议改法(最小改动):
- 将以上容器元素类型统一移到具名命名空间(例如
namespace mcpplibs::cmdline::completions::detail)且保有 module 可见链接; - 保留业务函数可在匿名命名空间;
flatten_subcommands/subcommand_detection_cases/subcommand_details等逻辑不变,仅调整类型定义位置与路径。
建议变更示例:
src/completions/bash.cppm- 移动
SubCmdEntry出匿名 namespace; - 移动
ScBranch出subcommand_details函数体到 file scope;
- 移动
src/completions/zsh.cppm- 同样将
SubCmdEntry移到 file scope 的具名命名空间。
- 同样将
- 验证(建议):
gh run view 29146418379 --log --job 86773636958当前失败链路保留;- 本地请固定用:
mcpp toolchain default gcc 15.1.0-muslmcpp build --workspace --no-cache
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TL;DR
Add
Shellenum,completions::Commandsnapshot, and three shell-completion generators (bash, fish, zsh) that produce native completion scripts for acmdline::App. The implementation is stripped-down fromclap_complete, matching what our data model (App/Option/Arg) actually supports: no aliases, no possible-values, no value-hints, no conflict annotations.Problem
mcpplibs.cmdlinehad no built-in mechanism to generate shell completions. Users who wanted tab-completion had to hand-write scripts for each shell (fishcomplete -c, bashcomplete -F, zsh_arguments), duplicating the option definitions already present in theirAppsetup.Approach
Port the three completion generators from
clap_complete(fish.rs,bash.rs,zsh.rs), stripping features thatcmdlinedoes not support. The stripping logic follows the pattern already established in our existing fish generator: only primary short/long names, bare file completion for value-taking options, global re-offer with dedup under subcommands.A
completions::Commandstruct captures a snapshot of theApptree (names, descriptions, options, args, subcommands) including auto-added--helpand--version. All three generators receive(const Command&, std::ostream&).Implementation
src/completions.cppmShellenum,Commandstruct,shell_from_string/to_string/shell_supportedhelperssrc/completions/bash.cppmcomplete -Fgenerator withcompgen -Wword-list matching and acase "${cmd}"dispatch switchclap_complete::bash.rssrc/completions/fish.cppmcomplete -cgenerator with-nconditions and helper functionssrc/completions/zsh.cppm#compdefgenerator with_argumentsspecs, recursivecase $statedispatch,_commands()helpersclap_complete::zsh.rssrc/cmdline.cppmsnapshot(), fourgenerate_completions()overloads,App::completions()App→Command→ shell outputtests/completions_test.cppdocs/api.mdexamples/completions/completionssubcommandArchitecture comparison (clap → cmdline)
Fishgeneratorgen_fish_innerrecursive walkgen_innerwithstd::span<Option>for root globalsBashgeneratorformat!template with placeholdersgenerate()without <<streaming, 7 helpers in anonymous namespaceZshgeneratorget_args_of/get_subcommands_of/subcommand_detailswalk_commandvs zsh identifiersget_short_and_visible_aliases(), subcommand aliasesshort_andlong_namepossible_values/ValueHintcompgen -W/_files/_command_namesetc._default(zsh) orcompgen -f(bash)(-x --y)prefix on specsCommand::build()root_globalsspan + dedupTrade-offs
completions::Commandis built eagerly viasnapshot(), copying vectors. For command trees with hundreds of subcommands this could be noticeable, but the typical case is negligible.walk_commandreturns a rawconst Command*. Callers must not hold it past the lifetime of the rootCommand.walk_command/flatten_subcommands/has_optionrather than sharing a utility module. This keeps each.cppmself-contained, matchingfish.cppm.Validation
All three generators produce valid output:
How to test
mcpp build(orxmake)xmake run cmdline_testcd examples/completions && mcpp build && ./target/*/bin/completions completions --shell bash