mcpField
S
shell-snippet-fmt

shell-snippet-fmt

github.com/petr-korobeinikov开发162 次安装2 天前更新
代码仓库

关于 shell-snippet-fmt

shell-snippet-fmt 是一项用于规范 Shell 代码片段格式的技能,旨在保持可读性并避免改变命令行为。它规定每行不超过 120 列,并说明长命令的安全换行方式。

主要功能

  1. 01每行最多 120 列
  2. 02命令的安全续行位置
  3. 03引号字符串与 heredoc 规则
  4. 04文档和脚本中的格式指南

适用场景

  1. 01整理文档中的长 Shell 命令
  2. 02编辑含超长命令行的脚本
  3. 03检查聊天或差异中的 Shell 片段

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/petr-korobeinikov/skills --skill shell-snippet-fmt

安装后在 Claude Code 中输入/shell-snippet-fmt确认已加载。

详细介绍

shell-snippet-fmt

始终对 shell 代码片段进行格式化,确保每行不超过 120 列。 如果某行将超过此限制, 请在安全的位置换行,并在行尾添加 \。

原因

120 列的上限能让代码片段在窄终端、 GitHub 差异视图、 并排审阅窗格 和聊天窗口中都易于阅读。 显式使用 \ 续行是唯一一种可移植的方式,可在不改变 shell 命令语义的情况下换行 — shell 会原样保留引号字符串和 heredoc 中的空白, 因此在这些位置换行会改变程序行为。

规则

  • shell 代码片段的每一行都应保持 ≤120 个视觉列宽 (每个字符占一列,不论字节宽度)。
  • 如果某行将超过此限制, 请在仍能符合限制的最靠后安全位置换行, 并在行尾添加 \。
  • \ 后面不能有任何内容 — 甚至不能有空格或注释; 只能是换行符。
  • 续行相对于命令起始位置缩进 4 个空格。
  • 如果代码片段本来就能在 120 列以内放在一行, 可以保持单行, 也可以在多行形式更清晰时换行 (复杂管道、多个标志、heredoc、短参数之间的长 URL)。 可读性优先于紧凑性; 120 列是硬性上限,而非目标。

安全的换行位置

只能在 shell 仍会将结果解析为一个逻辑命令的位置换行:

  • 在标志前(--flag 或 -f value)。
  • 在管道符前(|)。
  • 在逻辑运算符前(&&、||)。
  • 在重定向符前(>、>>、<、2>&1)。
  • 在位置参数之间, 前提是每个参数都是独立的词元。

绝不能在以下位置换行

  • 引号字符串内部 — 在 '...' 中,\<newline> 会按字面内容保留 (单引号不会解释转义符), 因此打印出的文本会多出一个反斜杠和换行符; 在 "..." 中,POSIX 会将 \<newline> 视为续行符 并静默移除两者, 将前后文本拼接在一起。 无论哪种情况,呈现的字符串都会与单行版本不同。
  • heredoc 正文内部(从开头的 <<EOF 到结束标记之间) — 内容会原样传递给命令, 因此插入的 \<newline> 会成为数据的一部分。
  • 未加引号的词元内部 — 拆分会改变词边界。
  • URL、 路径、 标识符 或任何其他不可拆分的单元内部。

如果一个不可拆分的词元本身就超过 120 列, 请保留超限行, 并在周围文本中注明此例外, 让读者知道这是有意放宽上限。

示例

错误 — 单行长达 138 列:

docker run --rm -it --name foo -v "$PWD:/work" -w /work -e FOO=bar -e BAZ=qux ghcr.io/example/tool:1.2.3 build --target prod --output dist

正确 — 使用 \ 换行,每行均 ≤120 列:

docker run --rm -it --name foo \
    -v "$PWD:/work" \
    -w /work \
    -e FOO=bar \
    -e BAZ=qux \
    ghcr.io/example/tool:1.2.3 \
    build --target prod --output dist

接下来的三个示例(管道符、逻辑运算符、heredoc)保持简短, 以便清楚展示换行约定 — 仍应遵循“仅在有助于可读性时换行”的规则, 但在需要换行时应采用以下形式。

管道符放在续行的行首, 并在前一行末尾使用 \:

curl -sSL https://example.com/data.json \
    | jq '.items[]' \
    | head -20

逻辑运算符遵循相同的约定:

docker build -t image:tag . \
    && docker push image:tag \
    && echo "deployed"

heredoc — 换行处理周围的命令, heredoc 正文保持原样(不添加 \,保留原始行):

ssh -o ConnectTimeout=10 \
    -o StrictHostKeyChecking=no \
    deploy@host bash <<'EOF'
cd /app
./run --restart
EOF

错误 — 在 \ 和换行符之间添加注释会中断续行:

docker run \  # mount the work dir
    -v "$PWD:/work" image

\ 后面跟着空格和 #,而不是换行符, 因此 shell 会停止续行, 并将下一行的 -v 解析为单独的命令。 请将注释放在命令上方的独立行中, 切勿放在行尾的 \ 后面。

错误 — 在引号字符串内部换行会改变程序输出:

echo 'this is a very long error message that needs to clearly demonstrate \
exceeding the 120-character width limit when written on one line'

在单引号中,\<newline> 会按字面内容打印为 \ + 换行符; 在双引号中,POSIX 会将其移除并拼接相邻文本 — 无论哪种情况,结果都与单行版本不同。 即使行长超过 120 列,也要保持字符串完整:

echo 'this is a very long error message that needs to clearly demonstrate exceeding the 120-character width limit when written on one line'

长的不可拆分词元(URL、路径、哈希)同理:

curl -O https://github.com/very-long-org-name/very-long-repo-name/releases/download/v1.2.3-rc.4/binary-name-linux-amd64.tar.gz

请在周围文本中注明超限行,让读者知道这是有意放宽了上限。

适用范围

适用于你编写或编辑的任何 shell 片段:

  • 聊天回复中的围栏代码块。
  • SKILL.md / README.md / 文档中的代码片段。
  • scripts/ 下的脚本。
  • Makefile 配方。
  • CI 配置(GitHub Actions 的 run:、GitLab 的 script:)。
  • Dockerfile 的 RUN 指令。
  • 安装说明和单行命令。

如果编辑文件时遇到很长且未换行的命令, 请在同一次编辑中对其重新排版。

评论

支持 Markdown