用 just 组织和管理常用命令集
在日常使用电脑的过程中,经常会用到一些命令,并且可能要将一组命令结合才能完成自己想要的结果。如果常用的一些命令(组合)每次使用都重新敲的话,势必会影响效率。此时你可能会想到类似于 make 这样的工具,当然这也是一个选择,但是 make 的缺点也是显而易见的(有兴趣的可以通过 makefile 介绍 — 跟我一起写 Makefile 1.0 文档 来入门)。几个月前我无意中发现了just,感觉在日常使用中完全可以替代 make。
just 语法和 make 很类似,如果你有 make 基础的话,可以很快上手。下面简单介绍一下 just 的用法以及和 make 的一些区别(首先一个区别是 Makefile 中每个执行项叫做目标(target),而 just 中叫做配方(recipe)):
-
首先 just 和 make 一样,需要一个 Justfile(make 是 Makefile,just 这个文件的文件名可以是 Justfile、justfile 或者 .justfile 等),不区分大小写,可以在前面加个
.
来隐藏这个文件。just 会从当前目录向上查找 justfile 文件,而 make 不会。 这就意味着只有某一个父级目录存在一个 justfile 文件,那就可以执行该 justfile 里的相关的代码。 -
如果 Makefile 的在当前目录下存在一个文件,这个文件和某个 target 名称相同,则这个 target 就不会执行,并且打印出错误信息:
make: xxx' is up to date.
,此时你需要在 Makefile 文件中加上一样.PHONY xxx
来防止此问题的发生,just 则没有此问题。 -
Makefile 中 target 可以对另一个 target 进行依赖(即先执行另一个 target,执行完毕后在执行当前的 target),just 也可以,而且 just 还有“后依赖”,例如:
1 | list_file := "formulae-list.json" |
在执行了 just generate-list
之后,会执行 preview
这个 recipe。
- just 中 recipe 支持配方参数:
1 | recipe P='D': |
上面的例子中 recipe
有一个参数 P
,并且有个默认值 D,可以在下面的命令中用 {{P}}
来使用这个参数(使用的是mustache来进行变量替换),除此之外还可以用 *P
代表该参数有 0 到多个值,+P
表示 1 到多个值。调用的时候可以用 just recipe E
就可以改变 P
的值为 E
。
-
just 可以通过
set shell := ["any-available-shell", "-c"]
的方式来改变默认的 shell;另外还可以加载 .env 文件的环境变量,只需要在 justfile 文件中加入set dotenv-load
即可。 -
just 默认的情况下每一行是一条命令(想要写成多行需要在每行的行尾加上
\
,使用的是默认的 shell 来执行),但是你可以通过 Shebang 来执行不同的脚本,这要看你想使用什么脚本,sh、bash、zsh、ksh、fish、python、ruby……一切支持 Shebang 的脚本,例如:
1 | push-changes: |
再如可以使用 Python 脚本写:
1 | # 数一下当前 iOS 使用了多少个 pods |
-
just 默认是会打印每条命令的,可以在每条命令前加上
@
来取消打印(这一点和 make 一样),如果想要整个 recipe 不打印任何执行的命令,只需要在这个 recipe 前面加上@
即可。但是有个问题,不知道是不是 bug,就是如果你在有 Shebang 的 recipe 前加上@
的话反而会把整个 recipe 打印出来。 -
just 支持私有的 recipe,可以在 recipe 前加上一个
_
或者在 recipe 的上方加上[private]
属性让其变成私有;如果一个 recipe 设置为私有,则在执行just -l
时就不会被列出来。just -l
有些类似于大部分命令的--help
参数,它会列出来所有非私有的 recipe,后面跟着每个 recipe 的注释;另外还可以通过just --choose
交互的执行相应的 recipe(会结合fzf
) -
just 中默认会选择 justfile 文件中的第一个 recipe 来作为默认的 recipe,也可以通过
default
recipe 来指定,例如:
1 | # 列出所有可用的 recipe |
执行默认 recipe 不需要额外的参数,只需要执行 just
即可。
- justfile 中可以通过
variable_name := variable
的形式来设置变量,可以在执行 recipe 的时候传入不同的变量,例如:
1 | name := "world" |
这里定义了一个变量为 name
,默认值为字符串 world
1 | just hello # 会打印出 Hello world |
-
一些常见的 recipe 属性:
[private]
:将 recipe 标记为私有[no-exit-message]
:如果配方执行失败,不要打印错误信息[no-cd]
:在执行配方之前不要改变目录。这里需要注意,默认情况下 just 在执行 recipe 的时候会将当前目录改变到 justfile 所在的目录,如果加上了此属性则不会改变目录,命令执行时当前的目录(pwd
)为执行 just 时所在的目录。- 另外还有一些只有在指定操作系统下 recipe 才有效的属性,如:
[linux]
,[macos]
等,详情请见 just 的文档。
just 在日常还是很好用的(结合 fzf
、自己喜欢的脚本等可以实现出很有意思的功能),但是终究无法代替 make,毕竟两者的定位不同。just 重在命令的管理和组织,而 make 在是定位为编译工具,在 C/C++ 的编译方面无法撼动。这篇文章一个月前就想写了,想来想去也不知道如何着手,后来想想其实也算只是推荐而已,更详细的看说明 - Just 用户指南足够了。我在平时的工作和生活中已经大量运用 just 来帮助我做一些事情了。除了一些官方和一些开源的 justfile 示例外,也可以看一下我自己写的一个小玩意儿里的 Justfile。工作中用到的一些 recipe 就不方便分享出来了,但是如果有什么问题也欢迎留言交流。