chinanf-boy / just-zh

中文翻译:<casey/just> 是保存和运行项目的特定命令的简便方法. :heart: 校对 ✅

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

casey/just explain translate-svg

just是保存和运行项目的特定命令的简便方法. 」

中文 | english


更新 ✅

翻译的原文 与日期 最新更新 更多
commit ⏰ 2019-10-07 last 中文翻译

贡献

欢迎 👏 勘误/校对/更新贡献 😊 具体贡献请看

生活

If help, buy me coffee —— 营养跟不上了,给我来瓶营养快线吧! 💰


目录


just

crates.io version build status chat on gitter say thanks

just是保存和运行项目的特定命令的简便方法。

命令存储在一个名为justfile,语法启发自make:

build:
    cc *.c -o main

# test everything
test-all: build
    ./test --all

# run a specific test
test TEST: build
    ./test --test {{TEST}}

然后可以使用just <COMMAND>运行它们:

$ just test-all
cc *.c -o main
./test --all
Yay, all your tests passed!

有些困惑,没事,下面就帮你理清一切

just产生详细的错误消息,并避免make不良癖好,因此调试一个 justfile 比调试一个 markfile 文件更容易,也更少惊吓。

如果你需要帮助just,请随时打开一个问题或让我知道gitter。 始终欢迎功能请求和错误报告!

使用手册

安装

just应该能在,具有合理sh的任何系统上运行,包括 Linux、MACOS 和 BSD。

在 Windows 上,just能与由Git for WindowsGitHub DesktopCygwin提供的sh一起工作。

预先构建的 二进制文件

Linux、MacOS 和 Windows 的预构建二进制文件,在releases 页面

您可以使用以下命令,下载 Mac OS 或 Windows 的最新二进制文件,只需将DESTINATION_DIRECTORY替换成你想放置just的目录:

curl -LSfs https://japaric.github.io/trust/install.sh | \
  sh -s -- --git casey/just --to DESTINATION_DIRECTORY

在 Linux 上,使用:

curl -LSfs https://japaric.github.io/trust/install.sh | \
  sh -s -- --git casey/just --target x86_64-unknown-linux-musl --to DESTINATION_DIRECTORY

Homebrew

关于 MacOS,just可以使用Homebrew 包管理器安装。 若还没有 Homebrew 可使用这里的命令安装,然后运行:

brew install just

Scoop

在 Windows 上,just可以使用Scoop 包管理器安装。 若还没有 Scoop 可使用这里的指令安装,然后运行:

scoop install just

Arch Linux

在 Arch Linux, just 作为 AUR包 just, Arch User Repository。几个可以从 AUR 下载包的工具, 包括 yayyaourt.

Void Linux

在 Void Linux, just can be installed with:

sudo xbps-install -S just

Nix

On NixOS, Linux, and MacOS, just 的安装,可使用Nix package manager. Install Nix or NixOS, then run:

nix-env -i just

Cargo

在 Windows、Linux 和 MACOS 上,just可使用 Cargo 安装, 它是rust 语言 包管理器. 可使用这里的说明书安装 Cargo,然后运行:

cargo install just

(您可能还需要添加~/.cargo/bin到你的$PATH。 如果安装后不能运行,请在 shell 配置文件中运行export PATH="$HOME/.cargo/bin:$PATH")

让我们快速开始

安装章节中安装了just后。试运行just --version确保安装正确.

一旦just成功安装和工作, 在项目的根目录中,创建一个名为justfile的文件,具有以下内容:

recipe-name:
    echo 'This is a recipe!'


# 这是一个注释
another-recipe:
    @echo 'This is another recipe.'

当你调用just,它会在当前目录和向上层目录,寻找一个justfile,因此您可以在项目的任何子目录调用它(它就是那么方便)。

若在没有参数的情况下运行just,那当你选择运行justfile的第一个配方(recipe/或者叫‘食谱’也行,反正听上去都好吃):

$ just
echo 'This is a recipe!'
This is a recipe!

一个或多个参数,就会指定要运行的配方(们):

$ just another-recipe
This is another recipe.

just会在运行真正命令之前,将每个命令打印到标准错误(stderr),这就是为什么echo 'This is a recipe!'会被打印。当然你可以使用@作为行开头,这样会抑制打印。echo 'Another recipe.'也就没有打印。

如果命令失败,配方将停止运行。下面的cargo publish只在cargo test成功后运行:

publish:
    cargo test
    # tests passed, time to publish!
    cargo publish

配方可以依赖其他配方。这里test配方依赖build配方,所以build会在test之前运行:

build:
    cc main.c foo.c bar.c -o main

test: build
    ./test

sloc:
    @echo "`wc -l *.c` lines of code"
$ just test
cc main.c foo.c bar.c -o main
./test
testing... all tests passed!

若是没有依赖关系的配方,将按照命令行上的顺序运行:

$ just build sloc
cc main.c foo.c bar.c -o main
1337 lines of code

依赖关系,总是先运行,即使它们(build)在依赖于它们的配方(test)之后传递:

$ just test build
cc main.c foo.c bar.c -o main
./test
testing... all tests passed!

特性

列出可用的配方

just --list可以列出配方:

$ just --list
Available recipes:
  build
  test
  deploy
  lint

just --summary则更简洁:

$ just --summary
build test deploy lint

Aliases

Aliases 让配方拥有替代名称:

alias b := build

build:
  echo 'Building!'
$ just b
build
echo 'Building!'
Building!

文档注释

just --list会让配方之前的相近注释,出现:

# build stuff
build:
  ./bin/build


# test stuff
test:
  ./bin/test
$ just --list
Available recipes:
    build # build stuff
    test # test stuff

变量和替代

变量、字符串、concatenation 和 substitution ,都通过使用{{…​}}支持:

version := "0.2.7"
tardir  := "awesomesauce-" + version
tarball := tardir + ".tar.gz"

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

转义 {{

写一份包含{{的配方,要使用{{ "{{" }}:

braces:
	echo 'I {{ "{{" }}LOVE}} curly braces!'

(上面 LOVE 旁边的,未闭合的}}会忽略,因此不需要转义).

另一个选择是把所有你想转义的文本,插入到插槽({{中}})中:

braces:
	echo '{{'I {{LOVE}} curly braces!'}}'

Strings

双引号字符串支持转义序列:

string-with-tab             := "\t"
string-with-newline         := "\n"
string-with-carriage-return := "\r"
string-with-double-quote    := "\""
string-with-slash           := "\\"
$ just --evaluate
"tring-with-carriage-return := "
string-with-double-quote    := """
string-with-newline         := "
"
string-with-slash           := "\"
string-with-tab             := "     "

单引号字符串不识别转义序列,可能包含空格行:

escapes := '\t\n\r\"\\'

line-breaks := 'hello
this
is
  a
     raw
string!
'
$ just --evaluate
escapes := "\t\n\r\"\\"

line-breaks := "hello
this
is
  a
     raw
string!
"

函数

只提供一些内置函数,在编写配方时可能有用.

系统信息

  • arch() - 系统指令体系结构,可能的值是:"aarch64","arm","asmjs","hexagon","mips","msp430","powerpc","powerpc64","s390x","sparc","wasm32","x86","x86_64""xcore".

  • os() - 操作系统,可能的值是:"android","bitrig","dragonfly","emscripten","freebsd","haiku","ios","linux","macos","netbsd","openbsd","solaris""windows".

  • os_family()操作系统家族; 可能的价值是:"unix""windows".

例如:

system-info:
	@echo "This is an {{arch()}} machine".
$ just system-info
This is an x86_64 machine

环境变量

  • env_var(key) - 用名称key检索环境变量,如果不存在会中止.

  • env_var_or_default(key, default) - 用名称key检索环境变量,如果它不存在则返回default值.

调用 目录

  • invocation_directory() - 检索当前工作目录的路径, 在just执行命令更改它(用 chdir)之前。

例如,调用rustfmt只作用于"当前目录"下的文件(从用户/调用方的角度),使用以下规则:

rustfmt:
    find {{invocation_directory()}} -name \*.rs -exec rustfmt {} \;

或者,如果您的命令需要从当前目录运行,您可以使用(例如):

build:
    cd {{invocation_directory()}}; ./some_script_that_needs_to_be_run_from_here

Dotenv 集成

just将从名为.env文件中,加载环境变量。 此文件可以与您的 justfile 位于同一个目录中, 或是父目录。这些变量都是环境变量, 因不是just变量,所以在配方和反引号中必须要使用$VARIABLE_NAME获取。

例如,如果你.env文件包含:

# 注释,会被忽略
DATABASE_ADDRESS=localhost:6379
SERVER_PORT=1337

你的 justfile 包含:

serve:
  @echo "Starting server with database $DATABASE_ADDRESS on port $SERVER_PORT..."
  ./server --database $DATABASE_ADDRESS --port $SERVER_PORT

just serve会输出:

$ just serve
Starting server with database localhost:6379 on port 1337...
./server --database $DATABASE_ADDRESS --port $SERVER_PORT

执行命令可使用反引号

反引号可用来存储命令的结果:

localhost := `dumpinterfaces | cut -d: -f2 | sed 's/\/.*//' | sed 's/ //g'`

serve:
    ./serve {{localhost}} 8080

使用命令行工具,设置变量

变量可以通过命令行重写.

os := "linux"

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

build:
    ./build {{os}}
$ just
./build linux
./test --test linux

在配方之前的任意数量参数,可用过NAME=VALUE设置:

$ just os=plan9
./build plan9
./test --test plan9

或者你可以使用 --set:

$ just --set os bsd
./build bsd
./test --test bsd

环境变量

export关键字会将作为环境变量,导入到配方中:

export RUST_BACKTRACE := "1"

test:
    # will print a stack trace if it crashes
    cargo test

配方 参数

配方可能有参数。这里的build配方有一个参数叫做target:

build target:
    @echo 'Building {{target}}...'
    cd {{target}} && make

其他配方可能不依赖带有参数的配方.

为了传递参数,把它们放在配方名称后面:

$ just build my-awesome-project
Building my-awesome-project...
cd my-awesome-project && make

参数也可具有默认值:

default := 'all'

test target tests=default:
    @echo 'Testing {{target}}:{{tests}}...'
    ./test --tests {{tests}} {{target}}

可以省略,具有默认值的参数:

$ just test server
Testing server:all...
./test --tests all server

或提供:

$ just test server unit
Testing server:unit...
./test --tests unit server

默认值可以是任意表达式,但 concatenations 必须被圆括号包裹:

arch := "wasm"

test triple=(arch + "-unknown-unknown"):
  ./test {{triple}}

配方的最后一个参数可以是变量。这在参数名称之前,用+表示:

backup +FILES:
  scp {{FILES}} me@server.com:

变量参数接受一个或多个参数,并由包含空格分隔的参数字符串,扩展:

$ 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

具有默认参数的变量参数,可接受零个或多个参数:

commit MESSAGE +FLAGS='':
  git commit {{FLAGS}} -m "{{MESSAGE}}"

{{…​}}替换可能需要引号,如果它们包含空格。例如,如果你有以下配方:

search QUERY:
    lynx https://www.google.com/?q={{QUERY}}

你的类型是:

$ just search "cat toupee"

Just会运行命令lynx [https://www.google.com/?q=cat](https://www.google.com/?q=cat) toupee,将被sh解析为lynx,[https://www.google.com/?q=cat](https://www.google.com/?q=cat)toupee,而不是你想的lynx[https://www.google.com/?q=cat](https://www.google.com/?q=cat) toupee

你可以通过添加引号来修正这个问题:

search QUERY:
    lynx 'https://www.google.com/?q={{QUERY}}'

用其他语言来写配方

以一个#!开始的配方会作为脚本执行,所以你可以用其他语言编写:

polyglot: python js perl sh ruby

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

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

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

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

ruby:
    #!/usr/bin/env ruby
    puts "Hello from ruby!"
$ just polyglot
Hello from python!
Greetings from justfile!
Larry Wall says Hi!
Yo from a shell script!
Hello from ruby!

多行结构语句

配方没有执行一个初始 shebang,并且是一行一行运行的。这意味着,多行结构语句的运行,可能不是你想的那样。

例如, 下面的 justfile:

    conditional:
        if true; then
            echo 'True!'
        fi

conditional语句下的缩进空格, 会给出解析错误:

    $ just conditional
    error: Recipe line has extra leading whitespace
      |
    3 |         echo 'True!'
      |     ^^^^^^^^^^^^^^^^

要使这个工作,你要把条件语句放在同一行,用\转为新行,或是添加一个 shebang 到你的配方中。下面有些参考。

if statements

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

for loops

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

while loops

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

命令行选项

just支持许多有用的命令行选项,用于列表,倒腾和调试配方和变量:

$ 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 --help查看所有选项.

私有配方

名称以一个_开头的配方和 aliases,just --list会省略:

test: _test-helper
  ./bin/test

_test-helper:
  ./bin/super-secret-test-helper-stuff
$ just --list
Available recipes:
  test

just --summary也是:

$ just --summary
test

这对于配方帮手来说是有用的,因为它们只是用来作为其他配方的依赖.

安静配方

配方名称可以用"@"前缀,在每行之前反转"@"的含义:

@quiet:
  echo hello
  echo goodbye
  @# all done!

现在,只有用"@"开头的台词会回响:

$ j quiet
hello
goodbye
# all done!

在其他目录调用 Justfiles

如果第一个参数传递给just包含一个/,那会发生以下情况:

  1. 参数以最后一个/,拆分.

  2. 拆分后的,前半部分被视为目录。just会开始在那里搜索 justfile,而不是在当前目录中搜索。

  3. 后部分被当作一个普通的参数,或者,若它是空的,则被忽略。

这看起来有点奇怪,但是如果您希望运行子目录中的 justfile 中的命令,这是很有用的。

例如,如果您在包含名为foo子目录,其中包含一个带有build(也是默认配方)配方的 justfile,以下每条命令都是相等的:

$ (cd foo && just build)
$ just foo/build
$ just foo/

Just 脚本

通过添加一个 shebang 到一个 justfile 文件的顶部,就能让它可执行化。just 就作为了脚本执行器:

$ cat > script <<EOF
#!/usr/bin/env just --justfile

foo:
  echo foo
EOF
$ chmod +x script
$ ./script foo
echo foo
foo

若一个执行脚本带有一个 shebang, 系统会提供一个脚本的路径,作为命令参数。 所以,#!/usr/bin/env just --justfile, 这个命令完整是 /usr/bin/env just --justfile PATH_TO_SCRIPT

使用上面的 shebang, just 会将工作目录改为脚本所在的目录。 如果不想改变工作目录, 使用 #!/usr/bin/env just --working-directory . --justfile

杂记(炸鸡?)

好'译'名

搭配工具

just很好搭配的工具,包括:

  • watchexec-一个简单的工具,它监视路径,并在检测到修改时,运行命令.

Shell Alias(别名)

为了闪电般的命令运行,把alias j=just放在 shell 的配置文件中.

语法 高亮

justfile语法足够接近make,您可能希望告诉编辑器使用 make 语法高亮显示。

Vim

对于 Vim,您可以将以下内容放入~/.vim/filetype.vim:

if exists("did_load_filetypes")
  finish
endif

augroup filetypedetect
  au BufNewFile,BufRead Justfile,justfile setf make
augroup END

Vim 和 Emacs

在一个justfile中包括以下内容,能在 Vim 和 Emacs 中启用语法高亮显示:

# Local Variables:
# mode: makefile
# End:
# vim: set ft=make :

Visual Studio Code

VS 代码的skellock扩展是可用的哦. (github 库)

您可以通过运行命令安装它:

code --install-extension skellock.just

Kakoune

Kakoune 支持justfile语法高亮出笼啦,感谢 TeddyDD.

其他编辑器

请随时给我发送必要的命令,使语法高亮工作在您的编辑器的选择,以便我可以在这里包括他们.

语法

justfile 的非规范语法可以在GRAMMAR.md.

just.sh

以前的just是一个花哨的 Rust 程序,它是一个小小的 shell 脚本,其调用make. 您可以在extras/just.sh中找到旧版本。

无定向项目的 Justfile

如果你想要一些命令在任何地方都可用,把它们放进去.~/.justfile,并将下列内容添加到 shell 初始化文件中:

alias .j='just --justfile ~/.justfile --working-directory ~'

或者,如果你宁愿他们运行在当前目录:

alias .j='just --justfile ~/.justfile --working-directory .'

我敢肯定没有人真正使用这个功能,但它在那里.

¯\_(ツ)_/¯

Janus

Janus 是收集和分析 justfiles 的工具,并确定新版 just 更新与变化,对现有 justfiles 的解析。

在合并一个格外大的变更之前, 要运行 Janus 确保没有破坏。 不要担心 Janus 的运行有多麻烦, Casey(原作者) 会为你,在需要它时,对变更运行 Janus。

FAQ

make 的什么不良癖好,just 避免了?

make 有一些混淆或复杂的行为,或者说,使它不适合用作一般的命令运行器.

一个例子是,有时 make 不会在配方中运行命令。例如,如果有一个文件叫test,例子如下且运行它:

test:
  ./test

Make 实际上,会拒绝运行它:

$ make test
make: `test' is up to date.

Make 发觉这个test配方,并假定它产生一个名为test的文件。 然后, 该文件已存在,因此假定配方不需要运行。

公平地说,当使用 make 作为构建系统时,这种行为是可取的,但是当使用它作为命令运行程序时,则不是那么回事。

其他一些例子,包括必须理解=:=赋值两者之间的区别;弄乱 makefile 的话,产生混乱的错误消息;不得不通过$$,在配方中使用环境变量;以及 Make 不同风格的配方之间的不相容性。

just 和 cargo build 脚本有一腿吗?

Cargo build 脚本有一个非常具体的用途,这是控制 Cargo , 正确建立你的 Rust 项目。这可能包括将命令行参数添加到rustc中调用,建立外部依赖,或运行某种代码生成步骤.

just,则控制另一方面,是开发过程中部分,需要运行的所有其他杂项命令。比如在不同的配置中运行测试、链接代码、将构建工件推送到服务器、删除临时文件等等.

而且,虽然just写于 Rust 语言,但它可以被使用在许多地方,而不在意你的项目使用的语言或构建系统.

进一步漫谈

我个人觉得写了justfile很有用,它几乎用到每一个项目,无论大小.

在一个有多个贡献者的大型项目中,拥有一个包含所有命令的文件来处理项目是非常有用的.

可能需要测试、构建、lint、部署等不同的命令,将它们全部放在一个地方很有用,并且减少了告诉人们要运行哪些命令,以及如何键入命令的时间.

而且,有了一个易于放置命令的地方,您很可能会想到其他有用的,项目集体智慧的部分东西,但智慧被集中在一起,没有到处扔,像:神秘命令需要修订控制工作流程的某些部分一样;安装所有项目的依赖项,或者您可能需要传递给构建系统的所有随机参数.

配方的一些想法:

  • 部署/发布项目

  • 发布模式与调试模式的构建

  • 运行调试模式或启用日志记录

  • 复杂的 git 工作流

  • 更新依赖关系

  • 运行不同的测试集,例如快速测试和完整测试,或者用详细的输出来运行它们.

  • 任何复杂的命令集,如果只是为了能够记得它们,你就应该写在某个地方(当然是 justfile 啦).

即使对于小型的个人项目,能够按名称记住命令也是很好的,而不是^反向搜索 shell 历史记录。也许在神秘(莫名其妙)的构建系统,使用未知语言编写的旧项目, 若是使用just,那justfile可是会知道您需要执行,还是想要的所有命令,这对于您来说是巨大的好处。如果你输入just可能会发生一些有用(或至少有趣!)的事情.

有关配方的建议,请查看这个项目的justfile或者一些justfile野花.

无论如何,这是我认为的赞,且详细的 README 文件.

我希望你喜欢用just,并在您的所有计算体系工作中找到巨大的成功和满足感!

😸

About

中文翻译:<casey/just> 是保存和运行项目的特定命令的简便方法. :heart: 校对 ✅


Languages

Language:Shell 100.0%