造轮子工程 · 第 3 章 造命令行工具与 CLI 框架 章节摘要:如果造 Shell 是「造工具的工具」,那造命令行工具(CLI)就是「造你天天用的工具」。这是本书里工程收益最直接、回报最快的一章——你造的小 CLI 当天就能用上,而且造一个 CLI 框架(让别人在你的框架上写命令)能教会你「API 设计」这门核心功夫。本章导读 CLI 的五个核心子系统:参数解析(从最朴素的 数组,到 getopt/getopts,再到 subcommand 风格,三种模式的取舍)、配置文件(YAML/TOML/JSON 的读取与默认值合并)、彩色与格式化输出(ANSI 转义码、表格、进度条)、交互输入(确认、密码、选择菜单)、打包分发(从单文件脚本到跨平台二进制)。
章节摘要:如果造 Shell 是「造工具的工具」,那造命令行工具(CLI)就是「造你天天用的工具」。这是本书里工程收益最直接、回报最快的一章——你造的小 CLI 当天就能用上,而且造一个 CLI 框架(让别人在你的框架上写命令)能教会你「API 设计」这门核心功夫。本章导读 CLI 的五个核心子系统:参数解析(从最朴素的
argv数组,到 getopt/getopts,再到 subcommand 风格,三种模式的取舍)、配置文件(YAML/TOML/JSON 的读取与默认值合并)、彩色与格式化输出(ANSI 转义码、表格、进度条)、交互输入(确认、密码、选择菜单)、打包分发(从单文件脚本到跨平台二进制)。我们以「造一个带子命令的待办事项工具 todo」为贯穿例子,讲清每一步。读完本章,你能造一个自己天天用、能分发给同事的 CLI 小工具,并理解为什么 argparse/click/cobra 这类框架要那样设计。
阅读完本章,你应当能够:
argv、getopt/getopts(短选项)、subcommand(子命令,如 git add/git commit)。-v vs 长选项 --verbose)、默认值、必选/可选参数、-h 帮助。y/N、密码隐藏输入、选择菜单),理解为什么交互要谨慎(破坏脚本化)。一个好 CLI 的设计哲学:可脚本化优先(任何操作都能用命令行完成,不依赖交互)、约定优于配置(默认值合理)、组合优于单体(能被管道与其他命令串起来)。这三条是 Unix 工具能流传五十年的根因。
从最朴素的「直接读 argv 数组」开始,讲到 getopt/getopts(短选项 + 长选项),再到现代 subcommand 风格(mytool add ... / mytool list ...)。讲清三种模式各自的适用场景与局限,为什么复杂工具最终都走向 subcommand。
好接口的几条约定:短选项 -v 与长选项 --verbose 对应、必选参数报错而非静默、-h/--help 永远有效、退出码语义清晰(0 成功,非零按错误类型编码)。呼应《Linux 命令》第 1 章的「退出码」与「求助四件套」。
复杂 CLI 通常支持配置文件(避免每次敲一长串选项)。讲清配置文件格式选型(YAML/TOML/JSON 的取舍)与「命令行参数 > 配置文件 > 内置默认值」的三级合并规则。这是「约定优于配置」的工程实现。
ANSI 转义码的基础(颜色、粗体、清屏),以及如何检测「输出是不是终端」来决定要不要加色(管道时自动去色,这是好 CLI 的细节)。再讲简单表格与进度条的实现思路。
y/N 确认、密码隐藏输入(关闭终端回显)、选择菜单(编号选择)。重点讲清「交互是脚本化的敌人」——好 CLI 只在必要时交互,且总提供 --yes 跳过交互的选项。
脚本语言(Python/Node)用包管理器分发,编译型语言(C/Go/Rust)出跨平台二进制。讲清版本管理、依赖锁定、README 与 --help 自动生成,以及为什么「单二进制」是分发的圣杯。
把前六节串起来,设计一个完整的 todo CLI:支持 todo add/todo list/todo done/todo rm 子命令、配置文件存默认优先级、彩色输出、打包分发。这是本章的综合应用题,也是「造你自己天天用的工具」的模板。
本章遵循「输入 → 接口 → 配置 → 输出 → 分发 → 综合」的递进路径,从「怎么接参数」到「怎么造完整工具」:
参数解析 (01) ── 怎么读 argv │ ▼ 接口设计 (02) ── 怎么设计得合理 │ ▼ 配置合并 (03) ── 怎么避免每次敲长串 │ ▼ 彩色输出 (04) ── 怎么让输出好看且可脚本化 │ ▼ 交互输入 (05) ── 怎么处理需要用户确认的场景 │ ▼ 打包分发 (06) ── 怎么让别人用上 │ ▼ 综合 todo (07) ── 全章综合应用 │ ▼ 第 4 章:从"用正则"上升到"造正则引擎"
前六节是「单点能力」,每节解决 CLI 的一个侧面;第 7 节是综合,把它们组装成一个完整工具。本章与第 2 章(造 Shell)形成对照:Shell 是「造一个能执行任意命令的程序」,CLI 是「造一个专门解决某问题的命令」——两者互补,合起来就是你在终端里的全部「自造工具箱」。
前置知识:
本章为后续章节奠定的基础: