- CLI
【免费下载链接】bash-it
A community Bash framework.
Bash-it 是一个社区驱动的 Bash 框架(仓库根目录见 bash_it.sh,社区协作是该项目持续演进的核心动力)。本文以官方文档 docs/contributing.rst 为骨架,系统讲解向 Bash-it 提交 Issues、Pull Request、代码风格规范、单元测试与 CI、功能集成原则以及主题与截图贡献的完整流程,并深入对应的仓库源码与测试用例进行印证。读完本文,你将掌握一套可直接照做的 Bash-it 贡献清单,包括如何让代码通过 lint 白名单、如何运行 bats 测试套件、以及如何规范化提交一个新主题。
贡献总览:先看 Issues,再提 Pull Request
官方指南开篇即强调:提交任何新功能、Bug 修复、新主题或其他改动之前,请先通读贡献规范。大部分条目属于常识,但务必遵守仓库既定的约定,避免维护者反复沟通。
关于 Issue,指南给出的核心建议是:报告 Bug 或请求新功能时,优先考虑直接附带一个 Pull Request——要么修复该问题,要么作为新功能的起点。文档原话提醒开发者"不必害怕,大多数事情并没有那么复杂",这与其"learning project"的定位一致(详见下文 Pull Request 部分)。
Pull Request 规范:一 PR 一事,鼓励展示过程
Pull Request 的提交流程有五个要点:
- Fork + 分支:Fork Bash-it 仓库,从master创建新的功能分支,在其中完成修改;再从该功能分支向 Bash-it 的master分支发起 Pull Request。
- 一 PR 一事:限制每个 Pull Request 只包含一个功能。不要把多个改动(例如一个新Theme加一个对既有插件的修复)打包进同一个 PR——主题单独一个 PR,修复单独一个 PR。
- Squash 提交:对于复杂改动,推送前尽量把变更squash成单个提交;推送并开 PR 之后,请不要再对 PR 分支进行 force-push——Bash-it 是分布式项目,你的分支可能已经被他人使用。
- 宁多勿少:拿不准时,宁可提交包含较多 commit 的 PR。Bash-it 对参与者而言是一个学习项目,展示你的工作过程能为后来者留下宝贵的"什么可行、什么不可行"的历史记录。
- CI 是门槛:任何推送到 PR 的代码都会自动触发 GitHub Actions 上的持续集成构建,测试套件会在 Linux 和 macOS 上同时运行,PR 页面会展示构建结果。带构建问题的 PR 不会被合并,务必关注 CI 状态。
代码风格:从 lint 白名单到 Bash 3.2 兼容
代码风格章节是贡献者最容易踩坑的地方,官方规范从以下六个维度给出了硬性要求。
1. clean_files.txt 白名单与本地 lint
新增文件时,务必把新文件加入 clean_files.txt——这是项目中"被 lint 检查文件"的不断增长的清单;修改既有文件时,也建议将其加入清单并修复随之而来的 lint 错误(详见下方"本地运行 lint"一节)。
从仓库实现看,clean_files.txt 是一个允许清单(Allow-list),支持目录引用(如themes/powerline会展开为目录下所有文件)与根文件引用(如 install.sh、uninstall.sh);空行与#注释行会被忽略。实际执行器是 lint_clean_files.sh,其逻辑为:读取clean_files.txt,过滤空行与注释行,用xargs -I{} find "{}" -type f把目录引用展开成具体文件列表,随后清空BASH_IT变量(帮助 shellcheck 识别source包含,规避 SC1090 警告),最后执行pre-commit run --files "${FILES[@]}"。也就是说,本地验证 lint 只需运行:
./lint_clean_files.sh2. 缩进与 EditorConfig
缩进使用tabs而非空格——文档特别指出,代码中大部分用 2 空格缩进、少部分用 4 空格 tabs,请尽量统一为 tabs。如果编辑器支持 EditorConfig,会自动采用仓库 .editorconfig 中的设置。
从 .editorconfig 的源码可以印证这套约定:[*]全局段默认indent_style = space, indent_size = 2(对应"大部分代码 2 空格"),而[{**.*sh,test/run,**.bats}]段则将 shell 脚本与 bats 测试统一为indent_style = tab, indent_size = tab,并附带shell_variant = bash、binary_next_line、switch_case_indent等 shell 专属选项;[**.bats]段进一步指定shell_variant = bats。此外还有trim_trailing_whitespace = true、insert_final_newline = true等收尾约束。
3. 用 command 内建调用命令
优先使用 shell 内建command直接调用命令,保证执行的永远是你想要的真实命令,而不是被同名的 alias/函数覆盖后的版本。例如用command rm而非rm。
仓库中 plugins/available/base.plugin.bash 的down4me函数就是标准示范:
command curl -Ls "http://downforeveryoneorjustme.com/${site}" | command sed '/just you/!d;s/<[^>]*>//g'4. 函数命名:短横线分隔,下划线留给内部
- 新建函数时,用短横线
-分隔单词,例如my-new-function,不要用下划线(如my_new_function)。 - 不面向终端用户使用的内部函数,应以一个下划线开头,例如
_my-new-internal-function。
对照 lib/helpers.bash 源码,可以看到项目自身严格执行该约定:_about、_enable-plugin、_disable-plugin、_command_exists等内部函数均以下划线开头,而对外暴露的_enable-plugin、_disable-plugin这类"组件开关"函数则用短横线连接单词。
5. 使用 meta 函数文档化代码
请使用项目提供的 meta 函数来为代码编写文档,包括about-plugin、about、group、param、example等,这会大大方便其他人使用你的新功能。官方示例即 plugins/available/base.plugin.bash。
从该文件开头可以看到完整的元信息写作范式:
cite about-plugin about-plugin 'miscellaneous tools' url "https://github.com/Bash-it/bash-it" function ips() { about 'display all ip addresses for this host' group 'base' # ... }而 lib/helpers.bash 中_about、_param、_example等基础设施函数(如第 1084 行cite _about _param _example)则负责把这类元信息注册进 Bash-it 的组件注册表,支撑bash-it help、组件搜索等能力,这正是"meta 函数让功能更易被他人使用"的底层实现。
6. 文件命名与安装兼容
新增文件时遵循既有命名约定,例如插件文件必须以.plugin.bash结尾——这对安装功能至关重要。仓库中 plugins/available 下的全部插件、aliases/available 下的别名、completion/available 下的补全脚本都严格遵守这一命名规则。
7. $BASH_IT 务必加双引号
凡使用$BASH_IT变量,务必用双引号包裹,以保证 Bash-it 安装在含空格的目录时依然工作:
for f in "${BASH_IT}/plugins/available"/*.bash ; do echo "$f" ; done8. 坚持 Bash 3.2 兼容,必要时自禁用
Bash-it 支持Bash 3.2 及以上版本,请勿使用仅 Bash 4 才有的特性(如关联数组 associative arrays)。如果你确有非 Bash 4 不可的酷插件或特性,可以参考 plugins/available/pack.plugin.bash 的自禁用与原因记录写法,让 Bash 3.2 用户不会卡在不必要的报错上。
从 plugins/available/pack.plugin.bash 源码可以看到该模式的完整实现——它正是为 Bash 4+ 关联数组而写的packCLI 补全:
# Requires bash 4+ for associative arrays # Skip loading if bash version is too old if [[ "${BASH_VERSINFO[0]}" -lt 4 ]]; then _disable-plugin pack return 0 fi_disable-plugin的行为在 lib/helpers.bash 中定义(第 966 行附近),并配有专门测试:见 test/lib/helpers.bats 中多组run _disable-plugin "sdkman"、run _disable-plugin "nvm"、run _disable-plugin "all"的用例,分别覆盖了按名称禁用插件与一键禁用全部组件的场景。
单元测试:用 Bats 验证你的改动
新增功能或修改/修复时,务必运行不断增长的单元测试套件,确认没有引入回归。测试套件虽未覆盖 Bash-it 的全部方面,但请无论如何都运行一遍。
运行测试套件
在克隆 Bash-it 的目录中直接执行:
test/run从 test/run 源码看,该脚本的执行逻辑非常清晰:
- 定位自身目录并导出
MAIN_BASH_IT_DIR与MAIN_BASH_IT_GITDIR两个环境变量供测试使用; - 执行
git submodule init && git submodule update,确保本地test_lib目录中存在 Bats 测试框架(Bats 以 Git 子模块形式引入,对应 test_lib/bats-core、test_lib/bats-assert、test_lib/bats-file、test_lib/bats-support 四个子模块目录); - 若工作区有未提交更改(
git diff非空),会提示"dirty worktree,未提交的改动不会被测试"; - 无参数时默认依次运行
test_directory下的bash_it、completion、install、lib、plugins、themes六个测试目录;也可以传入目录参数精确指定测试范围; - 检测到 GNU
parallel时启用并行模式:默认通过nproc探测 CPU 核数(至少按双核处理),也可用环境变量TEST_JOBS手动指定并发数;在 CI 环境下(CI变量非空)会追加--tap参数输出 TAP 格式结果,便于 CI 解析。
脚本会逐个执行每个测试并打印每个用例的状态。实际测试文件可参考 test/lib/helpers.bats、test/plugins/base.plugin.bats、test/bash_it/bash_it.bats 等既有用例。
新增测试的最佳实践
修改代码库时,请考虑为新增或变更的功能补充单元测试,这是提升 Bash-it 测试覆盖率的好机会;修复 Bug 时,理想情况是同时新增一个验证该 Bug 不再复现的测试。新增测试用例前,先看看既有测试的写法。官方推荐使用以下 Bats 生态库中的assert系列函数来校验测试结果:
- 测试框架:Bats Core(
bats-core) - Bats-Assert 支撑库:
bats-support - 通用
assert函数:bats-assert - 文件
assert函数:bats-file
功能贡献原则:集成而非复制
添加新的补全(completion)或插件(plugin)时,不要把现有工具简单地复制进 Bash-it 代码库,而应尽量加载/集成这些工具。官方给出的范例是nvm:Bash-it 不再内置 nvm 脚本,而是由 plugins/available/nvm.plugin.bash 尝试加载用户已有的 nvm 安装。
从 plugins/available/nvm.plugin.bash 源码可以完整看到这一"集成优先"的落地方式:
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}" # first check if NVM is managed by brew NVM_BREW_PREFIX="" if _bash_it_homebrew_check; then NVM_BREW_PREFIX=$(brew --prefix nvm 2> /dev/null) fi # This loads nvm if [[ -n "$NVM_BREW_PREFIX" && -s "${NVM_BREW_PREFIX}/nvm.sh" ]]; then source "${NVM_BREW_PREFIX}/nvm.sh" else [[ -s "$NVM_DIR/nvm.sh" ]] && source "$NVM_DIR/nvm.sh" fi if ! _command_exists nvm; then function nvm() { echo "Bash-it no longer bundles the nvm script. Please install the latest version ..." } nvm fi它的思路是:优先检查 Homebrew 托管的 nvm(brew --prefix nvm),其次回退到用户$HOME/.nvm下的标准安装;如果都没找到,则定义一个提示性的nvm函数引导用户自行安装。这样做的代价是用户需要多一步(从 nvm 自己的仓库或通过包管理器安装 nvm),但好处是nvm 可以被轻松升级,Bash-it 不会因捆绑旧版脚本而拖慢工具迭代。
主题(Theme)贡献:截图、描述与文档缺一不可
提交新主题时,请在 PR 的描述(description)字段中附上截图和一段简述该主题独特性的文字。不要把主题截图提交进 PR 本体——它们会给主分支带来不必要的体积膨胀。
主题相关约定还有两条:
- 项目文档的 Themes 页面 汇总了 Bash-it 内置主题的截图与文档索引,贡献者应在其中添加截图(添加方法见下文"添加截图"一节)。
- 理想情况下,应在 docs/themes-list 目录中新增一个
<theme_name>.rst文件,描述该主题及其配置选项。
从仓库现状看,该目录下的 barbuk.rst、powerline.rst、nwinkler_random_colors.rst 等即是为各主题维护的文档条目,而 index.rst 通过.. toctree::的:glob:方式自动收录目录内所有主题文档,并提供了按字母排序的截图列表。
添加截图:走 gh-pages 分支
为新增主题添加截图的正确姿势是使用gh-pages分支:
- 把新截图添加到
docs/images文件夹; - 打开一个 PR;
- 参照 Themes 页面 中其他截图的写法,确定你的链接格式。
需要说明的是,截图实际托管在 gh-pages 分支而非 master 分支上(文档页中的截图均通过https://bash-it.github.io/bash-it/docs/images/...形式引用),这正是不把截图并入主分支、避免 master 膨胀的核心原因。
结语:一份可直接执行的贡献清单
把以上规范浓缩成提交 Bash-it 前的自检清单:
- 从master切出功能分支,一个 PR 只做一件事
- 新增/修改的文件已加入 clean_files.txt,并运行 lint_clean_files.sh 确认 lint 通过
- 缩进为 tabs(shell 脚本与 bats 用例),函数名用
-分隔、内部函数以下划线开头 - 调用外部命令时使用
command内建 - 用
about-plugin/about/group/param/example等 meta 函数写好文档 - 所有
$BASH_IT均加双引号,避免 Bash 4 专属特性 - 运行
test/run,为新增/变更功能补充 bats 测试用例,确认 CI(Linux + macOS)通过 - 新插件/补全优先集成既有工具而非复制;新主题在 PR 描述中附截图与简介,并把
<theme_name>.rst与截图分别提交到对应位置
参照 docs/contributing.rst 与本文的源码级注解,即使是第一次向 Bash-it 提交代码的贡献者,也能平稳地走完从 fork 到合并的完整流程。
- CLI
【免费下载链接】bash-it
A community Bash framework.
相关推荐
Powerline 代码贡献指南:从分支规范、代码风格到测试与提交合并的完整工程实践
Powerline 代码贡献指南:从分支规范、代码风格到测试与提交合并的完整工程实践 Powerline 是一个用 Python 编写的状态栏插件框架,为 vi
开发工具CLILangChainGo 贡献指南:从代码风格、httprr 测试到 PR 提交流程的完整实战手册
LangChainGo 贡献指南:从代码风格、httprr 测试到 PR 提交流程的完整实战手册 LangChainGo( langchaingo )是使用 G
人工智能大模型AI AgentRAG后端Anubis 贡献指南实战:从构建、测试到代码风格与提交规范
Anubis 贡献指南实战:从构建、测试到代码风格与提交规范 本篇指南基于 Anubis 项目官方贡献文档( docs/docs/developer/CONTR
后端网络安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考