justfile

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Writing Justfiles

编写Justfile

It fully documents the Justfile syntax and system.

<h1 align=center><code>just</code></h1>
just
is a handy way to save and run project-specific commands.
This readme is also available as a book. The book reflects the latest release, whereas the readme on GitHub reflects latest master.
(中文文档在 这里, 快看过来!)
Commands, called recipes, are stored in a file called
justfile
with syntax inspired by
make
:
screenshot
You can then run them with
just RECIPE
:
console
$ just test-all
cc *.c -o main
./test --all
Yay, all your tests passed!
just
has a ton of useful features, and many improvements over
make
:
  • just
    is a command runner, not a build system, so it avoids much of
    make
    's complexity and idiosyncrasies
    . No need for
    .PHONY
    recipes!
  • Linux, MacOS, Windows, and other reasonable unices are supported with no additional dependencies. (Although if your system doesn't have an
    sh
    , you'll need to choose a different shell.)
  • Errors are specific and informative, and syntax errors are reported along with their source context.
  • Recipes can accept command line arguments.
  • Wherever possible, errors are resolved statically. Unknown recipes and circular dependencies are reported before anything runs.
  • just
    loads
    .env
    files
    , making it easy to populate environment variables.
  • Recipes can be listed from the command line.
  • Command line completion scripts are available for most popular shells.
  • Recipes can be written in arbitrary languages, like Python or NodeJS.
  • just
    can be invoked from any subdirectory, not just the directory that contains the
    justfile
    .
  • And much more!
If you need help with
just
please feel free to open an issue or ping me on Discord. Feature requests and bug reports are always welcome!
它完整记录了Justfile的语法和系统。

<h1 align=center><code>just</code></h1>
just
是一款用来保存和运行项目专属命令的便捷工具。
本README也有书籍版本,书籍内容对应最新的正式发布版,而GitHub上的README对应最新的master分支代码。
(中文文档在 这里, 快看过来!)
被称为recipe的命令存储在名为
justfile
的文件中,语法灵感来源于
make
screenshot
你可以使用
just RECIPE
来运行这些命令:
console
$ just test-all
cc *.c -o main
./test --all
Yay, all your tests passed!
just
拥有大量实用功能,相比
make
有诸多改进:
如果你需要
just
相关的帮助,欢迎提交Issue或者在Discord上联系我。功能建议和Bug报告一直都非常欢迎!

Quick Start

快速入门

See the installation section for how to install
just
on your computer. Try running
just --version
to make sure that it's installed correctly.
For an overview of the syntax, check out this cheatsheet.
Once
just
is installed and working, create a file named
justfile
in the root of your project with the following contents:
just
recipe-name:
  echo 'This is a recipe!'
请参考安装章节了解如何在你的电脑上安装
just
。尝试运行
just --version
确认安装正确。
要了解语法概览,可以查看这份速查表
安装并确认
just
可用后,在项目根目录创建名为
justfile
的文件,内容如下:
just
recipe-name:
  echo 'This is a recipe!'

this is a comment

this is a comment

another-recipe: @echo 'This is another recipe.'

When you invoke `just` it looks for file `justfile` in the current directory
and upwards, so you can invoke it from any subdirectory of your project.

The search for a `justfile` is case insensitive, so any case, like `Justfile`,
`JUSTFILE`, or `JuStFiLe`, will work. `just` will also look for files with the
name `.justfile`, in case you'd like to hide a `justfile`.

Running `just` with no arguments runs the first recipe in the `justfile`:

```console
$ just
echo 'This is a recipe!'
This is a recipe!
One or more arguments specify the recipe(s) to run:
console
$ just another-recipe
This is another recipe.
just
prints each command to standard error before running it, which is why
echo 'This is a recipe!'
was printed. This is suppressed for lines starting with
@
, which is why
echo 'This is another recipe.'
was not printed.
Recipes stop running if a command fails. Here
cargo publish
will only run if
cargo test
succeeds:
just
publish:
  cargo test
  # tests passed, time to publish!
  cargo publish
Recipes can depend on other recipes. Here the
test
recipe depends on the
build
recipe, so
build
will run before
test
:
just
build:
  cc main.c foo.c bar.c -o main

test: build
  ./test

sloc:
  @echo "`wc -l *.c` lines of code"
console
$ just test
cc main.c foo.c bar.c -o main
./test
testing… all tests passed!
Recipes without dependencies will run in the order they're given on the command line:
console
$ just build sloc
cc main.c foo.c bar.c -o main
1337 lines of code
Dependencies will always run first, even if they are passed after a recipe that depends on them:
console
$ just test build
cc main.c foo.c bar.c -o main
./test
testing… all tests passed!
Recipes may depend on recipes in submodules:
justfile
mod foo

baz: foo::bar
another-recipe: @echo 'This is another recipe.'

当你调用`just`时,它会从当前目录向上搜索`justfile`文件,因此你可以从项目的任意子目录调用它。

搜索`justfile`时不区分大小写,所以任何大小写形式比如`Justfile`、`JUSTFILE`、`JuStFiLe`都可以生效。`just`也会查找名为`.justfile`的文件,适合你想要隐藏`justfile`的场景。

不带参数运行`just`会执行`justfile`中的第一个recipe:

```console
$ just
echo 'This is a recipe!'
This is a recipe!
传入一个或多个参数可以指定要运行的recipe:
console
$ just another-recipe
This is another recipe.
just
在运行命令前会将每个命令打印到标准错误,所以上面的
echo 'This is a recipe!'
会被打印出来。以
@
开头的行会禁用该打印行为,所以
echo 'This is another recipe.'
不会被打印。
如果命令执行失败,recipe会停止运行。下面的示例中
cargo publish
只会在
cargo test
执行成功后运行:
just
publish:
  cargo test
  # tests passed, time to publish!
  cargo publish
Recipe可以依赖其他recipe。下面的示例中
test
recipe依赖
build
recipe,所以
build
会在
test
之前运行:
just
build:
  cc main.c foo.c bar.c -o main

test: build
  ./test

sloc:
  @echo "`wc -l *.c` lines of code"
console
$ just test
cc main.c foo.c bar.c -o main
./test
testing… all tests passed!
没有依赖的recipe会按照命令行中传入的顺序运行:
console
$ just build sloc
cc main.c foo.c bar.c -o main
1337 lines of code
依赖总是会优先运行,即使它们被放在依赖它们的recipe之后传入:
console
$ just test build
cc main.c foo.c bar.c -o main
./test
testing… all tests passed!
Recipe可以依赖子模块中的recipe:
justfile
mod foo

baz: foo::bar

Examples

示例

A variety of
justfile
s can be found in the examples directory and on GitHub.
你可以在示例目录GitHub上找到各种
justfile
示例。

Features

功能

The Default Recipe

默认Recipe

When
just
is invoked without a recipe, it runs the recipe with the
[default]
attribute, or the first recipe in the
justfile
if no recipe has the
[default]
attribute.
This recipe might be the most frequently run command in the project, like running the tests:
just
test:
  cargo test
You can also use dependencies to run multiple recipes by default:
just
default: lint build test

build:
  echo Building…

test:
  echo Testing…

lint:
  echo Linting…
If no recipe makes sense as the default recipe, you can add a recipe to the beginning of your
justfile
that lists the available recipes:
just
default:
  just --list
当调用
just
时没有指定recipe,它会运行带有
[default]
属性的recipe,如果没有recipe带有该属性则运行
justfile
中的第一个recipe。
这个recipe通常是项目中最常运行的命令,比如运行测试:
just
test:
  cargo test
你也可以使用依赖来默认运行多个recipe:
just
default: lint build test

build:
  echo Building…

test:
  echo Testing…

lint:
  echo Linting…
如果没有适合作为默认的recipe,你可以在
justfile
开头添加一个列出所有可用recipe的recipe:
just
default:
  just --list

Listing Available Recipes

列出可用Recipe

Recipes can be listed in alphabetical order with
just --list
:
console
$ just --list
Available recipes:
    build
    test
    deploy
    lint
Recipes in submodules can be listed with
just --list PATH
, where
PATH
is a space- or
::
-separated module path:
$ cat justfile
mod foo
$ cat foo.just
mod bar
$ cat bar.just
baz:
$ just --list foo bar
Available recipes:
    baz
$ just --list foo::bar
Available recipes:
    baz
just --summary
is more concise:
console
$ just --summary
build test deploy lint
Pass
--unsorted
to print recipes in the order they appear in the
justfile
:
just
test:
  echo 'Testing!'

build:
  echo 'Building!'
console
$ just --list --unsorted
Available recipes:
    test
    build
console
$ just --summary --unsorted
test build
If you'd like
just
to default to listing the recipes in the
justfile
, you can use this as your default recipe:
just
default:
  @just --list
Note that you may need to add
--justfile {{justfile()}}
to the line above. Without it, if you executed
just -f /some/distant/justfile -d .
or
just -f ./non-standard-justfile
, the plain
just --list
inside the recipe would not necessarily use the file you provided. It would try to find a justfile in your current path, maybe even resulting in a
No justfile found
error.
The heading text can be customized with
--list-heading
:
console
$ just --list --list-heading $'Cool stuff…\n'
Cool stuff…
    test
    build
And the indentation can be customized with
--list-prefix
:
console
$ just --list --list-prefix ····
Available recipes:
····test
····build
The argument to
--list-heading
replaces both the heading and the newline following it, so it should contain a newline if non-empty. It works this way so you can suppress the heading line entirely by passing the empty string:
console
$ just --list --list-heading ''
    test
    build
使用
just --list
可以按字母顺序列出所有recipe:
console
$ just --list
Available recipes:
    build
    test
    deploy
    lint
可以使用
just --list PATH
列出子模块中的recipe,其中
PATH
是用空格或
::
分隔的模块路径:
$ cat justfile
mod foo
$ cat foo.just
mod bar
$ cat bar.just
baz:
$ just --list foo bar
Available recipes:
    baz
$ just --list foo::bar
Available recipes:
    baz
just --summary
的输出更简洁:
console
$ just --summary
build test deploy lint
传入
--unsorted
参数可以按recipe在
justfile
中出现的顺序打印:
just
test:
  echo 'Testing!'

build:
  echo 'Building!'
console
$ just --list --unsorted
Available recipes:
    test
    build
console
$ just --summary --unsorted
test build
如果你希望
just
默认列出
justfile
中的recipe,可以使用以下默认recipe:
just
default:
  @just --list
注意你可能需要在上面的命令中添加
--justfile {{justfile()}}
。如果没有的话,当你执行
just -f /some/distant/justfile -d .
或者
just -f ./non-standard-justfile
时,recipe中的
just --list
不一定会使用你指定的文件,它会尝试在当前路径查找justfile,甚至可能返回
No justfile found
错误。
可以使用
--list-heading
自定义标题文本:
console
$ just --list --list-heading $'Cool stuff…\
'
Cool stuff…
    test
    build
可以使用
--list-prefix
自定义缩进:
console
$ just --list --list-prefix ····
Available recipes:
····test
····build
--list-heading
的参数会替换标题和后面的换行符,所以如果参数非空应该包含换行符。你可以通过传入空字符串完全隐藏标题行:
console
$ just --list --list-heading ''
    test
    build

Invoking Multiple Recipes

调用多个Recipe

Multiple recipes may be invoked on the command line at once:
just
build:
  make web

serve:
  python3 -m http.server -d out 8000
console
$ just build serve
make web
python3 -m http.server -d out 8000
Keep in mind that recipes with parameters will swallow arguments, even if they match the names of other recipes:
just
build project:
  make {{project}}

serve:
  python3 -m http.server -d out 8000
console
$ just build serve
make: *** No rule to make target `serve'.  Stop.
The
--one
flag can be used to restrict command-line invocations to a single recipe:
console
$ just --one build serve
error: Expected 1 command-line recipe invocation but found 2.
可以在命令行一次调用多个recipe:
just
build:
  make web

serve:
  python3 -m http.server -d out 8000
console
$ just build serve
make web
python3 -m http.server -d out 8000
请注意,带参数的recipe会吸收后续参数,即使这些参数匹配其他recipe的名称:
just
build project:
  make {{project}}

serve:
  python3 -m http.server -d out 8000
console
$ just build serve
make: *** No rule to make target `serve'.  Stop.
可以使用
--one
flag限制命令行只能调用单个recipe:
console
$ just --one build serve
error: Expected 1 command-line recipe invocation but found 2.

Working Directory

工作目录

By default, recipes run with the working directory set to the directory that contains the
justfile
.
The
[no-cd]
attribute can be used to make recipes run with the working directory set to directory in which
just
was invoked.
just
@foo:
  pwd

[no-cd]
@bar:
  pwd
console
$ cd subdir
$ just foo
/
$ just bar
/subdir
You can override the working directory for all recipes with
set working-directory := '…'
:
just
set working-directory := 'bar'

@foo:
  pwd
console
$ pwd
/home/bob
$ just foo
/home/bob/bar
You can override the working directory for a specific recipe with the
working-directory
attribute<sup>1.38.0</sup>:
just
[working-directory: 'bar']
@foo:
  pwd
console
$ pwd
/home/bob
$ just foo
/home/bob/bar
The argument to the
working-directory
setting or
working-directory
attribute may be absolute or relative. If it is relative it is interpreted relative to the default working directory.
默认情况下,recipe运行时的工作目录被设置为包含
justfile
的目录。
可以使用
[no-cd]
属性让recipe运行时的工作目录为调用
just
时的目录:
just
@foo:
  pwd

[no-cd]
@bar:
  pwd
console
$ cd subdir
$ just foo
/
$ just bar
/subdir
你可以使用
set working-directory := '…'
覆盖所有recipe的工作目录:
just
set working-directory := 'bar'

@foo:
  pwd
console
$ pwd
/home/bob
$ just foo
/home/bob/bar
你可以使用
working-directory
属性<sup>1.38.0</sup>覆盖单个recipe的工作目录:
just
[working-directory: 'bar']
@foo:
  pwd
console
$ pwd
/home/bob
$ just foo
/home/bob/bar
working-directory
设置或
working-directory
属性的参数可以是绝对路径或相对路径。如果是相对路径,会相对于默认工作目录解析。

Aliases

别名

Aliases allow recipes to be invoked on the command line with alternative names:
just
alias b := build

build:
  echo 'Building!'
console
$ just b
echo 'Building!'
Building!
The target of an alias may be a recipe in a submodule:
justfile
mod foo

alias baz := foo::bar
别名允许你在命令行使用其他名称调用recipe:
just
alias b := build

build:
  echo 'Building!'
console
$ just b
echo 'Building!'
Building!
别名的目标可以是子模块中的recipe:
justfile
mod foo

alias baz := foo::bar

Settings

设置

Settings control interpretation and execution. Each setting may be specified at most once, anywhere in the
justfile
.
For example:
just
set shell := ["zsh", "-cu"]

foo:
  # this line will be run as `zsh -cu 'ls **/*.txt'`
  ls **/*.txt
设置控制解释和执行行为。每个设置最多只能指定一次,可以放在
justfile
的任意位置。
例如:
just
set shell := ["zsh", "-cu"]

foo:
  # this line will be run as `zsh -cu 'ls **/*.txt'`
  ls **/*.txt

Table of Settings

设置表

NameValueDefaultDescription
allow-duplicate-recipes
boolean
false
Allow recipes appearing later in a
justfile
to override earlier recipes with the same name.
allow-duplicate-variables
boolean
false
Allow variables appearing later in a
justfile
to override earlier variables with the same name.
dotenv-filename
string-Load a
.env
file with a custom name, if present.
dotenv-load
boolean
false
Load a
.env
file, if present.
dotenv-override
boolean
false
Override existing environment variables with values from the
.env
file.
dotenv-path
string-Load a
.env
file from a custom path and error if not present. Overrides
dotenv-filename
.
dotenv-required
boolean
false
Error if a
.env
file isn't found.
export
boolean
false
Export all variables as environment variables.
fallback
boolean
false
Search
justfile
in parent directory if the first recipe on the command line is not found.
ignore-comments
boolean
false
Ignore recipe lines beginning with
#
.
positional-arguments
boolean
false
Pass positional arguments.
quiet
boolean
false
Disable echoing recipe lines before executing.
script-interpreter
<sup>1.33.0</sup>
[COMMAND, ARGS…]
['sh', '-eu']
Set command used to invoke recipes with empty
[script]
attribute.
shell
[COMMAND, ARGS…]
-Set command used to invoke recipes and evaluate backticks.
tempdir
string-Create temporary directories in
tempdir
instead of the system default temporary directory.
unstable
<sup>1.31.0</sup>
boolean
false
Enable unstable features.
windows-powershell
boolean
false
Use PowerShell on Windows as default shell. (Deprecated. Use
windows-shell
instead.
windows-shell
[COMMAND, ARGS…]
-Set the command used to invoke recipes and evaluate backticks.
working-directory
<sup>1.33.0</sup>
string-Set the working directory for recipes and backticks, relative to the default working directory.
Boolean settings can be written as:
justfile
set NAME
Which is equivalent to:
justfile
set NAME := true
Non-boolean settings can be set to both strings and expressions.<sup>1.46.0</sup>
However, because settings affect the behavior of backticks and many functions, those expressions may not contain backticks or function calls, directly or transitively via reference.
名称取值类型默认值描述
allow-duplicate-recipes
布尔值
false
允许
justfile
中后面出现的同名recipe覆盖前面的recipe
allow-duplicate-variables
布尔值
false
允许
justfile
中后面出现的同名变量覆盖前面的变量
dotenv-filename
字符串-如果存在的话加载指定名称的
.env
文件
dotenv-load
布尔值
false
如果存在的话加载
.env
文件
dotenv-override
布尔值
false
使用
.env
文件中的值覆盖已有的环境变量
dotenv-path
字符串-从指定路径加载
.env
文件,如果不存在则报错,会覆盖
dotenv-filename
设置
dotenv-required
布尔值
false
如果未找到
.env
文件则报错
export
布尔值
false
将所有变量导出为环境变量
fallback
布尔值
false
如果命令行的第一个recipe在当前
justfile
中未找到,到父目录搜索
justfile
ignore-comments
布尔值
false
忽略以
#
开头的recipe行
positional-arguments
布尔值
false
传递位置参数
quiet
布尔值
false
执行前禁用recipe行的打印输出
script-interpreter
<sup>1.33.0</sup>
[COMMAND, ARGS…]
['sh', '-eu']
设置用于执行带有空
[script]
属性的recipe的命令
shell
[COMMAND, ARGS…]
-设置用于调用recipe和计算反引号表达式的命令
tempdir
字符串-
tempdir
中创建临时目录,而非系统默认临时目录
unstable
<sup>1.31.0</sup>
布尔值
false
启用不稳定特性
windows-powershell
布尔值
false
在Windows上使用PowerShell作为默认shell(已废弃,请使用
windows-shell
替代)
windows-shell
[COMMAND, ARGS…]
-设置Windows上用于调用recipe和计算反引号表达式的命令
working-directory
<sup>1.33.0</sup>
字符串-设置recipe和反引号表达式的工作目录,相对于默认工作目录
布尔设置可以这样写:
justfile
set NAME
等价于:
justfile
set NAME := true
非布尔设置可以设置为字符串和表达式<sup>1.46.0</sup>
但是因为设置会影响反引号和很多函数的行为,这些表达式不能直接或间接通过引用包含反引号或函数调用。

Allow Duplicate Recipes

允许重复Recipe

If
allow-duplicate-recipes
is set to
true
, defining multiple recipes with the same name is not an error and the last definition is used. Defaults to
false
.
just
set allow-duplicate-recipes

@foo:
  echo foo

@foo:
  echo bar
console
$ just foo
bar
如果
allow-duplicate-recipes
设置为
true
,定义多个同名recipe不会报错,会使用最后一个定义,默认值为
false
just
set allow-duplicate-recipes

@foo:
  echo foo

@foo:
  echo bar
console
$ just foo
bar

Allow Duplicate Variables

允许重复变量

If
allow-duplicate-variables
is set to
true
, defining multiple variables with the same name is not an error and the last definition is used. Defaults to
false
.
just
set allow-duplicate-variables

a := "foo"
a := "bar"

@foo:
  echo {{a}}
console
$ just foo
bar
如果
allow-duplicate-variables
设置为
true
,定义多个同名变量不会报错,会使用最后一个定义,默认值为
false
just
set allow-duplicate-variables

a := "foo"
a := "bar"

@foo:
  echo {{a}}
console
$ just foo
bar

Dotenv Settings

Dotenv设置

If any of
dotenv-load
,
dotenv-filename
,
dotenv-override
,
dotenv-path
, or
dotenv-required
are set,
just
will try to load environment variables from a file.
If
dotenv-path
is set,
just
will look for a file at the given path, which may be absolute, or relative to the working directory.
The command-line option
--dotenv-path
, short form
-E
, can be used to set or override
dotenv-path
at runtime.
If
dotenv-filename
is set
just
will look for a file at the given path, relative to the working directory and each of its ancestors.
If
dotenv-filename
is not set, but
dotenv-load
or
dotenv-required
are set, just will look for a file named
.env
, relative to the working directory and each of its ancestors.
dotenv-filename
and
dotenv-path
are similar, but
dotenv-path
is only checked relative to the working directory, whereas
dotenv-filename
is checked relative to the working directory and each of its ancestors.
It is not an error if an environment file is not found, unless
dotenv-required
is set.
The loaded variables are environment variables, not
just
variables, and so must be accessed using
$VARIABLE_NAME
in recipes and backticks.
If
dotenv-override
is set, variables from the environment file will override existing environment variables.
For example, if your
.env
file contains:
console
undefined
如果设置了
dotenv-load
dotenv-filename
dotenv-override
dotenv-path
dotenv-required
中的任意一个,
just
会尝试从文件加载环境变量。
如果设置了
dotenv-path
just
会查找指定路径的文件,可以是绝对路径,也可以是相对于工作目录的路径。
命令行选项
--dotenv-path
(简写
-E
)可以在运行时设置或覆盖
dotenv-path
如果设置了
dotenv-filename
just
会从工作目录及其每个上级目录查找指定路径的文件。
如果没有设置
dotenv-filename
,但设置了
dotenv-load
dotenv-required
,just会从工作目录及其每个上级目录查找名为
.env
的文件。
dotenv-filename
dotenv-path
类似,但
dotenv-path
只会相对于工作目录检查,而
dotenv-filename
会相对于工作目录及其每个上级目录检查。
除非设置了
dotenv-required
,否则未找到环境文件不会报错。
加载的变量是环境变量,而非
just
变量,因此必须在recipe和反引号中使用
$VARIABLE_NAME
访问。
如果设置了
dotenv-override
,环境文件中的变量会覆盖已有的环境变量。
例如,如果你的
.env
文件包含:
console
undefined

a comment, will be ignored

a comment, will be ignored

DATABASE_ADDRESS=localhost:6379 SERVER_PORT=1337

And your `justfile` contains:

```just
set dotenv-load

serve:
  @echo "Starting server with database $DATABASE_ADDRESS on port $SERVER_PORT…"
  ./server --database $DATABASE_ADDRESS --port $SERVER_PORT
just serve
will output:
console
$ just serve
Starting server with database localhost:6379 on port 1337…
./server --database $DATABASE_ADDRESS --port $SERVER_PORT
DATABASE_ADDRESS=localhost:6379 SERVER_PORT=1337

你的`justfile`包含:

```just
set dotenv-load

serve:
  @echo "Starting server with database $DATABASE_ADDRESS on port $SERVER_PORT…"
  ./server --database $DATABASE_ADDRESS --port $SERVER_PORT
just serve
会输出:
console
$ just serve
Starting server with database localhost:6379 on port 1337…
./server --database $DATABASE_ADDRESS --port $SERVER_PORT

Export

导出

The
export
setting causes all
just
variables to be exported as environment variables. Defaults to
false
.
just
set export

a := "hello"

@foo b:
  echo $a
  echo $b
console
$ just foo goodbye
hello
goodbye
export
设置会将所有
just
变量导出为环境变量,默认值为
false
just
set export

a := "hello"

@foo b:
  echo $a
  echo $b
console
$ just foo goodbye
hello
goodbye

Positional Arguments

位置参数

If
positional-arguments
is
true
, recipe arguments will be passed as positional arguments to commands. For linewise recipes, argument
$0
will be the name of the recipe.
For example, running this recipe:
just
set positional-arguments

@foo bar:
  echo $0
  echo $1
Will produce the following output:
console
$ just foo hello
foo
hello
When using an
sh
-compatible shell, such as
bash
or
zsh
,
$@
expands to the positional arguments given to the recipe, starting from one. When used within double quotes as
"$@"
, arguments including whitespace will be passed on as if they were double-quoted. That is,
"$@"
is equivalent to
"$1" "$2"
… When there are no positional parameters,
"$@"
and
$@
expand to nothing (i.e., they are removed).
This example recipe will print arguments one by one on separate lines:
just
set positional-arguments

@test *args='':
  bash -c 'while (( "$#" )); do echo - $1; shift; done' -- "$@"
Running it with two arguments:
console
$ just test foo "bar baz"
- foo
- bar baz
Positional arguments may also be turned on on a per-recipe basis with the
[positional-arguments]
attribute<sup>1.29.0</sup>:
just
[positional-arguments]
@foo bar:
  echo $0
  echo $1
Note that PowerShell does not handle positional arguments in the same way as other shells, so turning on positional arguments will likely break recipes that use PowerShell.
If using PowerShell 7.4 or better, the
-CommandWithArgs
flag will make positional arguments work as expected:
just
set shell := ['pwsh.exe', '-CommandWithArgs']
set positional-arguments

print-args a b c:
  Write-Output @($args[1..($args.Count - 1)])
如果
positional-arguments
true
,recipe参数会作为位置参数传递给命令。对于逐行执行的recipe,
$0
是recipe的名称。
例如,运行这个recipe:
just
set positional-arguments

@foo bar:
  echo $0
  echo $1
会产生以下输出:
console
$ just foo hello
foo
hello
当使用
sh
兼容的shell(比如
bash
zsh
)时,
$@
会展开为传递给recipe的位置参数,从第一个开始。当在双引号中使用
"$@"
时,包含空格的参数会被正确传递,相当于
"$1" "$2"…
。当没有位置参数时,
"$@"
$@
会展开为空(即被移除)。
这个示例recipe会逐行打印每个参数:
just
set positional-arguments

@test *args='':
  bash -c 'while (( "$#" )); do echo - $1; shift; done' -- "$@"
传入两个参数运行:
console
$ just test foo "bar baz"
- foo
- bar baz
也可以使用
[positional-arguments]
属性为单个recipe开启位置参数<sup>1.29.0</sup>
just
[positional-arguments]
@foo bar:
  echo $0
  echo $1
注意PowerShell处理位置参数的方式和其他shell不同,所以开启位置参数可能会破坏使用PowerShell的recipe。
如果使用PowerShell 7.4或更高版本,
-CommandWithArgs
flag可以让位置参数正常工作:
just
set shell := ['pwsh.exe', '-CommandWithArgs']
set positional-arguments

print-args a b c:
  Write-Output @($args[1..($args.Count - 1)])

Shell

Shell

The
shell
setting controls the command used to invoke recipe lines and backticks. Shebang recipes are unaffected. The default shell is
sh -cu
.
just
undefined
shell
设置控制用于调用recipe行和反引号表达式的命令,不会影响Shebang recipe。默认shell是
sh -cu
just
undefined

use python3 to execute recipe lines and backticks

use python3 to execute recipe lines and backticks

set shell := ["python3", "-c"]
set shell := ["python3", "-c"]

use print to capture result of evaluation

use print to capture result of evaluation

foos :=
print("foo" * 4)
foo: print("Snake snake snake snake.") print("{{foos}}")

`just` passes the command to be executed as an argument. Many shells will need
an additional flag, often `-c`, to make them evaluate the first argument.
foos :=
print("foo" * 4)
foo: print("Snake snake snake snake.") print("{{foos}}")

`just`将要执行的命令作为参数传递。很多shell需要额外的flag(通常是`-c`)来让它们计算第一个参数。
Windows Shell
Windows Shell
just
uses
sh
on Windows by default. To use a different shell on Windows, use
windows-shell
:
just
set windows-shell := ["powershell.exe", "-NoLogo", "-Command"]

hello:
  Write-Host "Hello, world!"
See powershell.just for a justfile that uses PowerShell on all platforms.
just
在Windows上默认使用
sh
。要在Windows上使用其他shell,请使用
windows-shell
just
set windows-shell := ["powershell.exe", "-NoLogo", "-Command"]

hello:
  Write-Host "Hello, world!"
查看powershell.just了解在所有平台使用PowerShell的justfile示例。
Windows PowerShell
Windows PowerShell
set windows-powershell
uses the legacy
powershell.exe
binary, and is no longer recommended. See the
windows-shell
setting above for a more flexible way to control which shell is used on Windows.
just
uses
sh
on Windows by default. To use
powershell.exe
instead, set
windows-powershell
to true.
just
set windows-powershell := true

hello:
  Write-Host "Hello, world!"
set windows-powershell
使用旧版
powershell.exe
二进制文件,不再推荐使用。请参考上面的
windows-shell
设置来更灵活地控制Windows上使用的shell。
just
在Windows上默认使用
sh
。要改用
powershell.exe
,将
windows-powershell
设置为true。
just
set windows-powershell := true

hello:
  Write-Host "Hello, world!"
Python 3
Python 3
just
set shell := ["python3", "-c"]
just
set shell := ["python3", "-c"]
Bash
Bash
just
set shell := ["bash", "-uc"]
just
set shell := ["bash", "-uc"]
Z Shell
Z Shell
just
set shell := ["zsh", "-uc"]
just
set shell := ["zsh", "-uc"]
Fish
Fish
just
set shell := ["fish", "-c"]
just
set shell := ["fish", "-c"]
Nushell
Nushell
just
set shell := ["nu", "-c"]
If you want to change the default table mode to
light
:
just
set shell := ['nu', '-m', 'light', '-c']
Nushell was written in Rust, and has cross-platform support for Windows / macOS and Linux.
just
set shell := ["nu", "-c"]
如果你想将默认表格模式改为
light
just
set shell := ['nu', '-m', 'light', '-c']
Nushell使用Rust编写,支持Windows/macOS和Linux跨平台

Documentation Comments

文档注释

Comments immediately preceding a recipe will appear in
just --list
:
just
undefined
紧邻recipe之前的注释会出现在
just --list
的输出中:
just
undefined

build stuff

build stuff

build: ./bin/build
build: ./bin/build

test stuff

test stuff

test: ./bin/test

```console
$ just --list
Available recipes:
    build # build stuff
    test # test stuff
The
[doc]
attribute can be used to set or suppress a recipe's doc comment:
just
undefined
test: ./bin/test

```console
$ just --list
Available recipes:
    build # build stuff
    test # test stuff
可以使用
[doc]
属性设置或隐藏recipe的文档注释:
just
undefined

This comment won't appear

This comment won't appear

[doc('Build stuff')] build: ./bin/build
[doc('Build stuff')] build: ./bin/build

This one won't either

This one won't either

[doc] test: ./bin/test

```console
$ just --list
Available recipes:
    build # Build stuff
    test
[doc] test: ./bin/test

```console
$ just --list
Available recipes:
    build # Build stuff
    test

Expressions and Substitutions

表达式和替换

Various operators and function calls are supported in expressions, which may be used in assignments, default recipe arguments, and inside recipe body
{{…}}
substitutions.
just
tmpdir  := `mktemp -d`
version := "0.2.7"
tardir  := tmpdir / "awesomesauce-" + version
tarball := tardir + ".tar.gz"
config  := quote(config_dir() / ".project-config")

publish:
  rm -f {{tarball}}
  mkdir {{tardir}}
  cp README.md *.c {{ config }} {{tardir}}
  tar zcvf {{tarball}} {{tardir}}
  scp {{tarball}} me@server.com:release/
  rm -rf {{tarball}} {{tardir}}
表达式支持多种运算符和函数调用,可以用于赋值、默认recipe参数,以及recipe体中的
{{…}}
替换。
just
tmpdir  := `mktemp -d`
version := "0.2.7"
tardir  := tmpdir / "awesomesauce-" + version
tarball := tardir + ".tar.gz"
config  := quote(config_dir() / ".project-config")

publish:
  rm -f {{tarball}}
  mkdir {{tardir}}
  cp README.md *.c {{ config }} {{tardir}}
  tar zcvf {{tarball}} {{tardir}}
  scp {{tarball}} me@server.com:release/
  rm -rf {{tarball}} {{tardir}}

Concatenation

拼接

The
+
operator returns the left-hand argument concatenated with the right-hand argument:
just
foobar := 'foo' + 'bar'
+
运算符返回左参数和右参数拼接的结果:
just
foobar := 'foo' + 'bar'

Logical Operators

逻辑运算符

The logical operators
&&
and
||
can be used to coalesce string values<sup>1.37.0</sup>, similar to Python's
and
and
or
. These operators consider the empty string
''
to be false, and all other strings to be true.
These operators are currently unstable.
The
&&
operator returns the empty string if the left-hand argument is the empty string, otherwise it returns the right-hand argument:
justfile
foo := '' && 'goodbye'      # ''
bar := 'hello' && 'goodbye' # 'goodbye'
The
||
operator returns the left-hand argument if it is non-empty, otherwise it returns the right-hand argument:
justfile
foo := '' || 'goodbye'      # 'goodbye'
bar := 'hello' || 'goodbye' # 'hello'
逻辑运算符
&&
||
可以用于合并字符串值<sup>1.37.0</sup>,类似于Python的
and
or
。这些运算符将空字符串
''
视为假,其他所有字符串视为真。
这些运算符目前是不稳定特性。
如果左参数是空字符串,
&&
运算符返回空字符串,否则返回右参数:
justfile
foo := '' && 'goodbye'      # ''
bar := 'hello' && 'goodbye' # 'goodbye'
如果左参数非空,
||
运算符返回左参数,否则返回右参数:
justfile
foo := '' || 'goodbye'      # 'goodbye'
bar := 'hello' || 'goodbye' # 'hello'

Joining Paths

路径拼接

The
/
operator can be used to join two strings with a slash:
just
foo := "a" / "b"
$ just --evaluate foo
a/b
Note that a
/
is added even if one is already present:
just
foo := "a/"
bar := foo / "b"
$ just --evaluate bar
a//b
Absolute paths can also be constructed<sup>1.5.0</sup>:
just
foo := / "b"
$ just --evaluate foo
/b
The
/
operator uses the
/
character, even on Windows. Thus, using the
/
operator should be avoided with paths that use universal naming convention (UNC), i.e., those that start with
\?
, since forward slashes are not supported with UNC paths.
/
运算符可以用斜杠拼接两个字符串:
just
foo := "a" / "b"
$ just --evaluate foo
a/b
注意即使已经存在斜杠也会再添加一个:
just
foo := "a/"
bar := foo / "b"
$ just --evaluate bar
a//b
也可以构造绝对路径<sup>1.5.0</sup>
just
foo := / "b"
$ just --evaluate foo
/b
/
运算符即使在Windows上也使用
/
字符。因此,对于使用通用命名约定(UNC)的路径(即以
\\\\?
开头的路径),应避免使用
/
运算符,因为UNC路径不支持正斜杠。

Escaping
{{

转义
{{

To write a recipe containing
{{
, use
{{{{
:
just
braces:
  echo 'I {{{{LOVE}} curly braces!'
(An unmatched
}}
is ignored, so it doesn't need to be escaped.)
Another option is to put all the text you'd like to escape inside of an interpolation:
just
braces:
  echo '{{'I {{LOVE}} curly braces!'}}'
Yet another option is to use
{{ "{{" }}
:
just
braces:
  echo 'I {{ "{{" }}LOVE}} curly braces!'
要编写包含
{{
的recipe,请使用
{{{{
just
braces:
  echo 'I {{{{LOVE}} curly braces!'
(未匹配的
}}
会被忽略,所以不需要转义。)
另一种选择是将所有要转义的文本放在插值中:
just
braces:
  echo '{{'I {{LOVE}} curly braces!'}}'
还有一种选择是使用
{{ "{{" }}
just
braces:
  echo 'I {{ "{{" }}LOVE}} curly braces!'

Strings

字符串

'single'
,
"double"
, and
'''triple'''
quoted string literals are supported. Unlike in recipe bodies,
{{…}}
interpolations are not supported inside strings.
Double-quoted strings support escape sequences:
just
carriage-return   := "\r"
double-quote      := "\""
newline           := "\n"
no-newline        := "\
"
slash             := "\\"
tab               := "\t"
unicode-codepoint := "\u{1F916}"
console
$ just --evaluate
"arriage-return   := "
double-quote      := """
newline           := "
"
no-newline        := ""
slash             := "\"
tab               := "     "
unicode-codepoint := "🤖"
The unicode character escape sequence
\u{…}
<sup>1.36.0</sup> accepts up to six hex digits.
Strings may contain line breaks:
just
single := '
hello
'

double := "
goodbye
"
Single-quoted strings do not recognize escape sequences:
just
escapes := '\t\n\r\"\\'
console
$ just --evaluate
escapes := "\t\n\r\"\\"
Indented versions of both single- and double-quoted strings, delimited by triple single- or double-quotes, are supported. Indented string lines are stripped of a leading line break, and leading whitespace common to all non-blank lines:
just
undefined
支持
'单引号'
"双引号"
'''三引号'''
字符串字面量。与recipe体不同,字符串内部不支持
{{…}}
插值。
双引号字符串支持转义序列:
just
carriage-return   := "\\r"
double-quote      := "\\""
newline           := "\
"
no-newline        := "\\
"
slash             := "\\\\"
tab               := "\\t"
unicode-codepoint := "\\u{1F916}"
console
$ just --evaluate
"arriage-return   := "
double-quote      := """
newline           := "
"
no-newline        := ""
slash             := "\\"
tab               := "     "
unicode-codepoint := "🤖"
Unicode字符转义序列
\\u{…}
<sup>1.36.0</sup>接受最多六位十六进制数字。
字符串可以包含换行符:
just
single := '
hello
'

double := "
goodbye
"
单引号字符串不识别转义序列:
just
escapes := '\\t\
\\r\\"\\\\'
console
$ just --evaluate
escapes := "\\t\
\\r\\"\\\\"
支持使用三个单引号或双引号分隔的缩进版单双引号字符串。缩进字符串行的开头换行符会被移除,所有非空行共有的前导空格也会被移除:
just
undefined

this string will evaluate to
foo\nbar\n

this string will evaluate to `foo\

x := ''' foo bar '''
bar
` x := ''' foo bar '''

this string will evaluate to
abc\n  wuv\nxyz\n

this string will evaluate to `abc\

y := """ abc wuv xyz """

Similar to unindented strings, indented double-quoted strings process escape
sequences, and indented single-quoted strings ignore escape sequences. Escape
sequence processing takes place after unindentation. The unindentation
algorithm does not take escape-sequence produced whitespace or newlines into
account.
wuv
xyz
` y := """ abc wuv xyz """

与非缩进字符串类似,缩进的双引号字符串会处理转义序列,缩进的单引号字符串会忽略转义序列。转义序列处理在去除缩进之后进行。去除缩进的算法不会考虑转义序列产生的空格或换行符。

Shell-expanded strings

Shell扩展字符串

Strings prefixed with
x
are shell expanded<sup>1.27.0</sup>:
justfile
foobar := x'~/$FOO/${BAR}'
ValueReplacement
$VAR
value of environment variable
VAR
${VAR}
value of environment variable
VAR
${VAR:-DEFAULT}
value of environment variable
VAR
, or
DEFAULT
if
VAR
is not set
Leading
~
path to current user's home directory
Leading
~USER
path to
USER
's home directory
This expansion is performed at compile time, so variables from
.env
files and exported
just
variables cannot be used. However, this allows shell expanded strings to be used in places like settings and import paths, which cannot depend on
just
variables and
.env
files.
x
为前缀的字符串会进行Shell扩展<sup>1.27.0</sup>
justfile
foobar := x'~/$FOO/${BAR}'
替换为
$VAR
环境变量
VAR
的值
${VAR}
环境变量
VAR
的值
${VAR:-DEFAULT}
环境变量
VAR
的值,如果
VAR
未设置则使用
DEFAULT
开头的
~
当前用户的主目录路径
开头的
~USER
USER
的主目录路径
这种扩展在编译时执行,因此无法使用
.env
文件中的变量和导出的
just
变量。但这允许Shell扩展字符串用于设置和导入路径等不依赖
just
变量和
.env
文件的场景。

Format strings

格式字符串

Strings prefixed with
f
are format strings<sup>1.44.0</sup>:
justfile
name := "world"
message := f'Hello, {{name}}!'
Format strings may contain interpolations delimited with
{{…}}
that contain expressions. Format strings evaluate to the concatenated string fragments and evaluated expressions.
Use
{{{{
to include a literal
{{
in a format string:
justfile
foo := f'I {{{{LOVE} curly braces!'
f
为前缀的字符串是格式字符串<sup>1.44.0</sup>
justfile
name := "world"
message := f'Hello, {{name}}!'
格式字符串可以包含用
{{…}}
分隔的插值,插值内部是表达式。格式字符串的计算结果是字符串片段和计算后的表达式拼接的结果。
要在格式字符串中包含字面量
{{
,请使用
{{{{
justfile
foo := f'I {{{{LOVE} curly braces!'

Ignoring Errors

忽略错误

Normally, if a command returns a non-zero exit status, execution will stop. To continue execution after a command, even if it fails, prefix the command with
-
:
just
foo:
  -cat foo
  echo 'Done!'
console
$ just foo
cat foo
cat: foo: No such file or directory
echo 'Done!'
Done!
通常情况下,如果命令返回非零退出状态,执行会停止。要在命令失败后继续执行,即使它失败了,可以在命令前加上
-
just
foo:
  -cat foo
  echo 'Done!'
console
$ just foo
cat foo
cat: foo: No such file or directory
echo 'Done!'
Done!

Functions

函数

just
provides many built-in functions for use in expressions, including recipe body
{{…}}
substitutions, assignments, and default parameter values.
All functions ending in
_directory
can be abbreviated to
_dir
. So
home_directory()
can also be written as
home_dir()
. In addition,
invocation_directory_native()
can be abbreviated to
invocation_dir_native()
.
just
提供了很多内置函数用于表达式,包括recipe体中的
{{…}}
替换、赋值和默认参数值。
所有以
_directory
结尾的函数都可以缩写为
_dir
,因此
home_directory()
也可以写为
home_dir()
。此外,
invocation_directory_native()
可以缩写为
invocation_dir_native()

System Information

系统信息

  • arch()
    — Instruction set architecture. Possible values are:
    "aarch64"
    ,
    "arm"
    ,
    "asmjs"
    ,
    "hexagon"
    ,
    "mips"
    ,
    "msp430"
    ,
    "powerpc"
    ,
    "powerpc64"
    ,
    "s390x"
    ,
    "sparc"
    ,
    "wasm32"
    ,
    "x86"
    ,
    "x86_64"
    , and
    "xcore"
    .
  • num_cpus()
    <sup>1.15.0</sup> - Number of logical CPUs.
  • os()
    — Operating system. Possible values are:
    "android"
    ,
    "bitrig"
    ,
    "dragonfly"
    ,
    "emscripten"
    ,
    "freebsd"
    ,
    "haiku"
    ,
    "ios"
    ,
    "linux"
    ,
    "macos"
    ,
    "netbsd"
    ,
    "openbsd"
    ,
    "solaris"
    , and
    "windows"
    .
  • os_family()
    — Operating system family; possible values are:
    "unix"
    and
    "windows"
    .
For example:
just
system-info:
  @echo "This is an {{arch()}} machine".
console
$ just system-info
This is an x86_64 machine
The
os_family()
function can be used to create cross-platform
justfile
s that work on various operating systems. For an example, see cross-platform.just file.
  • arch()
    — 指令集架构。可能的取值有:
    "aarch64"
    "arm"
    "asmjs"
    "hexagon"
    "mips"
    "msp430"
    "powerpc"
    "powerpc64"
    "s390x"
    "sparc"
    "wasm32"
    "x86"
    "x86_64"
    "xcore"
  • num_cpus()
    <sup>1.15.0</sup> — 逻辑CPU数量。
  • os()
    — 操作系统。可能的取值有:
    "android"
    "bitrig"
    "dragonfly"
    "emscripten"
    "freebsd"
    "haiku"
    "ios"
    "linux"
    "macos"
    "netbsd"
    "openbsd"
    "solaris"
    "windows"
  • os_family()
    — 操作系统家族。可能的取值有:
    "unix"
    "windows"
例如:
just
system-info:
  @echo "This is an {{arch()}} machine".
console
$ just system-info
This is an x86_64 machine
os_family()
函数可以用于创建可在各种操作系统上运行的跨平台
justfile
。示例请参考cross-platform.just文件。

External Commands

外部命令

  • shell(command, args...)
    <sup>1.27.0</sup> returns the standard output of shell script
    command
    with zero or more positional arguments
    args
    . The shell used to interpret
    command
    is the same shell that is used to evaluate recipe lines, and can be changed with
    set shell := […]
    .
    command
    is passed as the first argument, so if the command is
    'echo $@'
    , the full command line, with the default shell command
    sh -cu
    and
    args
    'foo'
    and
    'bar'
    will be:
    'sh' '-cu' 'echo $@' 'echo $@' 'foo' 'bar'
    This is so that
    $@
    works as expected, and
    $1
    refers to the first argument.
    $@
    does not include the first positional argument, which is expected to be the name of the program being run.
just
undefined
  • shell(command, args...)
    <sup>1.27.0</sup> 返回Shell脚本
    command
    的标准输出,可以传入零个或多个位置参数
    args
    。解释
    command
    使用的Shell与计算recipe行使用的Shell相同,可以通过
    set shell := […]
    更改。
    command
    作为第一个参数传递,因此如果命令是
    'echo $@'
    ,使用默认Shell命令
    sh -cu
    ,参数为
    'foo'
    'bar'
    时,完整的命令行是:
    'sh' '-cu' 'echo $@' 'echo $@' 'foo' 'bar'
    这样
    $@
    可以正常工作,
    $1
    指向第一个参数。
    $@
    不包含第一个位置参数,该参数预计是正在运行的程序的名称。
just
undefined

arguments can be variables or expressions

arguments can be variables or expressions

file := '/sys/class/power_supply/BAT0/status' bat0stat := shell('cat $1', file)
file := '/sys/class/power_supply/BAT0/status' bat0stat := shell('cat $1', file)

commands can be variables or expressions

commands can be variables or expressions

command := 'wc -l' output := shell(command + ' "$1"', 'main.c')
command := 'wc -l' output := shell(command + ' "$1"', 'main.c')

arguments referenced by the shell command must be used

arguments referenced by the shell command must be used

empty := shell('echo', 'foo') full := shell('echo $1', 'foo') error := shell('echo $1')

```just
empty := shell('echo', 'foo') full := shell('echo $1', 'foo') error := shell('echo $1')

```just

Using python as the shell. Since
python -c
sets
sys.argv[0]
to
'-c'
,

Using python as the shell. Since
python -c
sets
sys.argv[0]
to
'-c'
,

the first "real" positional argument will be
sys.argv[2]
.

the first "real" positional argument will be
sys.argv[2]
.

set shell := ["python3", "-c"] olleh := shell('import sys; print(sys.argv[2][::-1])', 'hello')
undefined
set shell := ["python3", "-c"] olleh := shell('import sys; print(sys.argv[2][::-1])', 'hello')
undefined

Environment Variables

环境变量

  • env(key)
    <sup>1.15.0</sup> — Retrieves the environment variable with name
    key
    , aborting if it is not present.
just
home_dir := env('HOME')

test:
  echo "{{home_dir}}"
console
$ just
/home/user1
  • env(key, default)
    <sup>1.15.0</sup> — Retrieves the environment variable with name
    key
    , returning
    default
    if it is not present.
  • env_var(key)
    — Deprecated alias for
    env(key)
    .
  • env_var_or_default(key, default)
    — Deprecated alias for
    env(key, default)
    .
A default can be substituted for an empty environment variable value with the
||
operator, currently unstable:
just
set unstable

foo := env('FOO', '') || 'DEFAULT_VALUE'
  • env(key)
    <sup>1.15.0</sup> — 获取名为
    key
    的环境变量,如果不存在则终止执行。
just
home_dir := env('HOME')

test:
  echo "{{home_dir}}"
console
$ just
/home/user1
  • env(key, default)
    <sup>1.15.0</sup> — 获取名为
    key
    的环境变量,如果不存在则返回
    default
  • env_var(key)
    env(key)
    的废弃别名。
  • env_var_or_default(key, default)
    env(key, default)
    的废弃别名。
可以使用
||
运算符为空环境变量值替换默认值,该功能目前不稳定:
just
set unstable

foo := env('FOO', '') || 'DEFAULT_VALUE'

Executables

可执行文件

  • require(name)
    <sup>1.39.0</sup> — Search directories in the
    PATH
    environment variable for the executable
    name
    and return its full path, or halt with an error if no executable with
    name
    exists.
    just
    bash := require("bash")
    
    @test:
        echo "bash: '{{bash}}'"
    console
    $ just
    bash: '/bin/bash'
  • which(name)
    <sup>1.39.0</sup> — Search directories in the
    PATH
    environment variable for the executable
    name
    and return its full path, or the empty string if no executable with
    name
    exists. Currently unstable.
    just
    set unstable
    
    bosh := which("bosh")
    
    @test:
        echo "bosh: '{{bosh}}'"
    console
    $ just
    bosh: ''
  • require(name)
    <sup>1.39.0</sup> — 在
    PATH
    环境变量的目录中搜索可执行文件
    name
    并返回其完整路径,如果不存在则报错终止。
    just
    bash := require("bash")
    
    @test:
        echo "bash: '{{bash}}'"
    console
    $ just
    bash: '/bin/bash'
  • which(name)
    <sup>1.39.0</sup> — 在
    PATH
    环境变量的目录中搜索可执行文件
    name
    并返回其完整路径,如果不存在则返回空字符串,目前不稳定。
    just
    set unstable
    
    bosh := which("bosh")
    
    @test:
        echo "bosh: '{{bosh}}'"
    console
    $ just
    bosh: ''

Invocation Information

调用信息

  • is_dependency()
    - Returns the string
    true
    if the current recipe is being run as a dependency of another recipe, rather than being run directly, otherwise returns the string
    false
    .
  • is_dependency()
    - 如果当前recipe作为另一个recipe的依赖运行,而非直接运行,则返回字符串
    true
    ,否则返回字符串
    false

Invocation Directory

调用目录

  • invocation_directory()
    - Retrieves the absolute path to the current directory when
    just
    was invoked, before
    just
    changed it (chdir'd) prior to executing commands. On Windows,
    invocation_directory()
    uses
    cygpath
    to convert the invocation directory to a Cygwin-compatible
    /
    -separated path. Use
    invocation_directory_native()
    to return the verbatim invocation directory on all platforms.
For example, to call
rustfmt
on files just under the "current directory" (from the user/invoker's perspective), use the following rule:
just
rustfmt:
  find {{invocation_directory()}} -name \*.rs -exec rustfmt {} \;
Alternatively, if your command needs to be run from the current directory, you could use (e.g.):
just
build:
  cd {{invocation_directory()}}; ./some_script_that_needs_to_be_run_from_here
  • invocation_directory_native()
    - Retrieves the absolute path to the current directory when
    just
    was invoked, before
    just
    changed it (chdir'd) prior to executing commands.
  • invocation_directory()
    - 获取调用
    just
    时当前目录的绝对路径,即
    just
    在执行命令前切换目录之前的路径。在Windows上,
    invocation_directory()
    使用
    cygpath
    将调用目录转换为Cygwin兼容的
    /
    分隔路径。要在所有平台上返回原生的调用目录,请使用
    invocation_directory_native()
例如,要对用户/调用者视角下的"当前目录"下的文件调用
rustfmt
,可以使用以下规则:
just
rustfmt:
  find {{invocation_directory()}} -name \\*.rs -exec rustfmt {} \\;
或者,如果你的命令需要从当前目录运行,你可以使用:
just
build:
  cd {{invocation_directory()}}; ./some_script_that_needs_to_be_run_from_here
  • invocation_directory_native()
    - 获取调用
    just
    时当前目录的绝对路径,即
    just
    在执行命令前切换目录之前的路径。

Justfile and Justfile Directory

Justfile和Justfile目录

  • justfile()
    - Retrieves the path of the current
    justfile
    .
  • justfile_directory()
    - Retrieves the path of the parent directory of the current
    justfile
    .
For example, to run a command relative to the location of the current
justfile
:
just
script:
  {{justfile_directory()}}/scripts/some_script
  • justfile()
    - 获取当前
    justfile
    的路径。
  • justfile_directory()
    - 获取当前
    justfile
    父目录的路径。
例如,要运行相对于当前
justfile
位置的命令:
just
script:
  {{justfile_directory()}}/scripts/some_script

Source and Source Directory

源文件和源目录

  • source_file()
    <sup>1.27.0</sup> - Retrieves the path of the current source file.
  • source_directory()
    <sup>1.27.0</sup> - Retrieves the path of the parent directory of the current source file.
source_file()
and
source_directory()
behave the same as
justfile()
and
justfile_directory()
in the root
justfile
, but will return the path and directory, respectively, of the current
import
or
mod
source file when called from within an import or submodule.
  • source_file()
    <sup>1.27.0</sup> - 获取当前源文件的路径。
  • source_directory()
    <sup>1.27.0</sup> - 获取当前源文件父目录的路径。
在根
justfile
中,
source_file()
source_directory()
的行为与
justfile()
justfile_directory()
相同,但当在导入或子模块中调用时,会分别返回当前
import
mod
源文件的路径和目录。

Just Executable

Just可执行文件

  • just_executable()
    - Absolute path to the
    just
    executable.
For example:
just
executable:
  @echo The executable is at: {{just_executable()}}
console
$ just
The executable is at: /bin/just
  • just_executable()
    -
    just
    可执行文件的绝对路径。
例如:
just
executable:
  @echo The executable is at: {{just_executable()}}
console
$ just
The executable is at: /bin/just

Just Process ID

Just进程ID

  • just_pid()
    - Process ID of the
    just
    executable.
For example:
just
pid:
  @echo The process ID is: {{ just_pid() }}
console
$ just
The process ID is: 420
  • just_pid()
    -
    just
    可执行文件的进程ID。
例如:
just
pid:
  @echo The process ID is: {{ just_pid() }}
console
$ just
The process ID is: 420

String Manipulation

字符串操作

  • append(suffix, s)
    <sup>1.27.0</sup> Append
    suffix
    to whitespace-separated strings in
    s
    .
    append('/src', 'foo bar baz')
    'foo/src bar/src baz/src'
  • prepend(prefix, s)
    <sup>1.27.0</sup> Prepend
    prefix
    to whitespace-separated strings in
    s
    .
    prepend('src/', 'foo bar baz')
    'src/foo src/bar src/baz'
  • encode_uri_component(s)
    <sup>1.27.0</sup> - Percent-encode characters in
    s
    except
    [A-Za-z0-9_.!~*'()-]
    , matching the behavior of the JavaScript
    encodeURIComponent
    function
    .
  • quote(s)
    - Replace all single quotes with
    '\''
    and prepend and append single quotes to
    s
    . This is sufficient to escape special characters for many shells, including most Bourne shell descendants.
  • replace(s, from, to)
    - Replace all occurrences of
    from
    in
    s
    to
    to
    .
  • replace_regex(s, regex, replacement)
    - Replace all occurrences of
    regex
    in
    s
    to
    replacement
    . Regular expressions are provided by the Rust
    regex
    crate
    . See the syntax documentation for usage examples. Capture groups are supported. The
    replacement
    string uses Replacement string syntax.
  • trim(s)
    - Remove leading and trailing whitespace from
    s
    .
  • trim_end(s)
    - Remove trailing whitespace from
    s
    .
  • trim_end_match(s, substring)
    - Remove suffix of
    s
    matching
    substring
    .
  • trim_end_matches(s, substring)
    - Repeatedly remove suffixes of
    s
    matching
    substring
    .
  • trim_start(s)
    - Remove leading whitespace from
    s
    .
  • trim_start_match(s, substring)
    - Remove prefix of
    s
    matching
    substring
    .
  • trim_start_matches(s, substring)
    - Repeatedly remove prefixes of
    s
    matching
    substring
    .
  • append(suffix, s)
    <sup>1.27.0</sup>
    suffix
    追加到
    s
    中以空格分隔的每个字符串后面。
    append('/src', 'foo bar baz')
    'foo/src bar/src baz/src'
  • prepend(prefix, s)
    <sup>1.27.0</sup>
    prefix
    添加到
    s
    中以空格分隔的每个字符串前面。
    prepend('src/', 'foo bar baz')
    'src/foo src/bar src/baz'
  • encode_uri_component(s)
    <sup>1.27.0</sup> - 对
    s
    中的字符进行百分号编码,除了
    [A-Za-z0-9_.!~*'()-]
    ,与JavaScript
    encodeURIComponent
    函数
    的行为一致。
  • quote(s)
    - 将所有单引号替换为
    '\\''
    ,并在
    s
    前后添加单引号。这足以转义大多数Shell(包括大多数Bourne Shell衍生版本)的特殊字符。
  • replace(s, from, to)
    - 将
    s
    中所有
    from
    的出现替换为
    to
  • replace_regex(s, regex, replacement)
    - 将
    s
    中所有匹配
    regex
    的出现替换为
    replacement
    。正则表达式由Rust
    regex
    crate
    提供,语法示例请参考语法文档。支持捕获组,
    replacement
    字符串使用替换字符串语法
  • trim(s)
    - 移除
    s
    的前导和尾随空格。
  • trim_end(s)
    - 移除
    s
    的尾随空格。
  • trim_end_match(s, substring)
    - 移除
    s
    中匹配
    substring
    的后缀。
  • trim_end_matches(s, substring)
    - 重复移除
    s
    中匹配
    substring
    的后缀。
  • trim_start(s)
    - 移除
    s
    的前导空格。
  • trim_start_match(s, substring)
    - 移除
    s
    中匹配
    substring
    的前缀。
  • trim_start_matches(s, substring)
    - 重复移除
    s
    中匹配
    substring
    的前缀。

Case Conversion

大小写转换

  • capitalize(s)
    <sup>1.7.0</sup> - Convert first character of
    s
    to uppercase and the rest to lowercase.
  • kebabcase(s)
    <sup>1.7.0</sup> - Convert
    s
    to
    kebab-case
    .
  • lowercamelcase(s)
    <sup>1.7.0</sup> - Convert
    s
    to
    lowerCamelCase
    .
  • lowercase(s)
    - Convert
    s
    to lowercase.
  • shoutykebabcase(s)
    <sup>1.7.0</sup> - Convert
    s
    to
    SHOUTY-KEBAB-CASE
    .
  • shoutysnakecase(s)
    <sup>1.7.0</sup> - Convert
    s
    to
    SHOUTY_SNAKE_CASE
    .
  • snakecase(s)
    <sup>1.7.0</sup> - Convert
    s
    to
    snake_case
    .
  • titlecase(s)
    <sup>1.7.0</sup> - Convert
    s
    to
    Title Case
    .
  • uppercamelcase(s)
    <sup>1.7.0</sup> - Convert
    s
    to
    UpperCamelCase
    .
  • uppercase(s)
    - Convert
    s
    to uppercase.
  • capitalize(s)
    <sup>1.7.0</sup> - 将
    s
    的第一个字符转换为大写,其余字符转换为小写。
  • kebabcase(s)
    <sup>1.7.0</sup> - 将
    s
    转换为
    kebab-case
    格式。
  • lowercamelcase(s)
    <sup>1.7.0</sup> - 将
    s
    转换为
    lowerCamelCase
    格式。
  • lowercase(s)
    - 将
    s
    转换为小写。
  • shoutykebabcase(s)
    <sup>1.7.0</sup> - 将
    s
    转换为
    SHOUTY-KEBAB-CASE
    格式。
  • shoutysnakecase(s)
    <sup>1.7.0</sup> - 将
    s
    转换为
    SHOUTY_SNAKE_CASE
    格式。
  • snakecase(s)
    <sup>1.7.0</sup> - 将
    s
    转换为
    snake_case
    格式。
  • titlecase(s)
    <sup>1.7.0</sup> - 将
    s
    转换为
    Title Case
    格式。
  • uppercamelcase(s)
    <sup>1.7.0</sup> - 将
    s
    转换为
    UpperCamelCase
    格式。
  • uppercase(s)
    - 将
    s
    转换为大写。

Path Manipulation

路径操作

Fallible
可失败
  • absolute_path(path)
    - Absolute path to relative
    path
    in the working directory.
    absolute_path("./bar.txt")
    in directory
    /foo
    is
    /foo/bar.txt
    .
  • canonicalize(path)
    <sup>1.24.0</sup> - Canonicalize
    path
    by resolving symlinks and removing
    .
    ,
    ..
    , and extra
    /
    s where possible.
  • extension(path)
    - Extension of
    path
    .
    extension("/foo/bar.txt")
    is
    txt
    .
  • file_name(path)
    - File name of
    path
    with any leading directory components removed.
    file_name("/foo/bar.txt")
    is
    bar.txt
    .
  • file_stem(path)
    - File name of
    path
    without extension.
    file_stem("/foo/bar.txt")
    is
    bar
    .
  • parent_directory(path)
    - Parent directory of
    path
    .
    parent_directory("/foo/bar.txt")
    is
    /foo
    .
  • without_extension(path)
    -
    path
    without extension.
    without_extension("/foo/bar.txt")
    is
    /foo/bar
    .
These functions can fail, for example if a path does not have an extension, which will halt execution.
  • absolute_path(path)
    - 工作目录中相对路径
    path
    的绝对路径。目录
    /foo
    中的
    absolute_path("./bar.txt")
    /foo/bar.txt
  • canonicalize(path)
    <sup>1.24.0</sup> - 规范化
    path
    ,尽可能解析符号链接并移除
    .
    ..
    和多余的
    /
  • extension(path)
    -
    path
    的扩展名。
    extension("/foo/bar.txt")
    txt
  • file_name(path)
    -
    path
    的文件名,移除所有前导目录组件。
    file_name("/foo/bar.txt")
    bar.txt
  • file_stem(path)
    -
    path
    不带扩展名的文件名。
    file_stem("/foo/bar.txt")
    bar
  • parent_directory(path)
    -
    path
    的父目录。
    parent_directory("/foo/bar.txt")
    /foo
  • without_extension(path)
    - 不带扩展名的
    path
    without_extension("/foo/bar.txt")
    /foo/bar
这些函数可能会失败,例如路径没有扩展名,这会终止执行。
Infallible
不可失败
  • clean(path)
    - Simplify
    path
    by removing extra path separators, intermediate
    .
    components, and
    ..
    where possible.
    clean("foo//bar")
    is
    foo/bar
    ,
    clean("foo/..")
    is
    .
    ,
    clean("foo/./bar")
    is
    foo/bar
    .
  • join(a, b…)
    - This function uses
    /
    on Unix and
    \
    on Windows, which can be lead to unwanted behavior. The
    /
    operator, e.g.,
    a / b
    , which always uses
    /
    , should be considered as a replacement unless
    \
    s are specifically desired on Windows.
    Join path
    a
    with path
    b
    .
    join("foo/bar", "baz")
    is
    foo/bar/baz
    . Accepts two or more arguments.
  • clean(path)
    - 简化
    path
    ,移除多余的路径分隔符、中间的
    .
    组件,以及尽可能移除
    ..
    clean("foo//bar")
    foo/bar
    clean("foo/..")
    .
    clean("foo/./bar")
    foo/bar
  • join(a, b…)
    - 该函数在Unix上使用
    /
    ,在Windows上使用
    \\
    ,可能会导致意外行为。除非你确实需要在Windows上使用
    \\
    ,否则应该考虑使用
    /
    运算符(例如
    a / b
    ),它总是使用
    /
    将路径
    a
    与路径
    b
    拼接。
    join("foo/bar", "baz")
    foo/bar/baz
    。接受两个或更多参数。

Filesystem Access

文件系统访问

  • path_exists(path)
    - Returns
    true
    if the path points at an existing entity and
    false
    otherwise. Traverses symbolic links, and returns
    false
    if the path is inaccessible or points to a broken symlink.
  • read(path)
    <sup>1.39.0</sup> - Returns the content of file at
    path
    as string.
  • path_exists(path)
    - 如果路径指向存在的实体则返回
    true
    ,否则返回
    false
    。遍历符号链接,如果路径不可访问或指向损坏的符号链接则返回
    false
  • read(path)
    <sup>1.39.0</sup> - 以字符串形式返回
    path
    处文件的内容。
Error Reporting
错误报告
  • error(message)
    - Abort execution and report error
    message
    to user.
  • error(message)
    - 中止执行并向用户报告错误
    message

UUID and Hash Generation

UUID和哈希生成

  • blake3(string)
    <sup>1.25.0</sup> - Return BLAKE3 hash of
    string
    as hexadecimal string.
  • blake3_file(path)
    <sup>1.25.0</sup> - Return BLAKE3 hash of file at
    path
    as hexadecimal string.
  • sha256(string)
    - Return the SHA-256 hash of
    string
    as hexadecimal string.
  • sha256_file(path)
    - Return SHA-256 hash of file at
    path
    as hexadecimal string.
  • uuid()
    - Generate a random version 4 UUID.
  • blake3(string)
    <sup>1.25.0</sup> - 返回
    string
    BLAKE3哈希的十六进制字符串。
  • blake3_file(path)
    <sup>1.25.0</sup> - 返回
    path
    处文件的BLAKE3哈希的十六进制字符串。
  • sha256(string)
    - 返回
    string
    的SHA-256哈希的十六进制字符串。
  • sha256_file(path)
    - 返回
    path
    处文件的SHA-256哈希的十六进制字符串。
  • uuid()
    - 生成随机的版本4 UUID。

Random

随机

  • choose(n, alphabet)
    <sup>1.27.0</sup> - Generate a string of
    n
    randomly selected characters from
    alphabet
    , which may not contain repeated characters. For example,
    choose('64', HEX)
    will generate a random 64-character lowercase hex string.
  • choose(n, alphabet)
    <sup>1.27.0</sup> - 从
    alphabet
    中随机选择
    n
    个字符生成字符串,
    alphabet
    不能包含重复字符。例如,
    choose('64', HEX)
    会生成随机的64字符小写十六进制字符串。

Datetime

日期时间

  • datetime(format)
    <sup>1.30.0</sup> - Return local time with
    format
    .
  • datetime_utc(format)
    <sup>1.30.0</sup> - Return UTC time with
    format
    .
The arguments to
datetime
and
datetime_utc
are
strftime
-style format strings, see the
chrono
library docs
for details.
  • datetime(format)
    <sup>1.30.0</sup> - 按
    format
    格式返回本地时间。
  • datetime_utc(format)
    <sup>1.30.0</sup> - 按
    format
    格式返回UTC时间。
datetime
datetime_utc
的参数是
strftime
风格的格式字符串,详情请参考
chrono
库文档

Semantic Versions

语义化版本

  • semver_matches(version, requirement)
    <sup>1.16.0</sup> - Check whether a semantic
    version
    , e.g.,
    "0.1.0"
    matches a
    requirement
    , e.g.,
    ">=0.1.0"
    , returning
    "true"
    if so and
    "false"
    otherwise.
  • semver_matches(version, requirement)
    <sup>1.16.0</sup> - 检查语义化
    version
    (例如
    "0.1.0"
    )是否匹配
    requirement
    (例如
    ">=0.1.0"
    ),匹配则返回
    "true"
    ,否则返回
    "false"

Style

样式

  • style(name)
    <sup>1.37.0</sup> - Return a named terminal display attribute escape sequence used by
    just
    . Unlike terminal display attribute escape sequence constants, which contain standard colors and styles,
    style(name)
    returns an escape sequence used by
    just
    itself, and can be used to make recipe output match
    just
    's own output.
    Recognized values for
    name
    are
    'command'
    , for echoed recipe lines,
    error
    , and
    warning
    .
    For example, to style an error message:
    just
    scary:
      @echo '{{ style("error") }}OH NO{{ NORMAL }}'
  • style(name)
    <sup>1.37.0</sup> - 返回
    just
    使用的命名终端显示属性转义序列。与包含标准颜色和样式的终端显示属性转义序列常量不同,
    style(name)
    返回
    just
    自身使用的转义序列,可用于让recipe的输出与
    just
    自身的输出风格一致。
    name
    的可识别值有:
    'command'
    (用于回显的recipe行)、
    error
    warning
    例如,设置错误消息的样式:
    just
    scary:
      @echo '{{ style("error") }}OH NO{{ NORMAL }}'
User Directories<sup>1.23.0</sup>
用户目录<sup>1.23.0</sup>
These functions return paths to user-specific directories for things like configuration, data, caches, executables, and the user's home directory.
On Unix, these functions follow the XDG Base Directory Specification.
On MacOS and Windows, these functions return the system-specified user-specific directories. For example,
cache_directory()
returns
~/Library/Caches
on MacOS and
{FOLDERID_LocalAppData}
on Windows.
See the
dirs
crate for more details.
  • cache_directory()
    - The user-specific cache directory.
  • config_directory()
    - The user-specific configuration directory.
  • config_local_directory()
    - The local user-specific configuration directory.
  • data_directory()
    - The user-specific data directory.
  • data_local_directory()
    - The local user-specific data directory.
  • executable_directory()
    - The user-specific executable directory.
  • home_directory()
    - The user's home directory.
If you would like to use XDG base directories on all platforms you can use the
env(…)
function with the appropriate environment variable and fallback, although note that the XDG specification requires ignoring non-absolute paths, so for full compatibility with spec-compliant applications, you would need to do:
just
xdg_config_dir := if env('XDG_CONFIG_HOME', '') =~ '^/' {
  env('XDG_CONFIG_HOME')
} else {
  home_directory() / '.config'
}
这些函数返回用户特定目录的路径,用于存储配置、数据、缓存、可执行文件和用户主目录等内容。
在Unix上,这些函数遵循XDG基础目录规范
在MacOS和Windows上,这些函数返回系统指定的用户特定目录。例如,
cache_directory()
在MacOS上返回
~/Library/Caches
,在Windows上返回
{FOLDERID_LocalAppData}
更多详情请参考
dirs
crate。
  • cache_directory()
    - 用户特定的缓存目录。
  • config_directory()
    - 用户特定的配置目录。
  • config_local_directory()
    - 用户特定的本地配置目录。
  • data_directory()
    - 用户特定的数据目录。
  • data_local_directory()
    - 用户特定的本地数据目录。
  • executable_directory()
    - 用户特定的可执行文件目录。
  • home_directory()
    - 用户的主目录。
如果你想在所有平台上使用XDG基础目录,可以使用
env(…)
函数配合相应的环境变量和回退值,但请注意XDG规范要求忽略非绝对路径,因此要与符合规范的应用程序完全兼容,你需要这样做:
just
xdg_config_dir := if env('XDG_CONFIG_HOME', '') =~ '^/' {
  env('XDG_CONFIG_HOME')
} else {
  home_directory() / '.config'
}

Constants

常量

A number of constants are predefined:
NameValueValue on Windows
HEX
<sup>1.27.0</sup>
"0123456789abcdef"
HEXLOWER
<sup>1.27.0</sup>
"0123456789abcdef"
HEXUPPER
<sup>1.27.0</sup>
"0123456789ABCDEF"
PATH_SEP
<sup>1.41.0</sup>
"/"
"\"
PATH_VAR_SEP
<sup>1.41.0</sup>
":"
";"
CLEAR
<sup>1.37.0</sup>
"\ec"
NORMAL
<sup>1.37.0</sup>
"\e[0m"
BOLD
<sup>1.37.0</sup>
"\e[1m"
ITALIC
<sup>1.37.0</sup>
"\e[3m"
UNDERLINE
<sup>1.37.0</sup>
"\e[4m"
INVERT
<sup>1.37.0</sup>
"\e[7m"
HIDE
<sup>1.37.0</sup>
"\e[8m"
STRIKETHROUGH
<sup>1.37.0</sup>
"\e[9m"
BLACK
<sup>1.37.0</sup>
"\e[30m"
RED
<sup>1.37.0</sup>
"\e[31m"
GREEN
<sup>1.37.0</sup>
"\e[32m"
YELLOW
<sup>1.37.0</sup>
"\e[33m"
BLUE
<sup>1.37.0</sup>
"\e[34m"
MAGENTA
<sup>1.37.0</sup>
"\e[35m"
CYAN
<sup>1.37.0</sup>
"\e[36m"
WHITE
<sup>1.37.0</sup>
"\e[37m"
BG_BLACK
<sup>1.37.0</sup>
"\e[40m"
BG_RED
<sup>1.37.0</sup>
"\e[41m"
BG_GREEN
<sup>1.37.0</sup>
"\e[42m"
BG_YELLOW
<sup>1.37.0</sup>
"\e[43m"
BG_BLUE
<sup>1.37.0</sup>
"\e[44m"
BG_MAGENTA
<sup>1.37.0</sup>
"\e[45m"
BG_CYAN
<sup>1.37.0</sup>
"\e[46m"
BG_WHITE
<sup>1.37.0</sup>
"\e[47m"
just
@foo:
  echo {{HEX}}
console
$ just foo
0123456789abcdef
Constants starting with
\e
are ANSI escape sequences.
CLEAR
clears the screen, similar to the
clear
command. The rest are of the form
\e[Nm
, where
N
is an integer, and set terminal display attributes.
Terminal display attribute escape sequences can be combined, for example text weight
BOLD
, text style
STRIKETHROUGH
, foreground color
CYAN
, and background color
BG_BLUE
. They should be followed by
NORMAL
, to reset the terminal back to normal.
Escape sequences should be quoted, since
[
is treated as a special character by some shells.
just
@foo:
  echo '{{BOLD + STRIKETHROUGH + CYAN + BG_BLUE}}Hi!{{NORMAL}}'
预定义了许多常量:
名称取值Windows上的取值
HEX
<sup>1.27.0</sup>
"0123456789abcdef"
HEXLOWER
<sup>1.27.0</sup>
"0123456789abcdef"
HEXUPPER
<sup>1.27.0</sup>
"0123456789ABCDEF"
PATH_SEP
<sup>1.41.0</sup>
"/"
"\\\\"
PATH_VAR_SEP
<sup>1.41.0</sup>
":"
";"
CLEAR
<sup>1.37.0</sup>
"\\ec"
NORMAL
<sup>1.37.0</sup>
"\\e[0m"
BOLD
<sup>1.37.0</sup>
"\\e[1m"
ITALIC
<sup>1.37.0</sup>
"\\e[3m"
UNDERLINE
<sup>1.37.0</sup>
"\\e[4m"
INVERT
<sup>1.37.0</sup>
"\\e[7m"
HIDE
<sup>1.37.0</sup>
"\\e[8m"
STRIKETHROUGH
<sup>1.37.0</sup>
"\\e[9m"
BLACK
<sup>1.37.0</sup>
"\\e[30m"
RED
<sup>1.37.0</sup>
"\\e[31m"
GREEN
<sup>1.37.0</sup>
"\\e[32m"
YELLOW
<sup>1.37.0</sup>
"\\e[33m"
BLUE
<sup>1.37.0</sup>
"\\e[34m"
MAGENTA
<sup>1.37.0</sup>
"\\e[35m"
CYAN
<sup>1.37.0</sup>
"\\e[36m"
WHITE
<sup>1.37.0</sup>
"\\e[37m"
BG_BLACK
<sup>1.37.0</sup>
"\\e[40m"
BG_RED
<sup>1.37.0</sup>
"\\e[41m"
BG_GREEN
<sup>1.37.0</sup>
"\\e[42m"
BG_YELLOW
<sup>1.37.0</sup>
"\\e[43m"
BG_BLUE
<sup>1.37.0</sup>
"\\e[44m"
BG_MAGENTA
<sup>1.37.0</sup>
"\\e[45m"
BG_CYAN
<sup>1.37.0</sup>
"\\e[46m"
BG_WHITE
<sup>1.37.0</sup>
"\\e[47m"
just
@foo:
  echo {{HEX}}
console
$ just foo
0123456789abcdef
\\e
开头的常量是ANSI转义序列
CLEAR
清屏,类似于
clear
命令。其余的格式为
\\e[Nm
,其中
N
是整数,用于设置终端显示属性。
终端显示属性转义序列可以组合使用,例如字重
BOLD
、文本样式
STRIKETHROUGH
、前景色
CYAN
和背景色
BG_BLUE
。使用后应该跟随
NORMAL
,将终端重置为正常状态。
转义序列应该加引号,因为
[
会被一些Shell视为特殊字符。
just
@foo:
  echo '{{BOLD + STRIKETHROUGH + CYAN + BG_BLUE}}Hi!{{NORMAL}}'

Attributes

属性

Recipes,
mod
statements, and aliases may be annotated with attributes that change their behavior.
NameTypeDescription
[arg(ARG, help="HELP")]
<sup>1.46.0</sup>
recipePrint help string
HELP
for
ARG
in usage messages.
[arg(ARG, long="LONG")]
<sup>1.46.0</sup>
recipeRequire values of argument
ARG
to be passed as
--LONG
option.
[arg(ARG, short="S")]
<sup>1.46.0</sup>
recipeRequire values of argument
ARG
to be passed as short
-S
option.
[arg(ARG, value="VALUE")]
<sup>1.46.0</sup>
recipeMakes option
ARG
a flag which does not take a value.
[arg(ARG, pattern="PATTERN")]
<sup>1.45.0</sup>
recipeRequire values of argument
ARG
to match regular expression
PATTERN
.
[confirm]
<sup>1.17.0</sup>
recipeRequire confirmation prior to executing recipe.
[confirm(PROMPT)]
<sup>1.23.0</sup>
recipeRequire confirmation prior to executing recipe with a custom prompt.
[default]
<sup>1.43.0</sup>
recipeUse recipe as module's default recipe.
[doc(DOC)]
<sup>1.27.0</sup>
module, recipeSet recipe or module's documentation comment to
DOC
.
[extension(EXT)]
<sup>1.32.0</sup>
recipeSet shebang recipe script's file extension to
EXT
.
EXT
should include a period if one is desired.
[group(NAME)]
<sup>1.27.0</sup>
module, recipePut recipe or module in in group
NAME
.
[linux]
<sup>1.8.0</sup>
recipeEnable recipe on Linux.
[macos]
<sup>1.8.0</sup>
recipeEnable recipe on MacOS.
[metadata(METADATA)]
<sup>1.42.0</sup>
recipeAttach
METADATA
to recipe.
[no-cd]
<sup>1.9.0</sup>
recipeDon't change directory before executing recipe.
[no-exit-message]
<sup>1.7.0</sup>
recipeDon't print an error message if recipe fails.
[no-quiet]
<sup>1.23.0</sup>
recipeOverride globally quiet recipes and always echo out the recipe.
[openbsd]
<sup>1.38.0</sup>
recipeEnable recipe on OpenBSD.
[parallel]
<sup>1.42.0</sup>
recipeRun this recipe's dependencies in parallel.
[positional-arguments]
<sup>1.29.0</sup>
recipeTurn on positional arguments for this recipe.
[private]
<sup>1.10.0</sup>
alias, recipeMake recipe, alias, or variable private. See Private Recipes.
[script]
<sup>1.33.0</sup>
recipeExecute recipe as script. See script recipes for more details.
[script(COMMAND)]
<sup>1.32.0</sup>
recipeExecute recipe as a script interpreted by
COMMAND
. See script recipes for more details.
[unix]
<sup>1.8.0</sup>
recipeEnable recipe on Unixes. (Includes MacOS).
[windows]
<sup>1.8.0</sup>
recipeEnable recipe on Windows.
[working-directory(PATH)]
<sup>1.38.0</sup>
recipeSet recipe working directory.
PATH
may be relative or absolute. If relative, it is interpreted relative to the default working directory.
A recipe can have multiple attributes, either on multiple lines:
just
[no-cd]
[private]
foo:
    echo "foo"
Or separated by commas on a single line<sup>1.14.0</sup>:
just
[no-cd, private]
foo:
    echo "foo"
Attributes with a single argument may be written with a colon:
just
[group: 'bar']
foo:
Recipe、
mod
语句和别名可以添加属性注解来改变它们的行为。
名称类型描述
[arg(ARG, help="HELP")]
<sup>1.46.0</sup>
recipe在使用信息中打印参数
ARG
的帮助字符串
HELP
[arg(ARG, long="LONG")]
<sup>1.46.0</sup>
recipe要求通过
--LONG
选项传递参数
ARG
的值
[arg(ARG, short="S")]
<sup>1.46.0</sup>
recipe要求通过短选项
-S
传递参数
ARG
的值
[arg(ARG, value="VALUE")]
<sup>1.46.0</sup>
recipe将选项
ARG
设置为不需要值的flag
[arg(ARG, pattern="PATTERN")]
<sup>1.45.0</sup>
recipe要求参数
ARG
的值匹配正则表达式
PATTERN
[confirm]
<sup>1.17.0</sup>
recipe执行recipe前需要确认
[confirm(PROMPT)]
<sup>1.23.0</sup>
recipe执行recipe前需要确认,使用自定义提示语
[default]
<sup>1.43.0</sup>
recipe将该recipe作为模块的默认recipe
[doc(DOC)]
<sup>1.27.0</sup>
模块, recipe将recipe或模块的文档注释设置为
DOC
[extension(EXT)]
<sup>1.32.0</sup>
recipe设置shebang recipe脚本的文件扩展名为
EXT
,如果需要的话
EXT
应该包含点号
[group(NAME)]
<sup>1.27.0</sup>
模块, recipe将recipe或模块放入分组
NAME
[linux]
<sup>1.8.0</sup>
recipe在Linux上启用该recipe
[macos]
<sup>1.8.0</sup>
recipe在MacOS上启用该recipe
[metadata(METADATA)]
<sup>1.42.0</sup>
recipe为recipe附加
METADATA
[no-cd]
<sup>1.9.0</sup>
recipe执行recipe前不切换目录
[no-exit-message]
<sup>1.7.0</sup>
recipe如果recipe失败,不打印错误消息
[no-quiet]
<sup>1.23.0</sup>
recipe覆盖全局的quiet设置,始终回显recipe内容
[openbsd]
<sup>1.38.0</sup>
recipe在OpenBSD上启用该recipe
[parallel]
<sup>1.42.0</sup>
recipe并行运行该recipe的依赖
[positional-arguments]
<sup>1.29.0</sup>
recipe为该recipe开启位置参数
[private]
<sup>1.10.0</sup>
别名, recipe将recipe、别名或变量设为私有,参考私有Recipe
[script]
<sup>1.33.0</sup>
recipe将recipe作为脚本执行,更多细节参考脚本Recipe
[script(COMMAND)]
<sup>1.32.0</sup>
recipe将recipe作为由
COMMAND
解释的脚本执行,更多细节参考脚本Recipe
[unix]
<sup>1.8.0</sup>
recipe在Unix系统上启用该recipe(包含MacOS)
[windows]
<sup>1.8.0</sup>
recipe在Windows上启用该recipe
[working-directory(PATH)]
<sup>1.38.0</sup>
recipe设置recipe的工作目录,
PATH
可以是相对路径或绝对路径,如果是相对路径则相对于默认工作目录解析
一个recipe可以有多个属性,可以写在多行:
just
[no-cd]
[private]
foo:
    echo "foo"
也可以在一行用逗号分隔<sup>1.14.0</sup>
just
[no-cd, private]
foo:
    echo "foo"
带单个参数的属性可以用冒号编写:
just
[group: 'bar']
foo:

Enabling and Disabling Recipes<sup>1.8.0</sup>

启用和禁用Recipe<sup>1.8.0</sup>

The
[linux]
,
[macos]
,
[unix]
, and
[windows]
attributes are configuration attributes. By default, recipes are always enabled. A recipe with one or more configuration attributes will only be enabled when one or more of those configurations is active.
This can be used to write
justfile
s that behave differently depending on which operating system they run on. The
run
recipe in this
justfile
will compile and run
main.c
, using a different C compiler and using the correct output binary name for that compiler depending on the operating system:
just
[unix]
run:
  cc main.c
  ./a.out

[windows]
run:
  cl main.c
  main.exe
[linux]
[macos]
[unix]
[windows]
属性是配置属性。默认情况下,recipe始终启用。带有一个或多个配置属性的recipe只有在一个或多个配置处于活动状态时才会启用。
这可以用于编写在不同操作系统上表现不同的
justfile
。下面这个
justfile
中的
run
recipe会编译并运行
main.c
,根据操作系统使用不同的C编译器并使用正确的输出二进制文件名:
just
[unix]
run:
  cc main.c
  ./a.out

[windows]
run:
  cl main.c
  main.exe

Disabling Changing Directory<sup>1.9.0</sup>

禁用切换目录<sup>1.9.0</sup>

just
normally executes recipes with the current directory set to the directory that contains the
justfile
. This can be disabled using the
[no-cd]
attribute. This can be used to create recipes which use paths relative to the invocation directory, or which operate on the current directory.
For example, this
commit
recipe:
just
[no-cd]
commit file:
  git add {{file}}
  git commit
Can be used with paths that are relative to the current directory, because
[no-cd]
prevents
just
from changing the current directory when executing
commit
.
just
通常在执行recipe时将当前目录设置为包含
justfile
的目录。可以使用
[no-cd]
属性禁用该行为。这可以用于创建使用相对于调用目录的路径,或者对当前目录进行操作的recipe。
例如,这个
commit
recipe:
just
[no-cd]
commit file:
  git add {{file}}
  git commit
可以与相对于当前目录的路径一起使用,因为
[no-cd]
阻止
just
在执行
commit
时切换当前目录。

Requiring Confirmation for Recipes<sup>1.17.0</sup>

Recipe需要确认<sup>1.17.0</sup>

just
normally executes all recipes unless there is an error. The
[confirm]
attribute allows recipes require confirmation in the terminal prior to running. This can be overridden by passing
--yes
to
just
, which will automatically confirm any recipes marked by this attribute.
Recipes dependent on a recipe that requires confirmation will not be run if the relied upon recipe is not confirmed, as well as recipes passed after any recipe that requires confirmation.
just
[confirm]
delete-all:
  rm -rf *
just
通常会执行所有recipe,除非出现错误。
[confirm]
属性允许recipe在运行前需要在终端中确认。可以通过向
just
传递
--yes
覆盖该行为,会自动确认所有带有该属性标记的recipe。
如果依赖的recipe未被确认,依赖于它的recipe不会运行,任何需要确认的recipe之后传入的recipe也不会运行。
just
[confirm]
delete-all:
  rm -rf *

Custom Confirmation Prompt<sup>1.23.0</sup>

自定义确认提示<sup>1.23.0</sup>

The default confirmation prompt can be overridden with
[confirm(PROMPT)]
:
just
[confirm("Are you sure you want to delete everything?")]
delete-everything:
  rm -rf *
可以使用
[confirm(PROMPT)]
覆盖默认的确认提示:
just
[confirm("Are you sure you want to delete everything?")]
delete-everything:
  rm -rf *

Groups

分组

Recipes and modules may be annotated with one or more group names:
just
[group('lint')]
js-lint:
    echo 'Running JS linter…'

[group('rust recipes')]
[group('lint')]
rust-lint:
    echo 'Running Rust linter…'

[group('lint')]
cpp-lint:
  echo 'Running C++ linter…'
Recipe和模块可以添加一个或多个组名注解:
just
[group('lint')]
js-lint:
    echo 'Running JS linter…'

[group('rust recipes')]
[group('lint')]
rust-lint:
    echo 'Running Rust linter…'

[group('lint')]
cpp-lint:
  echo 'Running C++ linter…'

not in any group

not in any group

email-everyone: echo 'Sending mass email…'

Recipes are listed by group:
$ just --list Available recipes: email-everyone # not in any group
[lint]
cpp-lint
js-lint
rust-lint

[rust recipes]
rust-lint

`just --list --unsorted` prints recipes in their justfile order within each group:
$ just --list --unsorted Available recipes: (no group) email-everyone # not in any group
[lint]
js-lint
rust-lint
cpp-lint

[rust recipes]
rust-lint

Groups can be listed with `--groups`:
$ just --groups Recipe groups: lint rust recipes

Use `just --groups --unsorted` to print groups in their justfile order.
email-everyone: echo 'Sending mass email…'

Recipe按分组列出:
$ just --list Available recipes: email-everyone # not in any group
[lint]
cpp-lint
js-lint
rust-lint

[rust recipes]
rust-lint

`just --list --unsorted`按每个分组内recipe在justfile中的顺序打印:
$ just --list --unsorted Available recipes: (no group) email-everyone # not in any group
[lint]
js-lint
rust-lint
cpp-lint

[rust recipes]
rust-lint

可以使用`--groups`列出分组:
$ just --groups Recipe groups: lint rust recipes

使用`just --groups --unsorted`按分组在justfile中出现的顺序打印。

Command Evaluation Using Backticks

使用反引号进行命令求值

Backticks can be used to store the result of commands:
just
localhost := `dumpinterfaces | cut -d: -f2 | sed 's/\/.*//' | sed 's/ //g'`

serve:
  ./serve {{localhost}} 8080
Indented backticks, delimited by three backticks, are de-indented in the same manner as indented strings:
just
undefined
反引号可以用于存储命令的结果:
just
localhost := `dumpinterfaces | cut -d: -f2 | sed 's/\\/.*//' | sed 's/ //g'`

serve:
  ./serve {{localhost}} 8080
由三个反引号分隔的缩进反引号会以与缩进字符串相同的方式去除缩进:
just
undefined

This backtick evaluates the command
echo foo\necho bar\n
, which produces the value
foo\nbar\n
.

This backtick evaluates the command `echo foo\

stuff := ``` echo foo echo bar
undefined
See the Strings section for details on unindenting.
Backticks may not start with
#!
. This syntax is reserved for a future upgrade.
The
shell(…)
function
provides a more general mechanism to invoke external commands, including the ability to execute the contents of a variable as a command, and to pass arguments to a command.
echo bar
, which produces the value 
foo
bar
`. stuff := ``` echo foo echo bar
undefined
关于去除缩进的详情请参考字符串部分。
反引号不能以
#!
开头,该语法保留用于未来的功能升级。
shell(…)
函数
提供了更通用的调用外部命令的机制,包括执行变量内容作为命令的能力,以及向命令传递参数的能力。

Conditional Expressions

条件表达式

if
/
else
expressions evaluate different branches depending on if two expressions evaluate to the same value:
just
foo := if "2" == "2" { "Good!" } else { "1984" }

bar:
  @echo "{{foo}}"
console
$ just bar
Good!
It is also possible to test for inequality:
just
foo := if "hello" != "goodbye" { "xyz" } else { "abc" }

bar:
  @echo {{foo}}
console
$ just bar
xyz
And match against regular expressions:
just
foo := if "hello" =~ 'hel+o' { "match" } else { "mismatch" }

bar:
  @echo {{foo}}
console
$ just bar
match
Regular expressions are provided by the regex crate, whose syntax is documented on docs.rs. Since regular expressions commonly use backslash escape sequences, consider using single-quoted string literals, which will pass slashes to the regex parser unmolested.
Conditional expressions short-circuit, which means they only evaluate one of their branches. This can be used to make sure that backtick expressions don't run when they shouldn't.
just
foo := if env_var("RELEASE") == "true" { `get-something-from-release-database` } else { "dummy-value" }
Conditionals can be used inside of recipes:
just
bar foo:
  echo {{ if foo == "bar" { "hello" } else { "goodbye" } }}
Multiple conditionals can be chained:
just
foo := if "hello" == "goodbye" {
  "xyz"
} else if "a" == "a" {
  "abc"
} else {
  "123"
}

bar:
  @echo {{foo}}
console
$ just bar
abc
if
/
else
表达式根据两个表达式的计算结果是否相同来计算不同的分支:
just
foo := if "2" == "2" { "Good!" } else { "1984" }

bar:
  @echo "{{foo}}"
console
$ just bar
Good!
也可以测试不相等:
just
foo := if "hello" != "goodbye" { "xyz" } else { "abc" }

bar:
  @echo {{foo}}
console
$ just bar
xyz
还可以匹配正则表达式:
just
foo := if "hello" =~ 'hel+o' { "match" } else { "mismatch" }

bar:
  @echo {{foo}}
console
$ just bar
match
正则表达式由regex crate提供,其语法在docs.rs上有文档说明。由于正则表达式通常使用反斜杠转义序列,建议使用单引号字符串字面量,它会将斜杠原封不动地传递给正则表达式解析器。
条件表达式会短路,这意味着它们只会计算其中一个分支。这可以用于确保反引号表达式在不应该运行的时候不会运行。
just
foo := if env_var("RELEASE") == "true" { `get-something-from-release-database` } else { "dummy-value" }
条件可以在recipe内部使用:
just
bar foo:
  echo {{ if foo == "bar" { "hello" } else { "goodbye" } }}
多个条件可以链式使用:
just
foo := if "hello" == "goodbye" {
  "xyz"
} else if "a" == "a" {
  "abc"
} else {
  "123"
}

bar:
  @echo {{foo}}
console
$ just bar
abc

Stopping execution with error

报错终止执行

Execution can be halted with the
error
function. For example:
just
foo := if "hello" == "goodbye" {
  "xyz"
} else if "a" == "b" {
  "abc"
} else {
  error("123")
}
Which produce the following error when run:
error: Call to function `error` failed: 123
   |
16 |   error("123")
可以使用
error
函数终止执行。例如:
just
foo := if "hello" == "goodbye" {
  "xyz"
} else if "a" == "b" {
  "abc"
} else {
  error("123")
}
运行时会产生以下错误:
error: Call to function `error` failed: 123
   |
16 |   error("123")

Setting Variables from the Command Line

从命令行设置变量

Variables can be overridden from the command line.
just
os := "linux"

test: build
  ./test --test {{os}}

build:
  ./build {{os}}
console
$ just
./build linux
./test --test linux
Any number of arguments of the form
NAME=VALUE
can be passed before recipes:
console
$ just os=plan9
./build plan9
./test --test plan9
Or you can use the
--set
flag:
console
$ just --set os bsd
./build bsd
./test --test bsd
可以从命令行覆盖变量。
just
os := "linux"

test: build
  ./test --test {{os}}

build:
  ./build {{os}}
console
$ just
./build linux
./test --test linux
可以在recipe之前传递任意数量的
NAME=VALUE
格式的参数:
console
$ just os=plan9
./build plan9
./test --test plan9
或者你可以使用
--set
flag:
console
$ just --set os bsd
./build bsd
./test --test bsd

Getting and Setting Environment Variables

获取和设置环境变量

Exporting
just
Variables

导出
just
变量

Assignments prefixed with the
export
keyword will be exported to recipes as environment variables:
just
export RUST_BACKTRACE := "1"

test:
  # will print a stack trace if it crashes
  cargo test
Parameters prefixed with a
$
will be exported as environment variables:
just
test $RUST_BACKTRACE="1":
  # will print a stack trace if it crashes
  cargo test
Exported variables and parameters are not exported to backticks in the same scope.
just
export WORLD := "world"
export
关键字为前缀的赋值会作为环境变量导出给recipe:
just
export RUST_BACKTRACE := "1"

test:
  # will print a stack trace if it crashes
  cargo test
$
为前缀的参数会作为环境变量导出:
just
test $RUST_BACKTRACE="1":
  # will print a stack trace if it crashes
  cargo test
导出的变量和参数不会导出到同一作用域的反引号中。
just
export WORLD := "world"

This backtick will fail with "WORLD: unbound variable"

This backtick will fail with "WORLD: unbound variable"

BAR :=
echo hello $WORLD

```just
BAR :=
echo hello $WORLD

```just

Running
just a foo
will fail with "A: unbound variable"

Running
just a foo
will fail with "A: unbound variable"

a $A $B=
echo $A
: echo $A $B

When [export](#export) is set, all `just` variables are exported as environment
variables.
a $A $B=
echo $A
: echo $A $B

当设置了[export](#export)时,所有`just`变量都会作为环境变量导出。

Unexporting Environment Variables<sup>1.29.0</sup>

取消导出环境变量<sup>1.29.0</sup>

Environment variables can be unexported with the
unexport keyword
:
just
unexport FOO

@foo:
  echo $FOO
$ export FOO=bar
$ just foo
sh: FOO: unbound variable
可以使用
unexport
关键字取消导出环境变量:
just
unexport FOO

@foo:
  echo $FOO
$ export FOO=bar
$ just foo
sh: FOO: unbound variable

Getting Environment Variables from the environment

从环境中获取环境变量

Environment variables from the environment are passed automatically to the recipes.
just
print_home_folder:
  echo "HOME is: '${HOME}'"
console
$ just
HOME is '/home/myuser'
来自环境的环境变量会自动传递给recipe。
just
print_home_folder:
  echo "HOME is: '${HOME}'"
console
$ just
HOME is '/home/myuser'

Setting
just
Variables from Environment Variables

从环境变量设置
just
变量

Environment variables can be propagated to
just
variables using the
env()
function. See environment-variables.
可以使用
env()
函数将环境变量传递给
just
变量,参考环境变量

Recipe Parameters

Recipe参数

Recipes may have parameters. Here recipe
build
has a parameter called
target
:
just
build target:
  @echo 'Building {{target}}…'
  cd {{target}} && make
To pass arguments on the command line, put them after the recipe name:
console
$ just build my-awesome-project
Building my-awesome-project…
cd my-awesome-project && make
To pass arguments to a dependency, put the dependency in parentheses along with the arguments:
just
default: (build "main")

build target:
  @echo 'Building {{target}}…'
  cd {{target}} && make
Variables can also be passed as arguments to dependencies:
just
target := "main"

_build version:
  @echo 'Building {{version}}…'
  cd {{version}} && make

build: (_build target)
A command's arguments can be passed to dependency by putting the dependency in parentheses along with the arguments:
just
build target:
  @echo "Building {{target}}…"

push target: (build target)
  @echo 'Pushing {{target}}…'
Parameters may have default values:
just
default := 'all'

test target tests=default:
  @echo 'Testing {{target}}:{{tests}}…'
  ./test --tests {{tests}} {{target}}
Parameters with default values may be omitted:
console
$ just test server
Testing server:all…
./test --tests all server
Or supplied:
console
$ just test server unit
Testing server:unit…
./test --tests unit server
Default values may be arbitrary expressions, but expressions containing the
+
,
&&
,
||
, or
/
operators must be parenthesized:
just
arch := "wasm"

test triple=(arch + "-unknown-unknown") input=(arch / "input.dat"):
  ./test {{triple}}
The last parameter of a recipe may be variadic, indicated with either a
+
or a
*
before the argument name:
just
backup +FILES:
  scp {{FILES}} me@server.com:
Variadic parameters prefixed with
+
accept one or more arguments and expand to a string containing those arguments separated by spaces:
console
$ just backup FAQ.md GRAMMAR.md
scp FAQ.md GRAMMAR.md me@server.com:
FAQ.md                  100% 1831     1.8KB/s   00:00
GRAMMAR.md              100% 1666     1.6KB/s   00:00
Variadic parameters prefixed with
*
accept zero or more arguments and expand to a string containing those arguments separated by spaces, or an empty string if no arguments are present:
just
commit MESSAGE *FLAGS:
  git commit {{FLAGS}} -m "{{MESSAGE}}"
Variadic parameters can be assigned default values. These are overridden by arguments passed on the command line:
just
test +FLAGS='-q':
  cargo test {{FLAGS}}
{{…}}
substitutions may need to be quoted if they contain spaces. For example, if you have the following recipe:
just
search QUERY:
  lynx https://www.google.com/?q={{QUERY}}
And you type:
console
$ just search "cat toupee"
just
will run the command
lynx https://www.google.com/?q=cat toupee
, which will get parsed by
sh
as
lynx
,
https://www.google.com/?q=cat
, and
toupee
, and not the intended
lynx
and
https://www.google.com/?q=cat toupee
.
You can fix this by adding quotes:
just
search QUERY:
  lynx 'https://www.google.com/?q={{QUERY}}'
Parameters prefixed with a
$
will be exported as environment variables:
just
foo $bar:
  echo $bar
Parameters may be constrained to match regular expression patterns using the
[arg("name", pattern="pattern")]
attribute<sup>1.45.0</sup>:
just
[arg('n', pattern='\d+')]
double n:
  echo $(({{n}} * 2))
A leading
^
and trailing
$
are added to the pattern, so it must match the entire argument value.
You may constrain the pattern to a number of alternatives using the
|
operator:
just
[arg('flag', pattern='--help|--version')]
info flag:
  just {{flag}}
Regular expressions are provided by the Rust
regex
crate
. See the syntax documentation for usage examples.
Usage information for a recipe may be printed with the
--usage
subcommand<sup>1.46.0</sup>:
console
$ just --usage foo
Usage: just foo [OPTIONS] bar

Arguments:
  bar
Help strings may be added to arguments using the
[arg(ARG, help=HELP)]
attribute:
just
[arg("bar", help="hello")]
foo bar:
console
$ just --usage foo
Usage: just foo bar

Arguments:
  bar hello
Recipe可以有参数。下面的
build
recipe有一个名为
target
的参数:
just
build target:
  @echo 'Building {{target}}…'
  cd {{target}} && make
要在命令行传递参数,请将它们放在recipe名称后面:
console
$ just build my-awesome-project
Building my-awesome-project…
cd my-awesome-project && make
要向依赖传递参数,请将依赖和参数放在括号中:
just
default: (build "main")

build target:
  @echo 'Building {{target}}…'
  cd {{target}} && make
变量也可以作为参数传递给依赖:
just
target := "main"

_build version:
  @echo 'Building {{version}}…'
  cd {{version}} && make

build: (_build target)
命令的参数可以传递给依赖,方法是将依赖和参数放在括号中:
just
build target:
  @echo "Building {{target}}…"

push target: (build target)
  @echo 'Pushing {{target}}…'
参数可以有默认值:
just
default := 'all'

test target tests=default:
  @echo 'Testing {{target}}:{{tests}}…'
  ./test --tests {{tests}} {{target}}
带有默认值的参数可以省略:
console
$ just test server
Testing server:all…
./test --tests all server
也可以提供值:
console
$ just test server unit
Testing server:unit…
./test --tests unit server
默认值可以是任意表达式,但包含
+
&&
||
/
运算符的表达式必须放在括号中:
just
arch := "wasm"

test triple=(arch + "-unknown-unknown") input=(arch / "input.dat"):
  ./test {{triple}}
Recipe的最后一个参数可以是可变参数,用
+
*
加参数名表示:
just
backup +FILES:
  scp {{FILES}} me@server.com:
带有
+
前缀的可变参数接受一个或多个参数,展开为用空格分隔的这些参数的字符串:
console
$ just backup FAQ.md GRAMMAR.md
scp FAQ.md GRAMMAR.md me@server.com:
FAQ.md                  100% 1831     1.8KB/s   00:00
GRAMMAR.md              100% 1666     1.6KB/s   00:00
带有
*
前缀的可变参数接受零个或多个参数,展开为用空格分隔的这些参数的字符串,如果没有参数则展开为空字符串:
just
commit MESSAGE *FLAGS:
  git commit {{FLAGS}} -m "{{MESSAGE}}"
可变参数可以设置默认值,这些默认值会被命令行传递的参数覆盖:
just
test +FLAGS='-q':
  cargo test {{FLAGS}}
如果
{{…}}
替换包含空格,可能需要加引号。例如,如果你有以下recipe:
just
search QUERY:
  lynx https://www.google.com/?q={{QUERY}}
然后你输入:
console
$ just search "cat toupee"
just
会运行命令
lynx https://www.google.com/?q=cat toupee
,它会被
sh
解析为
lynx
https://www.google.com/?q=cat
toupee
,而不是预期的
lynx
https://www.google.com/?q=cat toupee
你可以通过添加引号来解决这个问题:
just
search QUERY:
  lynx 'https://www.google.com/?q={{QUERY}}'
$
为前缀的参数会作为环境变量导出:
just
foo $bar:
  echo $bar
可以使用
[arg("name", pattern="pattern")]
属性限制参数匹配正则表达式模式<sup>1.45.0</sup>
just
[arg('n', pattern='\\d+')]
double n:
  echo $(({{n}} * 2))
模式会自动添加开头的
^
和结尾的
$
,因此必须匹配整个参数值。
你可以使用
|
运算符将模式限制为多个备选值:
just
[arg('flag', pattern='--help|--version')]
info flag:
  just {{flag}}
正则表达式由Rust
regex
crate
提供,语法示例请参考语法文档
可以使用
--usage
子命令打印recipe的使用信息<sup>1.46.0</sup>
console
$ just --usage foo
Usage: just foo [OPTIONS] bar

Arguments:
  bar
可以使用
[arg(ARG, help=HELP)]
属性为参数添加帮助字符串:
just
[arg("bar", help="hello")]
foo bar:
console
$ just --usage foo
Usage: just foo bar

Arguments:
  bar hello

Recipe Flags and Options

Recipe Flag和选项

Recipe parameters are positional by default.
In this
justfile
:
just
@foo bar:
  echo bar={{bar}}
The parameter
bar
is positional:
console
$ just foo hello
bar=hello
The
[arg(ARG, long=OPTION)]
<sup>1.46.0</sup> attribute can be used to make a parameter a long option.
In this
justfile
:
just
[arg("bar", long="bar")]
foo bar:
The parameter
bar
is given with the
--bar
option:
console
$ just foo --bar hello
bar=hello
Options may also be passed with
--name=value
syntax:
console
$ just foo --bar=hello
bar=hello
The value of
long
can be omitted, in which case the option defaults to the name of the parameter:
just
[arg("bar", long)]
foo bar:
The
[arg(ARG, short=OPTION)]
<sup>1.46.0</sup> attribute can be used to make a parameter a short option.
In this
justfile
:
just
[arg("bar", short="b")]
foo bar:
The parameter
bar
is given with the
-b
option:
console
$ just foo -b hello
bar=hello
If a parameter has both a long and short option, it may be passed using either.
Variadic
+
and
?
parameters cannot be options.
The
[arg(ARG, value=VALUE, …)]
<sup>1.46.0</sup> attribute can be used with
long
or
short
to make a parameter a flag which does not take a value.
In this
justfile
:
just
[arg("bar", long="bar", value="hello")]
foo bar:
The parameter
bar
is given with the
--bar
option, but does not take a value, and instead takes the value given in the
[arg]
attribute:
console
$ just foo --bar
bar=hello
This is useful for unconditionally requiring a flag like
--force
on dangerous commands.
A flag is optional if its parameter has a default:
just
[arg("bar", long="bar", value="hello")]
foo bar="goodbye":
Causing it to receive the default when not passed in the invocation:
console
$ just foo
bar=goodbye
Recipe参数默认是位置参数。
在这个
justfile
中:
just
@foo bar:
  echo bar={{bar}}
参数
bar
是位置参数:
console
$ just foo hello
bar=hello
可以使用
[arg(ARG, long=OPTION)]
<sup>1.46.0</sup>属性将参数设置为长选项。
在这个
justfile
中:
just
[arg("bar", long="bar")]
foo bar:
参数
bar
通过
--bar
选项传递:
console
$ just foo --bar hello
bar=hello
选项也可以使用
--name=value
语法传递:
console
$ just foo --bar=hello
bar=hello
long
的值可以省略,此时选项默认使用参数的名称:
just
[arg("bar", long)]
foo bar:
可以使用
[arg(ARG, short=OPTION)]
<sup>1.46.0</sup>属性将参数设置为短选项。
在这个
justfile
中:
just
[arg("bar", short="b")]
foo bar:
参数
bar
通过
-b
选项传递:
console
$ just foo -b hello
bar=hello
如果一个参数同时有长选项和短选项,可以使用任意一种方式传递。
可变的
+
?
参数不能是选项。
可以将
[arg(ARG, value=VALUE, …)]
<sup>1.46.0</sup>属性与
long
short
一起使用,将参数设置为不需要值的flag。
在这个
justfile
中:
just
[arg("bar", long="bar", value="hello")]
foo bar:
参数
bar
通过
--bar
选项提供,但不需要值,而是使用
[arg]
属性中给出的值:
console
$ just foo --bar
bar=hello
这对于危险命令强制需要
--force
之类的flag非常有用。
如果flag的参数有默认值,则该flag是可选的:
just
[arg("bar", long="bar", value="hello")]
foo bar="goodbye":
调用时如果不传递则接收默认值:
console
$ just foo
bar=goodbye

Dependencies

依赖

Dependencies run before recipes that depend on them:
just
a: b
  @echo A

b:
  @echo B
$ just a
B
A
In a given invocation of
just
, a recipe with the same arguments will only run once, regardless of how many times it appears in the command-line invocation, or how many times it appears as a dependency:
just
a:
  @echo A

b: a
  @echo B

c: a
  @echo C
$ just a a a a a
A
$ just b c
A
B
C
Multiple recipes may depend on a recipe that performs some kind of setup, and when those recipes run, that setup will only be performed once:
just
build:
  cc main.c

test-foo: build
  ./a.out --test foo

test-bar: build
  ./a.out --test bar
$ just test-foo test-bar
cc main.c
./a.out --test foo
./a.out --test bar
Recipes in a given run are only skipped when they receive the same arguments:
just
build:
  cc main.c

test TEST: build
  ./a.out --test {{TEST}}
$ just test foo test bar
cc main.c
./a.out --test foo
./a.out --test bar
依赖在依赖它们的recipe之前运行:
just
a: b
  @echo A

b:
  @echo B
$ just a
B
A
在一次
just
调用中,带有相同参数的recipe只会运行一次,无论它在命令行调用中出现多少次,或者作为依赖出现多少次:
just
a:
  @echo A

b: a
  @echo B

c: a
  @echo C
$ just a a a a a
A
$ just b c
A
B
C
多个recipe可以依赖于执行某种设置的recipe,当这些recipe运行时,该设置只会执行一次:
just
build:
  cc main.c

test-foo: build
  ./a.out --test foo

test-bar: build
  ./a.out --test bar
$ just test-foo test-bar
cc main.c
./a.out --test foo
./a.out --test bar
只有当接收到相同的参数时,给定运行中的recipe才会被跳过:
just
build:
  cc main.c

test TEST: build
  ./a.out --test {{TEST}}
$ just test foo test bar
cc main.c
./a.out --test foo
./a.out --test bar

Running Recipes at the End of a Recipe

在Recipe结束时运行Recipe

Normal dependencies of a recipes always run before a recipe starts. That is to say, the dependee always runs before the depender. These dependencies are called "prior dependencies".
A recipe can also have subsequent dependencies, which run immediately after the recipe and are introduced with an
&&
:
just
a:
  echo 'A!'

b: a && c d
  echo 'B!'

c:
  echo 'C!'

d:
  echo 'D!'
…running b prints:
console
$ just b
echo 'A!'
A!
echo 'B!'
B!
echo 'C!'
C!
echo 'D!'
D!
Recipe的普通依赖总是在recipe开始之前运行,也就是说被依赖项总是在依赖项之前运行。这些依赖被称为"前置依赖"。
Recipe也可以有后续依赖,它们会在recipe结束后立即运行,用
&&
引入:
just
a:
  echo 'A!'

b: a && c d
  echo 'B!'

c:
  echo 'C!'

d:
  echo 'D!'
…运行b会打印:
console
$ just b
echo 'A!'
A!
echo 'B!'
B!
echo 'C!'
C!
echo 'D!'
D!

Running Recipes in the Middle of a Recipe

在Recipe中间运行Recipe

just
doesn't support running recipes in the middle of another recipe, but you can call
just
recursively in the middle of a recipe. Given the following
justfile
:
just
a:
  echo 'A!'

b: a
  echo 'B start!'
  just c
  echo 'B end!'

c:
  echo 'C!'
…running b prints:
console
$ just b
echo 'A!'
A!
echo 'B start!'
B start!
echo 'C!'
C!
echo 'B end!'
B end!
This has limitations, since recipe
c
is run with an entirely new invocation of
just
: Assignments will be recalculated, dependencies might run twice, and command line arguments will not be propagated to the child
just
process.
just
不支持在另一个recipe中间运行recipe,但你可以在recipe中间递归调用
just
。给定以下
justfile
just
a:
  echo 'A!'

b: a
  echo 'B start!'
  just c
  echo 'B end!'

c:
  echo 'C!'
…运行b会打印:
console
$ just b
echo 'A!'
A!
echo 'B start!'
B start!
echo 'C!'
C!
echo 'B end!'
B end!
这有局限性,因为recipe
c
是在全新的
just
调用中运行的:赋值会被重新计算,依赖可能会运行两次,命令行参数不会传递给子
just
进程。

Shebang Recipes

Shebang Recipe

Recipes that start with
#!
are called shebang recipes, and are executed by saving the recipe body to a file and running it. This lets you write recipes in different languages:
just
polyglot: python js perl sh ruby nu

python:
  #!/usr/bin/env python3
  print('Hello from python!')

js:
  #!/usr/bin/env node
  console.log('Greetings from JavaScript!')

perl:
  #!/usr/bin/env perl
  print "Larry Wall says Hi!\n";

sh:
  #!/usr/bin/env sh
  hello='Yo'
  echo "$hello from a shell script!"

nu:
  #!/usr/bin/env nu
  let hello = 'Hola'
  echo $"($hello) from a nushell script!"

ruby:
  #!/usr/bin/env ruby
  puts "Hello from ruby!"
console
$ just polyglot
Hello from python!
Greetings from JavaScript!
Larry Wall says Hi!
Yo from a shell script!
Hola from a nushell script!
Hello from ruby!
On Unix-like operating systems, including Linux and MacOS, shebang recipes are executed by saving the recipe body to a file in a temporary directory, marking the file as executable, and executing it. The OS then parses the shebang line into a command line and invokes it, including the path to the file. For example, if a recipe starts with
#!/usr/bin/env bash
, the final command that the OS runs will be something like
/usr/bin/env bash /tmp/PATH_TO_SAVED_RECIPE_BODY
.
Shebang line splitting is operating system dependent. When passing a command with arguments, you may need to tell
env
to split them explicitly by using the
-S
flag:
just
run:
  #!/usr/bin/env -S bash -x
  ls
Windows does not support shebang lines. On Windows,
just
splits the shebang line into a command and arguments, saves the recipe body to a file, and invokes the split command and arguments, adding the path to the saved recipe body as the final argument. For example, on Windows, if a recipe starts with
#! py
, the final command the OS runs will be something like
py C:\Temp\PATH_TO_SAVED_RECIPE_BODY
.
#!
开头的recipe称为shebang recipe,执行方式是将recipe体保存到文件中然后运行它。这允许你用不同的编程语言编写recipe:
just
polyglot: python js perl sh ruby nu

python:
  #!/usr/bin/env python3
  print('Hello from python!')

js:
  #!/usr/bin/env node
  console.log('Greetings from JavaScript!')

perl:
  #!/usr/bin/env perl
  print "Larry Wall says Hi!\
";

sh:
  #!/usr/bin/env sh
  hello='Yo'
  echo "$hello from a shell script!"

nu:
  #!/usr/bin/env nu
  let hello = 'Hola'
  echo $"($hello) from a nushell script!"

ruby:
  #!/usr/bin/env ruby
  puts "Hello from ruby!"
console
$ just polyglot
Hello from python!
Greetings from JavaScript!
Larry Wall says Hi!
Yo from a shell script!
Hola from a nushell script!
Hello from ruby!
在类Unix操作系统上,包括Linux和MacOS,shebang recipe的执行方式是将recipe体保存到临时目录的文件中,标记文件为可执行,然后执行它。操作系统会将shebang行解析为命令行并调用它,包含保存的recipe体的路径。例如,如果recipe以
#!/usr/bin/env bash
开头,操作系统最终运行的命令会类似于
/usr/bin/env bash /tmp/PATH_TO_SAVED_RECIPE_BODY
Shebang行的拆分取决于操作系统。传递带参数的命令时,你可能需要使用
-S
flag告诉
env
显式拆分它们:
just
run:
  #!/usr/bin/env -S bash -x
  ls
Windows不支持shebang行。在Windows上,
just
会将shebang行拆分为命令和参数,将recipe体保存到文件中,然后调用拆分后的命令和参数,将保存的recipe体的路径作为最后一个参数添加。例如,在Windows上,如果recipe以
#! py
开头,操作系统最终运行的命令会类似于
py C:\\Temp\\PATH_TO_SAVED_RECIPE_BODY

Script Recipes

脚本Recipe

Recipes with a
[script(COMMAND)]
<sup>1.32.0</sup> attribute are run as scripts interpreted by
COMMAND
. This avoids some of the issues with shebang recipes, such as the use of
cygpath
on Windows, the need to use
/usr/bin/env
, inconsistencies in shebang line splitting across Unix OSs, and requiring a temporary directory from which files can be executed.
Recipes with an empty
[script]
attribute are executed with the value of
set script-interpreter := […]
<sup>1.33.0</sup>, defaulting to
sh -eu
, and not the value of
set shell
.
The body of the recipe is evaluated, written to disk in the temporary directory, and run by passing its path as an argument to
COMMAND
.
带有
[script(COMMAND)]
<sup>1.32.0</sup>属性的recipe作为由
COMMAND
解释的脚本运行。这避免了shebang recipe的一些问题,例如Windows上
cygpath
的使用、需要使用
/usr/bin/env
、不同Unix操作系统上shebang行拆分的不一致,以及需要允许执行的临时目录。
带有空
[script]
属性的recipe使用
set script-interpreter := […]
<sup>1.33.0</sup>的值执行,默认为
sh -eu
,而不是
set shell
的值。
Recipe体会被计算,写入临时目录的磁盘,然后通过将其路径作为参数传递给
COMMAND
来运行。

Script and Shebang Recipe Temporary Files

脚本和Shebang Recipe临时文件

Both script and shebang recipes write the recipe body to a temporary file for execution. Script recipes execute that file by passing it to a command, while shebang recipes execute the file directly. Shebang recipe execution will fail if the filesystem containing the temporary file is mounted with
noexec
or is otherwise non-executable.
The directory that
just
writes temporary files to may be configured in a number of ways, from highest to lowest precedence:
  • Globally with the
    --tempdir
    command-line option or the
    JUST_TEMPDIR
    environment variable<sup>1.41.0</sup>.
  • On a per-module basis with the
    tempdir
    setting.
  • Globally on Linux with the
    XDG_RUNTIME_DIR
    environment variable.
  • Falling back to the directory returned by std::env::temp_dir.
脚本和shebang recipe都会将recipe体写入临时文件以便执行。脚本recipe通过将文件传递给命令来执行,而shebang recipe直接执行文件。如果包含临时文件的文件系统以
noexec
挂载或者不可执行,shebang recipe的执行会失败。
just
写入临时文件的目录可以通过多种方式配置,优先级从高到低:
  • 全局通过
    --tempdir
    命令行选项或
    JUST_TEMPDIR
    环境变量<sup>1.41.0</sup>
  • 每个模块通过
    tempdir
    设置。
  • Linux上全局通过
    XDG_RUNTIME_DIR
    环境变量。
  • 回退到std::env::temp_dir返回的目录。

Python Recipes with
uv

使用
uv
的Python Recipe

uv
is an excellent cross-platform python project manager, written in Rust.
Using the
[script]
attribute and
script-interpreter
setting,
just
can easily be configured to run Python recipes with
uv
:
just
set unstable

set script-interpreter := ['uv', 'run', '--script']

[script]
hello:
  print("Hello from Python!")

[script]
goodbye:
  # /// script
  # requires-python = ">=3.11"
  # dependencies=["sh"]
  # ///
  import sh
  print(sh.echo("Goodbye from Python!"), end='')
Of course, a shebang also works:
just
hello:
  #!/usr/bin/env -S uv run --script
  print("Hello from Python!")
uv
是一款优秀的跨平台Python项目管理器,使用Rust编写。
使用
[script]
属性和
script-interpreter
设置,可以轻松配置
just
uv
运行Python recipe:
just
set unstable

set script-interpreter := ['uv', 'run', '--script']

[script]
hello:
  print("Hello from Python!")

[script]
goodbye:
  # /// script
  # requires-python = ">=3.11"
  # dependencies=["sh"]
  # ///
  import sh
  print(sh.echo("Goodbye from Python!"), end='')
当然,使用shebang也可以:
just
hello:
  #!/usr/bin/env -S uv run --script
  print("Hello from Python!")

Safer Bash Shebang Recipes

更安全的Bash Shebang Recipe

If you're writing a
bash
shebang recipe, consider adding
set -euxo pipefail
:
just
foo:
  #!/usr/bin/env bash
  set -euxo pipefail
  hello='Yo'
  echo "$hello from Bash!"
It isn't strictly necessary, but
set -euxo pipefail
turns on a few useful features that make
bash
shebang recipes behave more like normal, linewise
just
recipe:
  • set -e
    makes
    bash
    exit if a command fails.
  • set -u
    makes
    bash
    exit if a variable is undefined.
  • set -x
    makes
    bash
    print each script line before it's run.
  • set -o pipefail
    makes
    bash
    exit if a command in a pipeline fails. This is
    bash
    -specific, so isn't turned on in normal linewise
    just
    recipes.
Together, these avoid a lot of shell scripting gotchas.
如果你正在编写
bash
shebang recipe,考虑添加
set -euxo pipefail
just
foo:
  #!/usr/bin/env bash
  set -euxo pipefail
  hello='Yo'
  echo "$hello from Bash!"
这不是严格必需的,但
set -euxo pipefail
开启了一些有用的功能,让
bash
shebang recipe的行为更像普通的逐行
just
recipe:
  • set -e
    bash
    在命令失败时退出。
  • set -u
    bash
    在变量未定义时退出。
  • set -x
    bash
    在运行每个脚本行之前打印它。
  • set -o pipefail
    bash
    在管道中的命令失败时退出。这是
    bash
    特有的,因此在普通的逐行
    just
    recipe中不会开启。
这些设置一起避免了很多Shell脚本的陷阱。

Shebang Recipe Execution on Windows

Windows上的Shebang Recipe执行

On Windows, shebang interpreter paths containing a
/
are translated from Unix-style paths to Windows-style paths using
cygpath
, a utility that ships with Cygwin.
For example, to execute this recipe on Windows:
just
echo:
  #!/bin/sh
  echo "Hello!"
The interpreter path
/bin/sh
will be translated to a Windows-style path using
cygpath
before being executed.
If the interpreter path does not contain a
/
it will be executed without being translated. This is useful if
cygpath
is not available, or you wish to pass a Windows-style path to the interpreter.
在Windows上,包含
/
的shebang解释器路径会使用
cygpath
从Unix风格路径转换为Windows风格路径,
cygpath
是随Cygwin附带的实用工具。
例如,要在Windows上执行这个recipe:
just
echo:
  #!/bin/sh
  echo "Hello!"
解释器路径
/bin/sh
会在执行前使用
cygpath
转换为Windows风格路径。
如果解释器路径不包含
/
,则不会进行转换直接执行。如果没有
cygpath
,或者你想向解释器传递Windows风格路径,这会很有用。

Setting Variables in a Recipe

在Recipe中设置变量

Recipe lines are interpreted by the shell, not
just
, so it's not possible to set
just
variables in the middle of a recipe:
justfile
foo:
  x := "hello" # This doesn't work!
  echo {{x}}
It is possible to use shell variables, but there's another problem. Every recipe line is run by a new shell instance, so variables set in one line won't be set in the next:
just
foo:
  x=hello && echo $x # This works!
  y=bye
  echo $y            # This doesn't, `y` is undefined here!
The best way to work around this is to use a shebang recipe. Shebang recipe bodies are extracted and run as scripts, so a single shell instance will run the whole thing:
just
foo:
  #!/usr/bin/env bash
  set -euxo pipefail
  x=hello
  echo $x
Recipe行由Shell解释,而不是
just
,因此无法在recipe中间设置
just
变量:
justfile
foo:
  x := "hello" # This doesn't work!
  echo {{x}}
可以使用Shell变量,但还有另一个问题。每个recipe行都由新的Shell实例运行,因此在一行中设置的变量在下一行中不存在:
just
foo:
  x=hello && echo $x # This works!
  y=bye
  echo $y            # This doesn't, `y` is undefined here!
解决这个问题的最佳方法是使用shebang recipe。Shebang recipe的体会被提取并作为脚本运行,因此单个Shell实例会运行整个内容:
just
foo:
  #!/usr/bin/env bash
  set -euxo pipefail
  x=hello
  echo $x

Sharing Environment Variables Between Recipes

在Recipe之间共享环境变量

Each line of each recipe is executed by a fresh shell, so it is not possible to share environment variables between recipes.
每个recipe的每一行都由新的Shell执行,因此无法在recipe之间共享环境变量。

Using Python Virtual Environments

使用Python虚拟环境

Some tools, like Python's venv, require loading environment variables in order to work, making them challenging to use with
just
. As a workaround, you can execute the virtual environment binaries directly:
just
venv:
  [ -d foo ] || python3 -m venv foo

run: venv
  ./foo/bin/python3 main.py
一些工具,比如Python的venv,需要加载环境变量才能工作,这使得它们很难与
just
一起使用。作为解决方法,你可以直接执行虚拟环境的二进制文件:
just
venv:
  [ -d foo ] || python3 -m venv foo

run: venv
  ./foo/bin/python3 main.py

Changing the Working Directory in a Recipe

在Recipe中更改工作目录

Each recipe line is executed by a new shell, so if you change the working directory on one line, it won't have an effect on later lines:
just
foo:
  pwd    # This `pwd` will print the same directory…
  cd bar
  pwd    # …as this `pwd`!
There are a couple ways around this. One is to call
cd
on the same line as the command you want to run:
just
foo:
  cd bar && pwd
The other is to use a shebang recipe. Shebang recipe bodies are extracted and run as scripts, so a single shell instance will run the whole thing, and thus a
cd
on one line will affect later lines, just like a shell script:
just
foo:
  #!/usr/bin/env bash
  set -euxo pipefail
  cd bar
  pwd
每个recipe行都由新的Shell执行,因此如果你在一行更改工作目录,对后面的行不会有影响:
just
foo:
  pwd    # This `pwd` will print the same directory…
  cd bar
  pwd    # …as this `pwd`!
有几种解决方法。一种是在要运行的命令同一行调用
cd
just
foo:
  cd bar && pwd
另一种是使用shebang recipe。Shebang recipe的体会被提取并作为脚本运行,因此单个Shell实例会运行整个内容,因此一行的
cd
会影响后面的行,就像Shell脚本一样:
just
foo:
  #!/usr/bin/env bash
  set -euxo pipefail
  cd bar
  pwd

Indentation

缩进

Recipe lines can be indented with spaces or tabs, but not a mix of both. All of a recipe's lines must have the same type of indentation, but different recipes in the same
justfile
may use different indentation.
Each recipe must be indented at least one level from the
recipe-name
but after that may be further indented.
Here's a justfile with a recipe indented with spaces, represented as
·
, and tabs, represented as
.
justfile
set windows-shell := ["pwsh", "-NoLogo", "-NoProfileLoadTime", "-Command"]

set ignore-comments

list-space directory:
··#!pwsh
··foreach ($item in $(Get-ChildItem {{directory}} )) {
····echo $item.Name
··}
··echo ""
Recipe行可以用空格或制表符缩进,但不能混合使用。同一个recipe的所有行必须使用相同类型的缩进,但同一个
justfile
中的不同recipe可以使用不同的缩进。
每个recipe必须比
recipe-name
至少缩进一级,之后可以进一步缩进。
下面是一个justfile示例,其中一个recipe用空格缩进(用
·
表示),另一个用制表符缩进(用
表示)。
justfile
set windows-shell := ["pwsh", "-NoLogo", "-NoProfileLoadTime", "-Command"]

set ignore-comments

list-space directory:
··#!pwsh
··foreach ($item in $(Get-ChildItem {{directory}} )) {
····echo $item.Name
··}
··echo ""

indentation nesting works even when newlines are escaped

indentation nesting works even when newlines are escaped

list-tab directory: → @foreach ($item in $(Get-ChildItem {{directory}} )) {
→ → echo $item.Name
→ } → @echo ""

```pwsh
PS > just list-space ~
Desktop
Documents
Downloads

PS > just list-tab ~
Desktop
Documents
Downloads
list-tab directory: → @foreach ($item in $(Get-ChildItem {{directory}} )) { \ → → echo $item.Name \ → } → @echo ""

```pwsh
PS > just list-space ~
Desktop
Documents
Downloads

PS > just list-tab ~
Desktop
Documents
Downloads

Multi-Line Constructs

多行结构

Recipes without an initial shebang are evaluated and run line-by-line, which means that multi-line constructs probably won't do what you want.
For example, with the following
justfile
:
justfile
conditional:
  if true; then
    echo 'True!'
  fi
The extra leading whitespace before the second line of the
conditional
recipe will produce a parse error:
console
$ just conditional
error: Recipe line has extra leading whitespace
  |
3 |         echo 'True!'
  |     ^^^^^^^^^^^^^^^^
To work around this, you can write conditionals on one line, escape newlines with slashes, or add a shebang to your recipe. Some examples of multi-line constructs are provided for reference.
没有初始shebang的recipe会逐行计算和运行,这意味着多行结构可能不会按你预期的方式工作。
例如,对于以下
justfile
justfile
conditional:
  if true; then
    echo 'True!'
  fi
conditional
recipe第二行前面的额外前导空格会产生解析错误:
console
$ just conditional
error: Recipe line has extra leading whitespace
  |
3 |         echo 'True!'
  |     ^^^^^^^^^^^^^^^^
要解决这个问题,你可以将条件写在一行,用反斜杠转义换行符,或者为你的recipe添加shebang。下面提供了一些多行结构的示例供参考。

if
statements

if
语句

just
conditional:
  if true; then echo 'True!'; fi
just
conditional:
  if true; then \
    echo 'True!'; \
  fi
just
conditional:
  #!/usr/bin/env sh
  if true; then
    echo 'True!'
  fi
just
conditional:
  if true; then echo 'True!'; fi
just
conditional:
  if true; then \\
    echo 'True!'; \\
  fi
just
conditional:
  #!/usr/bin/env sh
  if true; then
    echo 'True!'
  fi

for
loops

for
循环

just
for:
  for file in `ls .`; do echo $file; done
just
for:
  for file in `ls .`; do \
    echo $file; \
  done
just
for:
  #!/usr/bin/env sh
  for file in `ls .`; do
    echo $file
  done
just
for:
  for file in `ls .`; do echo $file; done
just
for:
  for file in `ls .`; do \\
    echo $file; \\
  done
just
for:
  #!/usr/bin/env sh
  for file in `ls .`; do
    echo $file
  done

while
loops

while
循环

just
while:
  while `server-is-dead`; do ping -c 1 server; done
just
while:
  while `server-is-dead`; do \
    ping -c 1 server; \
  done
just
while:
  #!/usr/bin/env sh
  while `server-is-dead`; do
    ping -c 1 server
  done
just
while:
  while `server-is-dead`; do ping -c 1 server; done
just
while:
  while `server-is-dead`; do \\
    ping -c 1 server; \\
  done
just
while:
  #!/usr/bin/env sh
  while `server-is-dead`; do
    ping -c 1 server
  done

Outside Recipe Bodies

Recipe体外部

Parenthesized expressions can span multiple lines:
just
abc := ('a' +
        'b'
         + 'c')

abc2 := (
  'a' +
  'b' +
  'c'
)

foo param=('foo'
      + 'bar'
    ):
  echo {{param}}

bar: (foo
        'Foo'
     )
  echo 'Bar!'
Lines ending with a backslash continue on to the next line as if the lines were joined by whitespace<sup>1.15.0</sup>:
just
a := 'foo' + \
     'bar'

foo param1 \
  param2='foo' \
  *varparam='': dep1 \
                (dep2 'foo')
  echo {{param1}} {{param2}} {{varparam}}

dep1: \
    # this comment is not part of the recipe body
  echo 'dep1'

dep2 \
  param:
    echo 'Dependency with parameter {{param}}'
Backslash line continuations can also be used in interpolations. The line following the backslash must be indented.
just
recipe:
  echo '{{ \
  "This interpolation " + \
    "has a lot of text." \
  }}'
  echo 'back to recipe body'
括号中的表达式可以跨多行:
just
abc := ('a' +
        'b'
         + 'c')

abc2 := (
  'a' +
  'b' +
  'c'
)

foo param=('foo'
      + 'bar'
    ):
  echo {{param}}

bar: (foo
        'Foo'
     )
  echo 'Bar!'
以反斜杠结尾的行会延续到下一行,就像行之间用空格连接一样<sup>1.15.0</sup>
just
a := 'foo' + \\
     'bar'

foo param1 \\
  param2='foo' \\
  *varparam='': dep1 \\
                (dep2 'foo')
  echo {{param1}} {{param2}} {{varparam}}

dep1: \\
    # this comment is not part of the recipe body
  echo 'dep1'

dep2 \\
  param:
    echo 'Dependency with parameter {{param}}'
反斜杠行延续也可以在插值中使用。反斜杠后面的行必须缩进。
just
recipe:
  echo '{{ \\
  "This interpolation " + \\
    "has a lot of text." \\
  }}'
  echo 'back to recipe body'

Command-line Options

命令行选项

just
supports a number of useful command-line options for listing, dumping, and debugging recipes and variables:
console
$ just --list
Available recipes:
  js
  perl
  polyglot
  python
  ruby
$ just --show perl
perl:
  #!/usr/bin/env perl
  print "Larry Wall says Hi!\n";
$ just --show polyglot
polyglot: python js perl sh ruby
just
支持许多有用的命令行选项,用于列出、转储和调试recipe和变量:
console
$ just --list
Available recipes:
  js
  perl
  polyglot
  python
  ruby
$ just --show perl
perl:
  #!/usr/bin/env perl
  print "Larry Wall says Hi!\
";
$ just --show polyglot
polyglot: python js perl sh ruby

Setting Command-line Options with Environment Variables

使用环境变量设置命令行选项

Some command-line options can be set with environment variables
For example, unstable features can be enabled either with the
--unstable
flag:
console
$ just --unstable
Or by setting the
JUST_UNSTABLE
environment variable:
console
$ export JUST_UNSTABLE=1
$ just
Since environment variables are inherited by child processes, command-line options set with environment variables are inherited by recursive invocations of
just
, where as command line options set with arguments are not.
Consult
just --help
for which options can be set with environment variables.
一些命令行选项可以通过环境变量设置。
例如,可以通过
--unstable
flag启用不稳定特性:
console
$ just --unstable
或者设置
JUST_UNSTABLE
环境变量:
console
$ export JUST_UNSTABLE=1
$ just
由于环境变量会被子进程继承,使用环境变量设置的命令行选项会被递归调用的
just
继承,而使用参数设置的命令行选项不会。
请参考
just --help
了解哪些选项可以通过环境变量设置。

Private Recipes

私有Recipe

Recipes and aliases whose name starts with a
_
are omitted from
just --list
:
just
test: _test-helper
  ./bin/test

_test-helper:
  ./bin/super-secret-test-helper-stuff
console
$ just --list
Available recipes:
    test
And from
just --summary
:
console
$ just --summary
test
The
[private]
attribute<sup>1.10.0</sup> may also be used to hide recipes or aliases without needing to change the name:
just
[private]
foo:

[private]
alias b := bar

bar:
console
$ just --list
Available recipes:
    bar
This is useful for helper recipes which are only meant to be used as dependencies of other recipes.
名称以
_
开头的recipe和别名不会出现在
just --list
中:
just
test: _test-helper
  ./bin/test

_test-helper:
  ./bin/super-secret-test-helper-stuff
console
$ just --list
Available recipes:
    test
也不会出现在
just --summary
中:
console
$ just --summary
test
也可以使用
[private]
属性<sup>1.10.0</sup>隐藏recipe或别名,无需更改名称:
just
[private]
foo:

[private]
alias b := bar

bar:
console
$ just --list
Available recipes:
    bar
这对于仅用作其他recipe依赖的辅助recipe非常有用。

Quiet Recipes

静默Recipe

A recipe name may be prefixed with
@
to invert the meaning of
@
before each line:
just
@quiet:
  echo hello
  echo goodbye
  @# all done!
Now only the lines starting with
@
will be echoed:
console
$ just quiet
hello
goodbye
Recipe名称可以以
@
为前缀,反转每行开头
@
的含义:
just
@quiet:
  echo hello
  echo goodbye
  @# all done!
现在只有以
@
开头的行会被回显:
console
$ just quiet
hello
goodbye

all done!

all done!


All recipes in a Justfile can be made quiet with `set quiet`:

```just
set quiet

foo:
  echo "This is quiet"

@foo2:
  echo "This is also quiet"
The
[no-quiet]
attribute overrides this setting:
just
set quiet

foo:
  echo "This is quiet"

[no-quiet]
foo2:
  echo "This is not quiet"
Shebang recipes are quiet by default:
just
foo:
  #!/usr/bin/env bash
  echo 'Foo!'
console
$ just foo
Foo!
Adding
@
to a shebang recipe name makes
just
print the recipe before executing it:
just
@bar:
  #!/usr/bin/env bash
  echo 'Bar!'
console
$ just bar
#!/usr/bin/env bash
echo 'Bar!'
Bar!
just
normally prints error messages when a recipe line fails. These error messages can be suppressed using the
[no-exit-message]
<sup>1.7.0</sup> attribute. You may find this especially useful with a recipe that wraps a tool:
just
git *args:
    @git {{args}}
console
$ just git status
fatal: not a git repository (or any of the parent directories): .git
error: Recipe `git` failed on line 2 with exit code 128
Add the attribute to suppress the exit error message when the tool exits with a non-zero code:
just
[no-exit-message]
git *args:
    @git {{args}}
console
$ just git status
fatal: not a git repository (or any of the parent directories): .git

使用`set quiet`可以让Justfile中的所有recipe变为静默:

```just
set quiet

foo:
  echo "This is quiet"

@foo2:
  echo "This is also quiet"
[no-quiet]
属性会覆盖该设置:
just
set quiet

foo:
  echo "This is quiet"

[no-quiet]
foo2:
  echo "This is not quiet"
Shebang recipe默认是静默的:
just
foo:
  #!/usr/bin/env bash
  echo 'Foo!'
console
$ just foo
Foo!
在shebang recipe名称前添加
@
会让
just
在执行前打印recipe:
just
@bar:
  #!/usr/bin/env bash
  echo 'Bar!'
console
$ just bar
#!/usr/bin/env bash
echo 'Bar!'
Bar!
当recipe行失败时,
just
通常会打印错误消息。可以使用
[no-exit-message]
<sup>1.7.0</sup>属性抑制这些错误消息。对于包装工具的recipe,你可能会发现这个属性特别有用:
just
git *args:
    @git {{args}}
console
$ just git status
fatal: not a git repository (or any of the parent directories): .git
error: Recipe `git` failed on line 2 with exit code 128
添加该属性可以在工具以非零代码退出时抑制退出错误消息:
just
[no-exit-message]
git *args:
    @git {{args}}
console
$ just git status
fatal: not a git repository (or any of the parent directories): .git

Selecting Recipes to Run With an Interactive Chooser

使用交互式选择器选择要运行的Recipe

The
--choose
subcommand makes
just
invoke a chooser to select which recipes to run. Choosers should read lines containing recipe names from standard input and print one or more of those names separated by spaces to standard output.
Because there is currently no way to run a recipe that requires arguments with
--choose
, such recipes will not be given to the chooser. Private recipes and aliases are also skipped.
The chooser can be overridden with the
--chooser
flag. If
--chooser
is not given, then
just
first checks if
$JUST_CHOOSER
is set. If it isn't, then the chooser defaults to
fzf
, a popular fuzzy finder.
Arguments can be included in the chooser, i.e.
fzf --exact
.
The chooser is invoked in the same way as recipe lines. For example, if the chooser is
fzf
, it will be invoked with
sh -cu 'fzf'
, and if the shell, or the shell arguments are overridden, the chooser invocation will respect those overrides.
If you'd like
just
to default to selecting recipes with a chooser, you can use this as your default recipe:
just
default:
  @just --choose
--choose
子命令让
just
调用选择器来选择要运行的recipe。选择器应该从标准输入读取包含recipe名称的行,并将一个或多个名称用空格分隔打印到标准输出。
目前没有办法使用
--choose
运行需要参数的recipe,因此这类recipe不会提供给选择器。私有recipe和别名也会被跳过。
可以使用
--chooser
flag覆盖选择器。如果没有提供
--chooser
just
首先会检查是否设置了
$JUST_CHOOSER
。如果没有设置,选择器默认为
fzf
,一款流行的模糊查找器。
参数可以包含在选择器中,例如
fzf --exact
选择器的调用方式与recipe行相同。例如,如果选择器是
fzf
,它会用
sh -cu 'fzf'
调用,如果覆盖了shell或shell参数,选择器调用会尊重这些覆盖。
如果你希望
just
默认使用选择器选择recipe,可以使用以下默认recipe:
just
default:
  @just --choose

Invoking
justfile
s in Other Directories

调用其他目录中的
justfile

If the first argument passed to
just
contains a
/
, then the following occurs:
  1. The argument is split at the last
    /
    .
  2. The part before the last
    /
    is treated as a directory.
    just
    will start its search for the
    justfile
    there, instead of in the current directory.
  3. The part after the last slash is treated as a normal argument, or ignored if it is empty.
This may seem a little strange, but it's useful if you wish to run a command in a
justfile
that is in a subdirectory.
For example, if you are in a directory which contains a subdirectory named
foo
, which contains a
justfile
with the recipe
build
, which is also the default recipe, the following are all equivalent:
console
$ (cd foo && just build)
$ just foo/build
$ just foo/
Additional recipes after the first are sought in the same
justfile
. For example, the following are both equivalent:
console
$ just foo/a b
$ (cd foo && just a b)
And will both invoke recipes
a
and
b
in
foo/justfile
.
如果传递给
just
的第一个参数包含
/
,则会发生以下情况:
  1. 参数在最后一个
    /
    处拆分。
  2. 最后一个
    /
    之前的部分被视为目录。
    just
    会从那里开始搜索
    justfile
    ,而不是当前目录。
  3. 最后一个斜杠之后的部分被视为普通参数,如果为空则忽略。
这可能看起来有点奇怪,但如果你想运行子目录中
justfile
的命令,这会很有用。
例如,如果你在一个包含名为
foo
的子目录的目录中,
foo
子目录包含一个
justfile
,其中有recipe
build
,也是默认recipe,以下命令都是等价的:
console
$ (cd foo && just build)
$ just foo/build
$ just foo/
第一个recipe之后的其他recipe会在同一个
justfile
中查找。例如,以下两个命令是等价的:
console
$ just foo/a b
$ (cd foo && just a b)
两者都会调用
foo/justfile
中的recipe
a
b

Imports

导入

One
justfile
can include the contents of another using
import
statements.
If you have the following
justfile
:
justfile
import 'foo/bar.just'

a: b
  @echo A
And the following text in
foo/bar.just
:
just
b:
  @echo B
foo/bar.just
will be included in
justfile
and recipe
b
will be defined:
console
$ just b
B
$ just a
B
A
The
import
path can be absolute or relative to the location of the justfile containing it. A leading
~/
in the import path is replaced with the current users home directory.
Justfiles are insensitive to order, so included files can reference variables and recipes defined after the
import
statement.
Imported files can themselves contain
import
s, which are processed recursively.
allow-duplicate-recipes
and
allow-duplicate-variables
allow duplicate recipes and variables, respectively, to override each other, instead of producing an error.
Within a module, later definitions override earlier definitions:
just
set allow-duplicate-recipes

foo:

foo:
  echo 'yes'
When
import
s are involved, things unfortunately get much more complicated and hard to explain.
Shallower definitions always override deeper definitions, so recipes at the top level will override recipes in imports, and recipes in an import will override recipes in an import which itself imports those recipes.
When two duplicate definitions are imported and are at the same depth, the one from the earlier import will override the one from the later import.
This is because
just
uses a stack when processing imports, pushing imports onto the stack in source-order, and always processing the top of the stack next, so earlier imports are actually handled later by the compiler.
This is definitely a bug, but since
just
has very strong backwards compatibility guarantees and we take enormous pains not to break anyone's
justfile
, we have created issue #2540 to discuss whether or not we can actually fix it.
Imports may be made optional by putting a
?
after the
import
keyword:
just
import? 'foo/bar.just'
Importing the same source file multiple times is not an error<sup>1.37.0</sup>. This allows importing multiple justfiles, for example
foo.just
and
bar.just
, which both import a third justfile containing shared recipes, for example
baz.just
, without the duplicate import of
baz.just
being an error:
justfile
undefined
一个
justfile
可以使用
import
语句包含另一个
justfile
的内容。
如果你有以下
justfile
justfile
import 'foo/bar.just'

a: b
  @echo A
foo/bar.just
中有以下内容:
just
b:
  @echo B
foo/bar.just
会被包含到
justfile
中,recipe
b
会被定义:
console
$ just b
B
$ just a
B
A
import
路径可以是绝对路径,也可以相对于包含它的justfile的位置。导入路径中开头的
~/
会被替换为当前用户的主目录。
Justfile对顺序不敏感,因此包含的文件可以引用
import
语句之后定义的变量和recipe。
导入的文件本身可以包含
import
,会递归处理。
allow-duplicate-recipes
allow-duplicate-variables
允许重复的recipe和变量互相覆盖,而不会产生错误。
在一个模块中,后面的定义会覆盖前面的定义:
just
set allow-duplicate-recipes

foo:

foo:
  echo 'yes'
当涉及到
import
时,情况会变得非常复杂且难以解释。
较浅的定义总是覆盖较深的定义,因此顶层的recipe会覆盖导入中的recipe,导入中的recipe会覆盖它所导入的其他导入中的recipe。
当导入两个重复的定义且深度相同时,来自较早导入的定义会覆盖来自较晚导入的定义。
这是因为
just
在处理导入时使用栈,按源代码顺序将导入压入栈,始终处理栈顶的导入,因此较早的导入实际上由编译器处理得更晚。
这绝对是一个bug,但由于
just
有非常强的向后兼容性保证,我们竭尽全力不破坏任何人的
justfile
,我们创建了issue #2540来讨论是否可以实际修复它。
可以在
import
关键字后面加
?
让导入变为可选:
just
import? 'foo/bar.just'
多次导入同一个源文件不会报错<sup>1.37.0</sup>。这允许导入多个justfile,例如
foo.just
bar.just
,它们都导入包含共享recipe的第三个justfile,例如
baz.just
,而不会因为重复导入
baz.just
而报错:
justfile
undefined

justfile

justfile

import 'foo.just' import 'bar.just'

```justfile
import 'foo.just' import 'bar.just'

```justfile

foo.just

foo.just

import 'baz.just' foo: baz

```justfile
import 'baz.just' foo: baz

```justfile

bar.just

bar.just

import 'baz.just' bar: baz

```just
import 'baz.just' bar: baz

```just

baz

baz

baz:
undefined
baz:
undefined

Modules<sup>1.19.0</sup>

模块<sup>1.19.0</sup>

A
justfile
can declare modules using
mod
statements.
mod
statements were stabilized in
just
<sup>1.31.0</sup>. In earlier versions, you'll need to use the
--unstable
flag,
set unstable
, or set the
JUST_UNSTABLE
environment variable to use them.
If you have the following
justfile
:
justfile
mod bar

a:
  @echo A
And the following text in
bar.just
:
just
b:
  @echo B
bar.just
will be included in
justfile
as a submodule. Recipes, aliases, and variables defined in one submodule cannot be used in another, and each module uses its own settings.
Recipes in submodules can be invoked as subcommands:
console
$ just bar b
B
Or with path syntax:
console
$ just bar::b
B
If a module is named
foo
, just will search for the module file in
foo.just
,
foo/mod.just
,
foo/justfile
, and
foo/.justfile
. In the latter two cases, the module file may have any capitalization.
Module statements may be of the form:
justfile
mod foo 'PATH'
Which loads the module's source file from
PATH
, instead of from the usual locations. A leading
~/
in
PATH
is replaced with the current user's home directory.
PATH
may point to the module source file itself, or to a directory containing the module source file with the name
mod.just
,
justfile
, or
.justfile
. In the latter two cases, the module file may have any capitalization.
Environment files are only loaded for the root justfile, and loaded environment variables are available in submodules. Settings in submodules that affect environment file loading are ignored.
Recipes in submodules without the
[no-cd]
attribute run with the working directory set to the directory containing the submodule source file.
justfile()
and
justfile_directory()
always return the path to the root justfile and the directory that contains it, even when called from submodule recipes.
Modules may be made optional by putting a
?
after the
mod
keyword:
just
mod? foo
Missing source files for optional modules do not produce an error.
Optional modules with no source file do not conflict, so you can have multiple mod statements with the same name, but with different source file paths, as long as at most one source file exists:
just
mod? foo 'bar.just'
mod? foo 'baz.just'
Modules may be given doc comments which appear in
--list
output<sup>1.30.0</sup>:
justfile
undefined
justfile
可以使用
mod
语句声明模块。
mod
语句在
just
<sup>1.31.0</sup>中稳定。在早期版本中,你需要使用
--unstable
flag、
set unstable
或设置
JUST_UNSTABLE
环境变量来使用它们。
如果你有以下
justfile
justfile
mod bar

a:
  @echo A
bar.just
中有以下内容:
just
b:
  @echo B
bar.just
会作为子模块包含到
justfile
中。在一个子模块中定义的recipe、别名和变量不能在另一个子模块中使用,每个模块使用自己的设置。
子模块中的recipe可以作为子命令调用:
console
$ just bar b
B
或者使用路径语法:
console
$ just bar::b
B
如果模块名为
foo
,just会在
foo.just
foo/mod.just
foo/justfile
foo/.justfile
中查找模块文件。后两种情况中,模块文件可以是任意大小写。
模块语句可以是以下形式:
justfile
mod foo 'PATH'
这会从
PATH
加载模块的源文件,而不是从通常位置加载。
PATH
中开头的
~/
会被替换为当前用户的主目录。
PATH
可以指向模块源文件本身,或者指向包含名为
mod.just
justfile
.justfile
的模块源文件的目录。后两种情况中,模块文件可以是任意大小写。
环境文件仅为根justfile加载,加载的环境变量在子模块中可用。子模块中影响环境文件加载的设置会被忽略。
没有
[no-cd]
属性的子模块中的recipe运行时的工作目录设置为包含子模块源文件的目录。
justfile()
justfile_directory()
始终返回根justfile的路径和包含它的目录,即使在子模块recipe中调用也是如此。
可以在
mod
关键字后面加
?
让模块变为可选:
just
mod? foo
可选模块缺少源文件不会产生错误。
没有源文件的可选模块不会冲突,因此你可以有多个同名的mod语句,但具有不同的源文件路径,只要最多存在一个源文件即可:
just
mod? foo 'bar.just'
mod? foo 'baz.just'
模块可以添加文档注释,会出现在
--list
输出中<sup>1.30.0</sup>
justfile
undefined

foo is a great module!

foo is a great module!

mod foo

```console
$ just --list
Available recipes:
    foo ... # foo is a great module!
Modules are still missing a lot of features, for example, the ability to refer to variables in other modules. See the module improvement tracking issue for more information.
mod foo

```console
$ just --list
Available recipes:
    foo ... # foo is a great module!
模块仍然缺少很多功能,例如引用其他模块中变量的能力。更多信息请参考模块改进跟踪issue

Hiding
justfile
s

隐藏
justfile

just
looks for
justfile
s named
justfile
and
.justfile
, which can be used to keep a
justfile
hidden.
just
会查找名为
justfile
.justfile
justfile
,可以用于隐藏
justfile

Just Scripts

Just脚本

By adding a shebang line to the top of a
justfile
and making it executable,
just
can be used as an interpreter for scripts:
console
$ cat > script <<EOF
#!/usr/bin/env just --justfile

foo:
  echo foo
EOF
$ chmod +x script
$ ./script foo
echo foo
foo
When a script with a shebang is executed, the system supplies the path to the script as an argument to the command in the shebang. So, with a shebang of
#!/usr/bin/env just --justfile
, the command will be
/usr/bin/env just --justfile PATH_TO_SCRIPT
.
With the above shebang,
just
will change its working directory to the location of the script. If you'd rather leave the working directory unchanged, use
#!/usr/bin/env just --working-directory . --justfile
.
Note: Shebang line splitting is not consistent across operating systems. The previous examples have only been tested on macOS. On Linux, you may need to pass the
-S
flag to
env
:
just
#!/usr/bin/env -S just --justfile

default:
  echo foo
通过在
justfile
顶部添加shebang行并使其可执行,
just
可以用作脚本的解释器:
console
$ cat > script <<EOF
#!/usr/bin/env just --justfile

foo:
  echo foo
EOF
$ chmod +x script
$ ./script foo
echo foo
foo
当执行带有shebang的脚本时,系统会将脚本的路径作为参数提供给shebang中的命令。因此,使用
#!/usr/bin/env just --justfile
作为shebang时,命令会是
/usr/bin/env just --justfile PATH_TO_SCRIPT
使用上述shebang时,
just
会将其工作目录切换到脚本所在的位置。如果你希望保持工作目录不变,请使用
#!/usr/bin/env just --working-directory . --justfile
注意:Shebang行的拆分在不同操作系统上不一致。前面的示例仅在macOS上测试过。在Linux上,你可能需要向
env
传递
-S
flag:
just
#!/usr/bin/env -S just --justfile

default:
  echo foo

Formatting and dumping
justfile
s

格式化和转储
justfile

Each
justfile
has a canonical formatting with respect to whitespace and newlines.
You can overwrite the current justfile with a canonically-formatted version using the currently-unstable
--fmt
flag:
console
$ cat justfile
每个
justfile
在空格和换行方面都有规范的格式化方式。
你可以使用目前不稳定的
--fmt
flag将当前justfile覆盖为规范格式化的版本:
console
$ cat justfile

A lot of blank lines

A lot of blank lines

some-recipe: echo "foo" $ just --fmt --unstable $ cat justfile
some-recipe: echo "foo" $ just --fmt --unstable $ cat justfile

A lot of blank lines

A lot of blank lines

some-recipe: echo "foo"

Invoking `just --fmt --check --unstable` runs `--fmt` in check mode. Instead of
overwriting the `justfile`, `just` will exit with an exit code of 0 if it is
formatted correctly, and will exit with 1 and print a diff if it is not.

You can use the `--dump` command to output a formatted version of the
`justfile` to stdout:

```console
$ just --dump > formatted-justfile
The
--dump
command can be used with
--dump-format json
to print a JSON representation of a
justfile
.
some-recipe: echo "foo"

调用`just --fmt --check --unstable`以检查模式运行`--fmt`。如果格式正确,`just`会以退出码0退出,如果格式不正确,会以1退出并打印差异。

你可以使用`--dump`命令将格式化版本的`justfile`输出到标准输出:

```console
$ just --dump > formatted-justfile
可以将
--dump
命令与
--dump-format json
一起使用,打印
justfile
的JSON表示。

Fallback to parent
justfile
s

回退到父
justfile

If a recipe is not found in a
justfile
and the
fallback
setting is set,
just
will look for
justfile
s in the parent directory and up, until it reaches the root directory.
just
will stop after it reaches a
justfile
in which the
fallback
setting is
false
or unset.
As an example, suppose the current directory contains this
justfile
:
just
set fallback
foo:
  echo foo
And the parent directory contains this
justfile
:
just
bar:
  echo bar
console
$ just bar
Trying ../justfile
echo bar
bar
如果在
justfile
中未找到recipe且设置了
fallback
设置,
just
会在父目录及以上目录查找
justfile
,直到到达根目录。
just
会在到达
fallback
设置为
false
或未设置的
justfile
后停止。
例如,假设当前目录包含这个
justfile
just
set fallback
foo:
  echo foo
父目录包含这个
justfile
just
bar:
  echo bar
console
$ just bar
Trying ../justfile
echo bar
bar

Avoiding Argument Splitting

避免参数拆分

Given this
justfile
:
just
foo argument:
  touch {{argument}}
The following command will create two files,
some
and
argument.txt
:
console
$ just foo "some argument.txt"
The user's shell will parse
"some argument.txt"
as a single argument, but when
just
replaces
touch {{argument}}
with
touch some argument.txt
, the quotes are not preserved, and
touch
will receive two arguments.
There are a few ways to avoid this: quoting, positional arguments, and exported arguments.
给定这个
justfile
just
foo argument:
  touch {{argument}}
以下命令会创建两个文件
some
argument.txt
console
$ just foo "some argument.txt"
用户的Shell会将
"some argument.txt"
解析为单个参数,但当
just
touch {{argument}}
替换为
touch some argument.txt
时,引号不会保留,
touch
会收到两个参数。
有几种方法可以避免这种情况:引号、位置参数和导出参数。

Quoting

引号

Quotes can be added around the
{{argument}}
interpolation:
just
foo argument:
  touch '{{argument}}'
This preserves
just
's ability to catch variable name typos before running, for example if you were to write
{{argument}}
, but will not do what you want if the value of
argument
contains single quotes.
可以在
{{argument}}
插值周围添加引号:
just
foo argument:
  touch '{{argument}}'
这保留了
just
在运行前捕获变量名拼写错误的能力,例如你写错
{{argument}}
的情况,但如果
argument
的值包含单引号,就不会按预期工作。

Positional Arguments

位置参数

The
positional-arguments
setting causes all arguments to be passed as positional arguments, allowing them to be accessed with
$1
,
$2
, …, and
$@
, which can be then double-quoted to avoid further splitting by the shell:
just
set positional-arguments

foo argument:
  touch "$1"
This defeats
just
's ability to catch typos, for example if you type
$2
instead of
$1
, but works for all possible values of
argument
, including those with double quotes.
positional-arguments
设置会将所有参数作为位置参数传递,允许使用
$1
$2
…和
$@
访问它们,然后可以用双引号括起来以避免Shell进一步拆分:
just
set positional-arguments

foo argument:
  touch "$1"
这会削弱
just
捕获拼写错误的能力,例如你输入
$2
而不是
$1
的情况,但适用于所有可能的
argument
值,包括包含双引号的值。

Exported Arguments

导出参数

All arguments are exported when the
export
setting is set:
just
set export

foo argument:
  touch "$argument"
Or individual arguments may be exported by prefixing them with
$
:
just
foo $argument:
  touch "$argument"
This defeats
just
's ability to catch typos, for example if you type
$argument
, but works for all possible values of
argument
, including those with double quotes.
当设置了
export
设置时,所有参数都会被导出:
just
set export

foo argument:
  touch "$argument"
或者可以通过在参数前加
$
单独导出参数:
just
foo $argument:
  touch "$argument"
这会削弱
just
捕获拼写错误的能力,例如你写错
$argument
的情况,但适用于所有可能的
argument
值,包括包含双引号的值。

Configuring the Shell

配置Shell

There are a number of ways to configure the shell for linewise recipes, which are the default when a recipe does not start with a
#!
shebang. Their precedence, from highest to lowest, is:
  1. The
    --shell
    and
    --shell-arg
    command line options. Passing either of these will cause
    just
    to ignore any settings in the current justfile.
  2. set windows-shell := [...]
  3. set windows-powershell
    (deprecated)
  4. set shell := [...]
Since
set windows-shell
has higher precedence than
set shell
, you can use
set windows-shell
to pick a shell on Windows, and
set shell
to pick a shell for all other platforms.
有多种方法可以为逐行recipe配置Shell,逐行recipe是recipe不以
#!
shebang开头时的默认类型。它们的优先级从高到低为:
  1. --shell
    --shell-arg
    命令行选项。传递其中任意一个都会导致
    just
    忽略当前justfile中的任何设置。
  2. set windows-shell := [...]
  3. set windows-powershell
    (已废弃)
  4. set shell := [...]
由于
set windows-shell
的优先级高于
set shell
,你可以使用
set windows-shell
为Windows选择Shell,使用
set shell
为所有其他平台选择Shell。

Timestamps

时间戳

just
can print timestamps before each recipe commands:
just
recipe:
  echo one
  sleep 2
  echo two
$ just --timestamp recipe
[07:28:46] echo one
one
[07:28:46] sleep 2
[07:28:48] echo two
two
By default, timestamps are formatted as
HH:MM:SS
. The format can be changed with
--timestamp-format
:
$ just --timestamp recipe --timestamp-format '%H:%M:%S%.3f %Z'
[07:32:11:.349 UTC] echo one
one
[07:32:11:.350 UTC] sleep 2
[07:32:13:.352 UTC] echo two
two
The argument to
--timestamp-format
is a
strftime
-style format string, see the
chrono
library docs
for details.
just
可以在每个recipe命令前打印时间戳:
just
recipe:
  echo one
  sleep 2
  echo two
$ just --timestamp recipe
[07:28:46] echo one
one
[07:28:46] sleep 2
[07:28:48] echo two
two
默认情况下,时间戳的格式为
HH:MM:SS
。可以使用
--timestamp-format
更改格式:
$ just --timestamp recipe --timestamp-format '%H:%M:%S%.3f %Z'
[07:32:11:.349 UTC] echo one
one
[07:32:11:.350 UTC] sleep 2
[07:32:13:.352 UTC] echo two
two
--timestamp-format
的参数是
strftime
风格的格式字符串,详情请参考
chrono
库文档

Signal Handling

信号处理

Signals are messsages sent to running programs to trigger specific behavior. For example,
SIGINT
is sent to all processes in the terminal forground process group when
CTRL-C
is pressed.
just
tries to exit when requested by a signal, but it also tries to avoid leaving behind running child proccesses, two goals which are somewhat in conflict.
If
just
exits leaving behind child processes, the user will have no recourse but to
ps aux | grep
for the children and manually
kill
them, a tedious endevour.
信号是发送给运行中程序以触发特定行为的消息。例如,按下
CTRL-C
时,
SIGINT
会发送到终端前台进程组中的所有进程。
just
会在收到信号请求时尝试退出,但也会尽量避免留下运行中的子进程,这两个目标有些冲突。
如果
just
退出时留下了子进程,用户别无选择,只能用
ps aux | grep
查找子进程并手动
kill
它们,这是一项繁琐的工作。

Fatal Signals

致命信号

SIGHUP
,
SIGINT
, and
SIGQUIT
are generated when the user closes the terminal, types
ctrl-c
, or types
ctrl-\
, respectively, and are sent to all processes in the foreground process group.
SIGTERM
is the default signal sent by the
kill
command, and is delivered only to its intended victim.
When a child process is not running,
just
will exit immediately on receipt of any of the above signals.
When a child process is running,
just
will wait until it terminates, to avoid leaving it behind.
Additionally, on receipt of
SIGTERM
,
just
will forward
SIGTERM
to any running children<sup>1.41.0</sup>, since unlike other fatal signals,
SIGTERM
, was likely sent to
just
alone.
Regardless of whether a child process terminates successfully after
just
receives a fatal signal,
just
halts execution.
当用户关闭终端、输入
ctrl-c
或输入
ctrl-\\
时,分别会生成
SIGHUP
SIGINT
SIGQUIT
,它们会发送到前台进程组中的所有进程。
SIGTERM
kill
命令发送的默认信号,仅传递给其目标进程。
当没有子进程运行时,
just
收到上述任何信号都会立即退出。
当有子进程正在运行时,
just
会等待它终止,以避免留下它。
此外,收到
SIGTERM
时,
just
会将
SIGTERM
转发给所有运行中的子进程<sup>1.41.0</sup>,因为与其他致命信号不同,
SIGTERM
可能只发送给
just
本身。
无论子进程在
just
收到致命信号后是否成功终止,
just
都会中止执行。

SIGINFO

SIGINFO

SIGINFO
is sent to all processes in the foreground process group when the user types
ctrl-t
on BSD-derived operating systems, including MacOS, but not Linux.
just
responds by printing a list of all child process IDs and commands<sup>1.41.0</sup>.
BSD派生的操作系统(包括MacOS,但不包括Linux)上,用户输入
ctrl-t
时,
SIGINFO
会发送到前台进程组中的所有进程。
just
的响应是打印所有子进程ID和命令的列表<sup>1.41.0</sup>

Windows

Windows

On Windows,
just
behaves as if it had received
SIGINT
when the user types
ctrl-c
. Other signals are unsupported.
在Windows上,当用户输入
ctrl-c
时,
just
的行为就像收到了
SIGINT
。其他信号不受支持。
",