你可以通过 Tem - GitHub 获取项目的源代码。
唠嗑
我在 $HOME/Public/
目录下专门设置了一个文件夹 /templates
,里面放了一堆什么 *.gitignore
、*.json
之类的文件。每次从 Spring Initializr 弄下来什么工程,或是 yarn init
创了一个项目,就得 cp $HOME/Public/templates/
然后 Tab Tab 一会儿选中对应的文件。如果需要访问私有的 Maven 仓库,再 cp
一个 settings.xml
。如果是老项目,就得 ii
(这好像是一个 Cmd / PowerShell 下的命令,可能是早年我 alias
来的)一下,然后拷贝一份修改了镜像地址的 Maven Wrapper 来。如果是个打算内部推广的 Golang CLI 工具(最近常借着 copilot 学习写工具,这就是其中一个),那就 cp
一份 go-cross-compile.sh
。
Tab Tab 的问题在于它没法选到隐藏文件(至少默认配置是这样),而好多配置文件都是 .
开头的,这样久一点不用就想不起来文件叫什么名字了。而且像 Maven Wrapper 这样又是文件又是目录的,有时候感觉 Finder 还会快一些。
我这个需求既简单又杂乱,因此用 yeoman 这样的脚手架生成器就有些杀鸡用牛刀。差不多 2020 年的时候研究了下 Zsh,写了个支持自动补全的脚本,大概长这样:
#!/bin/zsh
function tem() {
GITIGNORE_JAVA="$CT_TEMPLATES_PATH/git/gitignore-java"
UML_CLASS="$CT_TEMPLATES_PATH/plantuml/class"
# ...
case $1 {
# gitignore
(gitignore-java)
cp $GITIGNORE_JAVA .gitignore
;;
# ...
(uml-class);&
(class)
TARGET_FILE=$2
cp $UML_CLASS ${TARGET_FILE:-class.wsd}
;;
# ...
}
}
compdef _autocomplate_template tem
function _autocomplate_template() {
local -a templates
# 获取 misc/ 下的所有文件,文件名作为提示符
for i ($CT_TEMPLATES_PATH/misc/*) {
templates+=($i:t)
}
templates+=(gitignore-java uml-class class)
# ...
_describe 'command' templates
}
- Tab Tab 能触发 Zsh 的补全动作
$HOME/Public/templates/misc/
下的同名文件能自动注册- 部分样板接受额外参数来构造目标文件名
- 支持样板别名
- 支持拷贝一组样板文件
不过我的 Zsh 水平止步于此,很难再做什么改进了。
所以搞了个 CLI 工具
首次安装或升级后需要执行 tem init
。tem 会检查 $HOME/.tem/
目录,并替换 $HOME/.tem/default/
的内容,最终效果就是:
$ tree /Users/yufan/.tem
├── custom
│ └── custom.toml
└── default
├── default.toml
├── git
│ ├── java.gitignore
...
default/
目录预置了一些样板文件,default/default.toml
描述了复制这些样板文件需要输入的命令。
如果用户还没有编写自定义配置,tem init
也会创建一个 custom/custom.toml
文件作为示例。虽然 tem 不会碰用户创建的 custom/
配置,还是备份一下以防万一比较好。
用户自定义配置和基础配置遵循相同的语法。以tem init
生成的示例 custom/custom.toml
为例:
[[template]]
key = "maven-wrapper"
assets = [
["custom/maven/mvnw", "mvnw"],
["custom/maven/mvnw.cmd", "mvnw.cmd"],
["custom/maven/maven-wrapper.jar", ".mvn/wrapper/maven-wrapper.jar"],
["custom/maven/maven-wrapper.properties", ".mvn/wrapper/maven-wrapper.properties"],
]
[[template]]
key = "golang"
assets = [
["https://www.toptal.com/developers/gitignore/api/goland+all,macos", ".gitignore"]
]
[config]
imports = [
"custom/some-custom-config-pull-from-repos/custom.toml",
"custom/like-github/custom.toml"
]
每一个 [[template]]
代表一组样板文件配置(我也不是很喜欢这种 List of Object 的语法),key
是这组样板文件的名称。assets
中的每一项都是一个数组,第一个元素是源,如果是文件的话,使用相对 $HOME/.tem/
的路径,如果是个 URL,tem 会请求这个 URL 并把响应写入目标文件。第二个元素是相对当前目录的目标文件路径,如果路径上的文件夹还不存在,tem 会创建。
[config]
是用来加载子配置的,imports
字段指示了其他需要载入的配置文件相对 $TEM_HOME
的路径。模版配置的加载使用深度优先的方案,即读取到子配置文件就先加载子配置文件中的内容,因此需要将可能重名且优先度较高的的模版 key 放在加载队列的后方。
输入 tem add maven-wrapper -y
,tem 就会在当前目录下准备好 Maven Wrapper 需要的文件。输入 tem add golang -y
,tem 就会从 Toptal 的服务下载融合了 goland + macos +linux + ...
需要的 .gitignore
文件。
为了防止时间久远后记不起执行命令的效果,试试不要键入 -y
,tem 会告诉你接下来准备干什么。
在 custom/custom.toml
中编写相同的 key
可以覆盖默认行为,不过如果用到了 default/
中的内容,还是建议复制一份到 custom/
,免得将来 tem 更新了默认配置。
tem 通过 github.com/spf13/cobra 实现对命令行参数的解析,顺便得到了自动补全功能,支持 bash、Zsh、fish、PowerShell 等 shell。
以 Zsh 为例,执行如下命令,在新的会话中即可使用 Tab 补全。
$ tem completion zsh > "$ZSH_CACHE_DIR/completions/_tem"
后面的打算
- 读取环境变量填充模版
再后边就应该差不多了,毕竟我可没打算做什么项目脚手架工具,那种事情还是交给 yeoman 和 cobra 比较好。