pull/370/head
eric.tao 2022-09-12 17:20:13 +07:00
parent 4bd6bd4638
commit e22ff2a84d
16 changed files with 280 additions and 530 deletions

@ -1,17 +1,17 @@
# Summary总结
# 总结
- [Introduction](./introduction.md)
- [Installation](./installation.md)
- [Usage](./usage.md)
- [简介](./introduction.md)
- [安装](./installation.md)
- [使用](./usage.md)
- [Git](./git.md)
- [Mercurial](./mercurial.md)
- [Languages Supported](./languages_supported.md)
- [Internals: Parsing](./parsing.md)
- [Internals: Diffing](./diffing.md)
- [Tricky Cases](./tricky_cases.md)
- [Contributing](./contributing.md)
- [Parser Vendoring](./parser_vendoring.md)
- [Adding A Parser](./adding_a_parser.md)
- [Glossary](./glossary.md)
- [Alternative Projects](./alternative_projects.md)
- [Tree Diffing](./tree_diffing.md)
- [支持语言](./languages_supported.md)
- [解析](./parsing.md)
- [差异分析](./diffing.md)
- [棘手的例子](./tricky_cases.md)
- [贡献](./contributing.md)
- [解析器依赖库](./parser_vendoring.md)
- [添加解析器](./adding_a_parser.md)
- [词典](./glossary.md)
- [其它项目](./alternative_projects.md)
- [树状差异分析](./tree_diffing.md)

@ -1,36 +1,29 @@
# Adding A Parser添加解析器
# 添加解析器
## Finding a parser寻找解析器
## 寻找解析器
New parsers for difftastic must be reasonably complete and maintained.Difftastic的新解析器必须完整且合理地维护。
Difftastic的新解析器必须完整且合理地维护。
There are many tree-sitter parsers available, and the tree-sitter
website includes [a list of some well-known
parsers](https://tree-sitter.github.io/tree-sitter/#available-parsers).有许多解析器可用,网站包括[一些著名的解析器列表](https://tree-sitter.github.io/tree-sitter/#available-parsers)。
有许多解析器可用,网站包括[一些著名的解析器列表](https://tree-sitter.github.io/tree-sitter/#available-parsers)。
## Add the source code添加源码
## 添加源码
Once you've found a parser, add it as a git subtree to
`vendor/`. We'll use
[tree-sitter-json](https://github.com/tree-sitter/tree-sitter-json) as
an example.一旦你找到一个解析器需要将其作为git的subtree添加到`vendor/`中。我们会使用[tree-sitter-json](https://github.com/tree-sitter/tree-sitter-json)作为例子。
一旦你找到一个解析器需要将其作为git的subtree添加到`vendor/`中。我们会使用[tree-sitter-json](https://github.com/tree-sitter/tree-sitter-json)作为例子。
```
$ git subtree add --prefix=vendor/tree-sitter-json git@github.com:tree-sitter/tree-sitter-json.git master
```
## Configure the build配置编译过程
## 配置编译过程
Cargo does not allow packages to include subdirectories that contain a
`Cargo.toml`. Add a symlink to the `src/` parser subdirectory.Cargo不允许软件包包含`Cargo.toml`。需要在`src/`解析器子目录中添加一个符号链接。
Cargo不允许软件包包含`Cargo.toml`。需要在`src/`解析器子目录中添加一个符号链接。
```
$ cd vendor
$ ln -s tree-sitter-json/src tree-sitter-json-src
```
You can now add the parser to build by including the directory in
`build.rs`. 现在你可以通过在`build.rs`中加入目录,并将解析器添加到构建中。
现在你可以通过在`build.rs`中加入目录,并将解析器添加到构建中。
```
TreeSitterParser {
@ -40,12 +33,11 @@ TreeSitterParser {
},
```
If your parser includes custom C or C++ files for lexing (e.g. a
`scanner.cc`), add them to `extra_files`.如果你的解析器包括用于语法的自定义C或C++文件(例如,一个`scanner.cc`),请将它添加到`extra_files`中。
如果你的解析器包括用于语法的自定义C或C++文件(例如,一个`scanner.cc`),请将它添加到`extra_files`中。
## Configure parsing配置解析器
## 配置解析器
Add an entry to `tree_sitter_parser.rs` for your language.为你的语言在`tree_sitter_parser.rs`中增加一个条目。
为你的语言在`tree_sitter_parser.rs`中增加一个条目。
```
Json => {
@ -64,64 +56,46 @@ Json => {
}
```
`name` is the human-readable name shown in the UI.`name`是用户节目中显示的可读名称。
`name`是用户节目中显示的可读名称。
`atom_nodes` is a list of tree-sitter node names that should be
treated as atoms even though the nodes have children. This is common
for things like string literals or interpolated strings, where the
node might have children for the opening and closing quote.`atom_nodes`是一个树形节点名称的列表,这些节点应被视为原子。即使这些节点有子节点,也应被视为原子。这对于字符串表面之或插值字符串非常常见的,因为在这种情况下,节点可能有用来表示开头和结尾的引用号。
`atom_nodes`是一个树形节点名称的列表,这些节点应被视为原子。即使这些节点有子节点,也应被视为原子。这对于字符串表面之或插值字符串非常常见的,因为在这种情况下,节点可能有用来表示开头和结尾的引用号。
If you don't set `atom_nodes`, you may notice added/removed content
shown in white. This is usually a sign that child node should have its
parent treated as an atom.如果你没有设置`atom_nodes`,你可能会主要添加/删除的内容显示为白色。这通常表面了子节点的父节点应该被当作原子。
如果你没有设置`atom_nodes`,你可能会主要添加/删除的内容显示为白色。这通常表面了子节点的父节点应该被当作原子。
`delimiter_tokens` are delimiters that difftastic stores on
the enclosing list node. This allows difftastic to distinguish
delimiter tokens from other punctuation in the language.`delimiter_tokens`是Difftastic存储在闭包节点上的定界符。这使得Difftastic能够区分划线符号和语言中的其它标点符号。
`delimiter_tokens`是Difftastic存储在闭包节点上的定界符。这使得Difftastic能够区分划线符号和语言中的其它标点符号。
If you don't set `delimiter_tokens`, difftastic will consider the
tokens in isolation, and may think that a `(` was added but the `)`
was unchanged.如果你不设置`delimiter_tokens`Difftastic会单独考虑这些标记并会认为是添加了`(`,但是`)`没有发生变化。
如果你不设置`delimiter_tokens`Difftastic会单独考虑这些标记并会认为是添加了`(`,但是`)`没有发生变化。
You can use `difft --dump-ts foo.json` to see the results of the
tree-sitter parser, and `difft --dump-syntax foo.json` to confirm that
you've set atoms and delimiters correctly.你可以使用`difft --dump-ts foo.json`来查看树状解析器的结果,并使用`difft --dump-syntax foo.json`来确认你已经正确设置了原子和定界符。
你可以使用`difft --dump-ts foo.json`来查看树状解析器的结果,并使用`difft --dump-syntax foo.json`来确认你已经正确设置了原子和定界符。
## Configure sliders配置滑动
## 配置滑块
Add an entry to `sliders.rs` for your language.请为你的语言在`sliders.rs`中添加入口。
请为你的语言在`sliders.rs`中添加入口。
## Configure language detection配置语言检测
## 配置语言检测
Update `from_extension` in `guess_language.rs` to detect your new
language.更新`guess_language.rs`中的`from_extension`以检测新的语言。
更新`guess_language.rs`中的`from_extension`以检测新的语言。
```
"json" => Some(Json),
```
There may also file names or shebangs associated with your
language. [GitHub's linguist
definitions](https://github.com/github/linguist/blob/master/lib/linguist/languages.yml)
is a useful source of common file extensions.也可能有与你的语言相关的文件名或shebangs。[GitHub的语言定义](https://github.com/github/linguist/blob/master/lib/linguist/languages.yml)是针对常见文件扩展名的一个有用来源。
也可能有与你的语言相关的文件名或shebangs。[GitHub的语言定义](https://github.com/github/linguist/blob/master/lib/linguist/languages.yml)是针对常见文件扩展名的一个有用来源。
## Syntax highlighting (Optional)语法高亮(可选)
## 语法高亮(可选)
To add syntax highlighting for your language, you'll also need a symlink
to the `queries/highlights.scm` file, if available.要为你的语言添加语法高亮,如果有的话,你还需要在`queries/highlights.scm`文件一个符号链接。
要为你的语言添加语法高亮,如果有的话,你还需要在`queries/highlights.scm`文件一个符号链接。
```
$ cd vendor/highlights
$ ln -s ../tree-sitter-json/queries/highlights.scm json.scm
```
## Add a regression test添加一个回归测试
## 添加一个回归测试
Finally, add a regression test for your language. This ensures that
the output for your test file doesn't change unexpectedly.最后,为你的语言添加一个回归测试,这样可以确保你的测试文件的输出不会意外改变。
最后,为你的语言添加一个回归测试,这样可以确保你的测试文件的输出不会意外改变。
Regression test files live in `sample_files/` and have the form
`foo_before.abc` and `foo_after.abc`.回归测试文件存在于`sample_files/`中,其形式为
回归测试文件存在于`sample_files/`中,其形式为
`foo_before.abc`和`foo_after.abc`。
```
@ -129,7 +103,7 @@ $ nano simple_before.json
$ nano simple_after.json
```
Run the regression test script and update the `.expected` file.运行回归测试脚本并更新`.expect`文件。
运行回归测试脚本并更新`.expect`文件。
```
$ ./sample_files/compare_all.sh

@ -1,5 +1,3 @@
# Alternative Projects其它项目
# 其它项目
Many different tools exist for diffing files. This section of the
manual discusses the design of other tools that have influenced
difftastic.有许多不同的工具可以比较文件。本说明书的这一个部分讨论了其他影响到Difftastic的工具。
有许多不同的工具可以比较文件。本说明书的这一个部分讨论了其他影响到Difftastic的工具。

@ -1,24 +1,21 @@
# Contributing贡献
# 贡献
## Building构建
## 构建
Install Rust with [rustup](https://rustup.rs/), then clone the code.用[rustup](https://rustup.rs/)安装Rust然后克隆代码。
用[rustup](https://rustup.rs/)安装Rust然后克隆代码。
```
$ git clone git@github.com:Wilfred/difftastic.git
$ cd difftastic
```
Difftastic uses [Cargo](https://doc.rust-lang.org/cargo/) for
building.Difftastic使用[Cargo](https://doc.rust-lang.org/cargo/)进行构建。
Difftastic使用[Cargo](https://doc.rust-lang.org/cargo/)进行构建。
```
$ cargo build
```
Debug builds are significantly slower than release builds. For files
with more than fifty lines, it's usually worth using an optimised
build.调试构建的速度明显比发布构建的速度慢。对于超过50行的文件通常建议使用一个优化的构建。
调试构建的速度明显比发布构建的速度慢。对于超过50行的文件通常建议使用一个优化的构建。
```
$ cargo build --release
@ -26,95 +23,80 @@ $ cargo build --release
## Manual说明书
This website is generated with
[mdbook](https://github.com/rust-lang/mdBook/). mdbook can be
installed with Cargo.这个网站是用[mdbook](https://github.com/rust-lang/mdBook/)。mdbook可以用Cargo安装。
这个网站是用[mdbook](https://github.com/rust-lang/mdBook/)。mdbook可以用Cargo安装。
```
$ cargo install mdbook
```
You can then use the `mdbook` binary to build and serve the site
locally.然后你可以使用`mdbook`二进制文件来建立和在本地运行网站。
然后你可以使用`mdbook`二进制文件来建立和在本地运行网站。
```
$ cd manual
$ mdbook serve
```
## API DocumentationAPI文档
## API文档
You can browse the internal API documentation generated by rustdoc
[here](https://difftastic.wilfred.me.uk/rustdoc/difft/).你可以浏览由rustdoc生成的内部API文档[在这里](https://difftastic.wilfred.me.uk/rustdoc/difft/)。
你可以浏览由rustdoc生成的内部API文档[在这里](https://difftastic.wilfred.me.uk/rustdoc/difft/)。
Difftastic's internal docs are not available on docs.rs, as it [does
not support binary crates today](https://difftastic.wilfred.me.uk/rustdoc/difft/).Difftastic的内部文档在docs.rs上没有提供因为它[不支持二进制工具箱](https://difftastic.wilfred.me.uk/rustdoc/difft/)。
Difftastic的内部文档在docs.rs上没有提供因为它[不支持二进制工具箱](https://difftastic.wilfred.me.uk/rustdoc/difft/)。
## Testing测试
## 测试
```
$ cargo test
```
There are also several files in `sample_files/` that you can use.在`sample_files/`中也有几个文件你可以使用。
在`sample_files/`中也有几个文件你可以使用。
The best way to test difftastic is to look at history from a real
project. Set `GIT_EXTERNAL_DIFF` to point to your current build.测试difftastic的最好方法是在真实项目查看历史。设置`GIT_EXTERNAL_DIFF`指向你当前的构建。
测试difftastic的最好方法是在真实项目查看历史。设置`GIT_EXTERNAL_DIFF`指向你当前的构建。
For example, you can run difftastic on its own source code.例如你可以在自己的源代码上运行Difftastic。
例如你可以在自己的源代码上运行Difftastic。
```
$ GIT_EXTERNAL_DIFF=./target/release/difft git log -p --ext-diff -- src
```
## Logging
## 记录
Difftastic uses the `pretty_env_logger` library to log some additional
debug information.Difftastic使用`pretty_env_logger`库来记录一些额外的调试信息。
Difftastic使用`pretty_env_logger`库来记录一些额外的调试信息。
```
$ RUST_LOG=debug cargo run sample_files/old.jsx sample_files/new.jsx
```
See the [`env_logger`
documentation](https://docs.rs/env_logger/0.9.0/env_logger/) for full details.请参阅[`env_logger`](https://docs.rs/env_logger/0.9.0/env_logger/)以获得完整的细节。
请参阅[`env_logger`](https://docs.rs/env_logger/0.9.0/env_logger/)以获得完整的细节。
## Profiling
## 调试
If you have a file that's particularly slow, you can use
[cargo-flamegraph](https://github.com/flamegraph-rs/flamegraph) to see
which functions are slow.如果你有一个特别慢的文件,你可以使用 [cargo-flamegraph](https://github.com/flamegraph-rs/flamegraph) 来查看是哪些函数慢的。
如果你有一个特别慢的文件,你可以使用 [cargo-flamegraph](https://github.com/flamegraph-rs/flamegraph) 来查看是哪些函数慢的。
```
$ CARGO_PROFILE_RELEASE_DEBUG=true cargo flamegraph --bin difft sample_files/slow_before.rs sample_files/slow_after.rs
```
It's also worth looking at memory usage, as graph traversal bugs can
lead to huge memory consumption.内存的使用情况也是值得关注,因为图的遍历错误会导致巨大的内存消耗。
内存的使用情况也是值得关注,因为图的遍历错误会导致巨大的内存消耗。
```
$ /usr/bin/time -v ./target/release/difft sample_files/slow_before.rs sample_files/slow_after.rs
```
If timing measurement are noisy, Linux's `perf` tool will report
instructions executed, which is more stable.如果定时测量有噪音Linux的`perf`工具将报告 执行的指令,这也是更加稳定的。
如果定时测量有噪音Linux的`perf`工具将报告 执行的指令,这也是更加稳定的。
```
$ perf stat ./target/release/difft sample_files/slow_before.rs sample_files/slow_after.rs
$ perf stat ./target/release/difft sample_files/typing_old.ml sample_files/typing_new.ml
```
Many more profiling techniques are discussed in the [The Rust
Performance Book](https://nnethercote.github.io/perf-book/).还有很多剖析技术在[The Rust性能手册](https://nnethercote.github.io/perf-book/)中讨论了。
还有很多剖析技术在[The Rust性能手册](https://nnethercote.github.io/perf-book/)中讨论了。
## Releasing发布
## 发布
Use Cargo to create a new release, and tag it in git. Difftastic has a
helper script for this:使用Cargo创建一个新的版本并在git中标记它。Difftastic有一个帮助脚本。
使用Cargo创建一个新的版本并在git中标记它。Difftastic有一个帮助脚本
```
$ ./scripts/release.sh
```
You can now increment the version in Cargo.toml and add a new entry to
CHANGELOG.md.现在你可以增加Cargo.toml中的版本并在
现在你可以增加Cargo.toml中的版本并在
CHANGELOG.md加一个新的条目。

@ -1,17 +1,14 @@
# Diffing差异分析
# 差异分析
Difftastic treats diff calculations as a route finding problem on a
directed acyclic graph.Difftastic将diff计算视作为有向无环图上的寻路问题。
Difftastic将diff计算视作为有向无环图上的寻路问题。
## Graph Representation图表示
## 图表示
A vertex in the graph represents a position in two syntax trees.图中的一个顶点代表两个语法树中的一个位置。
图中的一个顶点代表两个语法树中的一个位置。
The start vertex has both positions pointing to the first syntax node
in both trees. The end vertex has both positions just
after the last syntax node in both trees.开始顶点的两个位置都指向两个树的第一个语法节点。结束顶点的两个位置都正好在两棵语法树的最后一个节点之后。
开始顶点的两个位置都指向两个树的第一个语法节点。结束顶点的两个位置都正好在两棵语法树的最后一个节点之后。
Consider comparing `A` with `X A`.以`A`和`X A`比较为例:
以`A`和`X A`比较为例:
```
START
@ -27,12 +24,10 @@ END
+---------------------+
```
From the start vertex, we have two options:从起始顶点开始,我们有两个选择:
从起始顶点开始,我们有两个选择:
* we can mark the first syntax node on the left as novel, and advance
to the next syntax node on the left (vertex 1 above), or我们可以将左边的第一个语法节点标记为注意项并推进到左边的下一个语法节点即上面的顶点1
* we can mark the first syntax node on the right as novel, and advance
to the next syntax node on the right (vertex 2 above).我们可以将右边的第一个语法节点标记为注意项并推进到右边的下一个语法节点上即上面的顶点2
* 我们可以将左边的第一个语法节点标记为注意项并推进到左边的下一个语法节点即上面的顶点1
* 我们可以将右边的第一个语法节点标记为注意项并推进到右边的下一个语法节点上即上面的顶点2
```
START
@ -50,8 +45,7 @@ From the start vertex, we have two options:从起始顶点开始,我们有两
```
Choosing "novel atom R" to vertex 2 will turn out to be the best
choice. From vertex 2, we can see three routes to the end vertex.选择"新原子R"到顶点2将是最佳选择。从顶点2我们可以看到有三条路线通往终点。
选择"新原子R"到顶点2将是最佳选择。从顶点2我们可以看到有三条路线通往终点。
```
2
@ -76,26 +70,17 @@ choice. From vertex 2, we can see three routes to the end vertex.选择"新原
+---------------------+
```
## Comparing Routes比较路线
## 比较路线
We assign a cost to each edge. Marking a syntax node as novel is worse
than finding a matching syntax node, so the "novel atom" edge has a
higher cost than the "syntax nodes match" edge.我们给每条边分配一个成本。将一个语法节点标记为新奇,比找到一个匹配的语法节点更糟糕,因此"新奇原子"边的成本比"语法节点匹配"边更高。
我们给每条边分配一个成本。将一个语法节点标记为新奇,比找到一个匹配的语法节点更糟糕,因此"新奇原子"边的成本比"语法节点匹配"边更高。
The best route is the lowest cost route from the start vertex to the
end vertex.最佳路线是指从起始顶点到终端顶点成本最低的路线。
最佳路线是指从起始顶点到终端顶点成本最低的路线。
## Finding The Best Route寻找最佳路线
## 寻找最佳路线
Difftastic uses Dijkstra's algorithm to find the best (i.e. lowest cost)
route.Difftastic使用Dijkstra算法来寻找最佳或称最低成本的路线。
Difftastic使用Dijkstra算法来寻找最佳或称最低成本的路线。
One big advantage of this algorithm is that we don't need to construct
the graph in advance. Constructing the whole graph would require
exponential memory relative to the number of syntax nodes. Instead,
vertex neighbours are constructed as the graph is explored.这种算法的一大优势是,我们不需要事先构建图。相对于语法节点的数量,构建整个图需要指数级的内存。相反顶点的邻居是在探索图的过程中构建的。
这种算法的一大优势是,我们不需要事先构建图。相对于语法节点的数量,构建整个图需要指数级的内存。相反顶点的邻居是在探索图的过程中构建的。
There are lots of resources explaining Dijkstra's algorithm online,
but I particularly recommend the [graph search section of Red Blob
Games](https://www.redblobgames.com/pathfinding/a-star/introduction.html#dijkstra).网上有很多解释Dijkstra的算法但我特别推荐[Red
网上有很多解释Dijkstra的算法但我特别推荐[Red
Blod Games的图搜索部分](https://www.redblobgames.com/pathfinding/a-star/introduction.html#dijkstra)。

@ -1,8 +1,6 @@
# Git
Git [supports external diff
tools](https://git-scm.com/docs/diff-config#Documentation/diff-config.txt-diffexternal). You
can use `GIT_EXTERNAL_DIFF` for a one-off git command.Git[支持使用外部的diff工具](https://git-scm.com/docs/diff-config#Documentation/diff-config.txt-diffexternal)。你可以使用`GIT_EXTERNEL_DIFF`来进行一键git命令。
Git[支持使用外部的diff工具](https://git-scm.com/docs/diff-config#Documentation/diff-config.txt-diffexternal)。你可以使用`GIT_EXTERNEL_DIFF`来进行一键git命令。
```
$ GIT_EXTERNAL_DIFF=difft git diff
@ -10,7 +8,7 @@ $ GIT_EXTERNAL_DIFF=difft git log -p --ext-diff
$ GIT_EXTERNAL_DIFF=difft git show e96a7241760319 --ext-diff
```
If you want to use difftastic by default, use `git config`.如果你想要默认使用Difftastic可以使用`git config`。
如果你想要默认使用Difftastic可以使用`git config`。
```
# Set git configuration for the current repository.
@ -20,9 +18,7 @@ $ git config diff.external difft
$ git config --global diff.external difft
```
After running `git config`, `git diff` will use `difft`
automatically. Other git commands require `--ext-diff` to use
`diff.external`.在运行`git config`后,`git diff`命令将会自动使用`difft`。其他情况则需要使用`--ext-diff`来使用`diff.externel`。
在运行`git config`后,`git diff`命令将会自动使用`difft`。其他情况则需要使用`--ext-diff`来使用`diff.externel`。
```
$ git diff
@ -32,12 +28,9 @@ $ git show e96a7241760319 --ext-diff
## git-difftool
[git difftool](https://git-scm.com/docs/git-difftool) is a git command
for viewing the current changes with a different diff tool. It's
useful if you want to use difftastic occasionally.[git difftool](https://git-scm.com/docs/git-difftool) 是一款使用不同diff工具来查看当前修改的git命令。如果你想要偶尔使用Difftastic的话这将会非常有用。
[git difftool](https://git-scm.com/docs/git-difftool) 是一款使用不同diff工具来查看当前修改的git命令。如果你想要偶尔使用Difftastic的话这将会非常有用。
Add the
following to your `.gitconfig` to use difftastic as your difftool.添加下列内容到你的`.gitconfig`中就会让Difftastic作为你的difftool工具。
添加下列内容到你的`.gitconfig`中就会让Difftastic作为你的difftool工具。
```ini
[diff]
@ -50,14 +43,13 @@ following to your `.gitconfig` to use difftastic as your difftool.添加下列
cmd = difft "$LOCAL" "$REMOTE"
```
You can then run `git difftool` to see current changes with difftastic.然后你可以使用`git difftool`来用Difftastic查看当前修改。
然后你可以使用`git difftool`来用Difftastic查看当前修改。
```
$ git difftool
```
We also recommend the following settings to get the best difftool
experience.我们还推荐使用下列设置来获得最好的difftool体验。
我们还推荐使用下列设置来获得最好的difftool体验。
```ini
# Use a pager for large output, just like other git commands.

@ -1,34 +1,20 @@
# Glossary词典
# 词典
**Atom原子**: An atom is an item in difftastic's syntax tree structure
that has no children. It represents things like literals, variable
names, and comments. See also 'list'.原子是Difftastic语法树结构中的一个项目没有子项。它代表着字面量、变量名以及注释。 另见'list'。
**原子**: 原子是Difftastic语法树结构中的一个项目没有子项。它代表着字面量、变量名以及注释。 另见'list'。
**Delimiter分隔符**: A paired piece of syntax. A list has an open delimiter
and a close delimiter, such as `[` and `]`. Delimiters may not be
punctuation (e.g. `begin` and `end`) and may be empty strings (e.g. infix
syntax converted to difftastic's syntax tree).即一个成对的语法。一个列表有一个开放定界符和一个封闭定界符,例如`[`和`]`。分隔符不可以是标点符号(例如,`begin`和`end`以及空字符串例如infix语法转换为Difftastic的语法树
**分隔符**: 即一个成对的语法。一个列表有一个开放定界符和一个封闭定界符,例如`[`和`]`。分隔符不可以是标点符号(例如,`begin`和`end`以及空字符串例如infix语法转换为Difftastic的语法树
**LHS**: Left-hand side. Difftastic compares two items, and LHS refers
to the first item. See also 'RHS'.即Left-hand side。Difftastic会对比两个文件而LHS是指第一个文件。另见'RHS'。
**LHS**: 即Left-hand side。Difftastic会对比两个文件而LHS是指第一个文件。另见'RHS'。
**List列表**: A list is an item in difftastic's syntax tree structure that
has an open delimiter, children, and a close delimiter. It represents
things like expressions and function definitions. See also 'atom'.列表是Difftastic语法树结构中的一个项目它有一个开放定界符、子项和一个封闭定界符。它代表表达式和函数定义等东西。另见'atom'。
**列表**: 列表是Difftastic语法树结构中的一个项目它有一个开放定界符、子项和一个封闭定界符。它代表表达式和函数定义等东西。另见'atom'。
**Novel注意项**: An addition or a removal. Syntax is novel if it occurs
in only one of the two items being compared.一个增加或一个减少。如果语法只出现在被比较的两个项目中的一个,那么它就是一个注意项。
**注意项**: 一个增加或一个减少。如果语法只出现在被比较的两个项目中的一个,那么它就是一个注意项。
**RHS**: Right-hand side. Difftastic compares two items, and RHS
refers to the second item. See also 'LHS'.即Right-hand side。Difftastic会对比两个文件而RHS是指第一个文件。另见'LHS'。
**RHS**: 即Right-hand side。Difftastic会对比两个文件而RHS是指第一个文件。另见'LHS'。
**Root根**: A syntax tree without a parent node. Roots represent
top-level definitions in the file being diffed.
**根**: 一个没有父节点的语法树。根代表被差异的文件中的顶级定义。
**Syntax node**: An item in difftastic's syntax tree structure. Either
an atom or a list.一个没有父节点的语法树。根代表被差异的文件中的顶级定义。
**语法节点**: Difftastic的语法树结构中的一个项目。可以是一个原子或一个列表。
**字符**: A small piece of syntax tracked by difftastic (e.g. `$x`,
`function` or `]`), for highlighting and aligned display. This is
either an atom or a non-empty delimiter.一小段由Difftastic跟踪的语法例如`$x`,
**字符**: 一小段由Difftastic跟踪的语法例如`$x`,
`function``]`),用于高亮显示和对齐显示。它是原子或者是一个非空的分隔符。

@ -1,65 +1,50 @@
# Installation安装
# 安装
## Installing a binary从二进制安装
## 从二进制安装
Difftastic [provides GitHub
releases](https://github.com/Wilfred/difftastic/releases) with
prebuilt binaries.Difftastic以预先编译好的二进制的形式[提供Github realease](https://github.com/Wilfred/difftastic/releases) 。
Difftastic以预先编译好的二进制的形式[提供Github realease](https://github.com/Wilfred/difftastic/releases) 。
Packages are also available on the following platforms.在以下平台上也可以使用软件包。
在以下平台上也可以使用软件包。
[![Packaging status](https://repology.org/badge/vertical-allrepos/difftastic.svg)](https://repology.org/project/difftastic/versions)
## Installing via homebrew (on macOS or Linux)通过homebrew安装在macos或者Linux平台
## 通过homebrew安装在macos或者Linux平台
Difftastic can be installed with [Homebrew](https://formulae.brew.sh/formula/difftastic) on macOS or Linux.Difftastic可以用[Homebrew](https://formulae.brew.sh/formula/difftastic)安装在macOS或Linux上。
Difftastic可以用[Homebrew](https://formulae.brew.sh/formula/difftastic)安装在macOS或Linux上。
```
$ brew install difftastic
```
## Installing from source从源码安装
## 从源码安装
### Build Requirements编译要求
### 编译要求
Difftastic is written in Rust, so you will need Rust installed. I
recommend [rustup](https://rustup.rs/) to install Rust. Difftastic
requires Rust version 1.57 or later.Difftasitc是使用Rust编写的所以你需要安装Rust。我推荐使用[rustup](https://rustup.rs/)来安装Rust。
Difftasitc是使用Rust编写的所以你需要安装Rust。我推荐使用[rustup](https://rustup.rs/)来安装Rust。
You will also need a C++ compiler that supports C++14. If you're using
GCC, you need at least version 8.同时你也需要一个支持C++14的C++编译器。如果你正在使用GCC则GCC版本至少为8。
同时你也需要一个支持C++14的C++编译器。如果你正在使用GCC则GCC版本至少为8。
### Build编译
You can download and build [difftastic on
crates.io](https://crates.io/crates/difftastic) with Cargo (which is
part of Rust).你可以下载并通过Cargo它是Rust的一部分来编译[difftastic on
你可以下载并通过Cargo它是Rust的一部分来编译[difftastic on
crates.io](https://crates.io/crates/difftastic) 。
```
$ cargo install difftastic
```
Difftastic uses the `cc` crate for building C/C++ dependencies. This
allows you to use environment variables `CC` and `CXX` to control the
compiler used (see [the cc
docs](https://github.com/alexcrichton/cc-rs#external-configuration-via-environment-variables)). Difftastic使用`cc`程序箱来构建C/C++的依赖关系。这使得你可以通过环境变量`CC`和`CXX`来控制使用的编译器参照see [the cc
Difftastic使用`cc`程序箱来构建C/C++的依赖关系。这使得你可以通过环境变量`CC`和`CXX`来控制使用的编译器参照see [the cc
docs](https://github.com/alexcrichton/cc-rs#external-configuration-via-environment-variables))。
See [contributing](./contributing.md) for instructions on debug
builds.参考[contributing](./contributing.md)来查看有关构建的说明。
参考[contributing](./contributing.md)来查看有关构建的说明。
## (Optional) Install MIME Database可选安装MINE数据库
## 可选安装MINE数据库
If a MIME database is available, difftastic will use it to detect
binary files more accurately. This is the same database used by the
`file` command, so you probably already have it.如果有一个MIME数据库Difftastic将使用它来更准确地检测二进制文件。这个也是使用`file`命令时所调用的同一个数据库,你可能已经安装了它。
如果有一个MIME数据库Difftastic将使用它来更准确地检测二进制文件。这个也是使用`file`命令时所调用的同一个数据库,你可能已经安装了它。
The MIME database path is [specified in the XDG
specification](https://specifications.freedesktop.org/shared-mime-info-spec/0.11/ar01s03.html). The
database should be at one of the following paths:MIME数据库的路径[是在XDG的规定下](https://specifications.freedesktop.org/shared-mime-info-spec/0.11/ar01s03.html)
MIME数据库的路径[是在XDG的规定下](https://specifications.freedesktop.org/shared-mime-info-spec/0.11/ar01s03.html)
* `/usr/share/mime/magic`
* `/usr/local/share/mime/magic`

@ -1,20 +1,14 @@
# Introduction简介
# 简介
Difftastic is a structural diff tool that understands syntax. It
supports [over 20 programming languages](./languages_supported.html)
and when it works, it's *fantastic*. Difftastic是一个根据文件的语法的结构化比较工具。它支持[超过20款编程语言](./languages_supported.html),当使用它的时候,就会知道它有多么的*棒*。
Difftastic是一个根据文件的语法的结构化比较工具。它支持[超过20款编程语言](./languages_supported.html),当使用它的时候,就会知道它有多么的*棒*。
Difftastic is open source software (MIT license) and [available on
GitHub](https://github.com/wilfred/difftastic). Difftastic是一款开源软件使用MIT许可证并且可以[在Github上获得](https://github.com/wilfred/difftastic)。
Difftastic是一款开源软件使用MIT许可证并且可以[在Github上获得](https://github.com/wilfred/difftastic)。
This copy of the manual describes version DFT_VERSION_HERE. The
[changelog](https://github.com/Wilfred/difftastic/blob/master/CHANGELOG.md)
records which features and bug fixes are in each version. 该说明书会表明当前版本DFT_VERSION_HERE。[变更记录](https://github.com/Wilfred/difftastic/blob/master/CHANGELOG.md)会记录每个版本的特性增加和bug的修复。
该说明书会表明当前版本DFT_VERSION_HERE。[变更记录](https://github.com/Wilfred/difftastic/blob/master/CHANGELOG.md)会记录每个版本的特性增加和bug的修复。
## 语法差异分析
Difftastic [detects the language](./usage.html#language-detection), parses the code, and then
compares the syntax trees. Let's look at an example. Difftastic会[检测编程语言](./usage.html#language-detection),爬取代码,随后比较句法树。见例子:
Difftastic会[检测编程语言](./usage.html#language-detection),爬取代码,随后比较句法树。见例子:
```
// old.rs
@ -35,10 +29,9 @@ let ts_lang = language_override
</code>
</pre>
Notice how difftastic recognises that `.map` is unchanged, even though
it's now on a new line with whitespace. 注意Difftastic是如何识别`.map`那段没有发生变化的,尽管它是在新的一行上以空格开头的。
注意Difftastic是如何识别`.map`那段没有发生变化的,尽管它是在新的一行上以空格开头的。
A line-oriented diff does a much worse job here.如果是以前那种面对行的差异分析表现会不理想。
如果是以前那种面对行的差异分析表现会不理想。
<pre><code style="display:block">$ diff -u old.rs new.rs
@ -50,15 +43,10 @@ A line-oriented diff does a much worse job here.如果是以前那种面对行
</code>
</pre>
Some textual diff tools also highlight word changes (e.g. GitHub or
git's `--word-diff`). They still don't understand the code
though. Difftastic will always find matched delimiters: you can see
the closing `)` from `or_else` has been highlighted. 一些文本差异分析工具也会突出单词的变化例如GitHub或者是git的`--word-diff`但是它们无法做到理解代码本身。Difftastic永远会找到匹配的定界符你可以看到`or_else`结尾出的`)`已经被突出显示。
一些文本差异分析工具也会突出单词的变化例如GitHub或者是git的`--word-diff`但是它们无法做到理解代码本身。Difftastic永远会找到匹配的定界符你可以看到`or_else`结尾出的`)`已经被突出显示。
## 另一种文本差异分析
If input files are not in a format that difftastic understands, it
uses a conventional line-oriented text diff with word highlighting.如果输入的文件格式Difftastic无法理解他就会使用传统的以行为单位的文本差异分析并且会将单词高亮显示。
如果输入的文件格式Difftastic无法理解他就会使用传统的以行为单位的文本差异分析并且会将单词高亮显示。
Difftastic will also use textual diffing when given extremely large
inputs.同时当输入的文件较大时Difftastic也会使用以行为单位的文本差异分析。
同时当输入的文件较大时Difftastic也会使用以行为单位的文本差异分析。

@ -1,12 +1,10 @@
# Languages Supported
# 支持语言
This page lists all the languages supported by difftastic. You can
also view the languages supported in your current installed version
with `difft --list-languages`.本页列出了 difftastic 支持的所有语言。你也可以用`difft --list-languages`查看你当前安装的版本所支持的语言。
本页列出了 difftastic 支持的所有语言。你也可以用`difft --list-languages`查看你当前安装的版本所支持的语言。
## Programming Languages编程语言
## 编程语言
| Language语言 | Parser Used使用的解析器 |
| 语言 | 使用的解析器 |
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Bash | [tree-sitter/tree-sitter-bash](https://github.com/tree-sitter/tree-sitter-bash) |
| C | [tree-sitter/tree-sitter-c](https://github.com/tree-sitter/tree-sitter-c) |
@ -44,9 +42,9 @@ with `difft --list-languages`.本页列出了 difftastic 支持的所有语言
| TypeScript, TSX | [tree-sitter/tree-sitter-typescript](https://github.com/tree-sitter/tree-sitter-typescript) |
| Zig | [maxxnino/tree-sitter-zig](https://github.com/maxxnino/tree-sitter-zig) |
## Structured Text Formats结构化文本格式
## 结构化文本格式
| Language语言 | Parser Used使用的解析器 |
| 语言 | 使用的解析器 |
|----------|-----------------------------------------------------------------------------------|
| CSS | [tree-sitter/tree-sitter-css](https://github.com/tree-sitter/tree-sitter-css) |
| HCL | [MichaHoffmann/tree-sitter-hcl](https://github.com/MichaHoffmann/tree-sitter-hcl) |

@ -1,20 +1,15 @@
# Mercurial
Mercurial [supports external diff
tools](https://www.mercurial-scm.org/wiki/ExtdiffExtension) with the
Extdiff extension. Enable it by adding an entry to `extensions` in
your `.hgrc`.Mercurial[支持另外的diff工具](https://www.mercurial-scm.org/wiki/ExtdiffExtension)与Extdiff扩展。通过在你的`.hgrc`中添加`extensions`条目来启用它。
Mercurial[支持另外的diff工具](https://www.mercurial-scm.org/wiki/ExtdiffExtension)与Extdiff扩展。通过在你的`.hgrc`中添加`extensions`条目来启用它。
```
[extensions]
extdiff =
```
You can then run `hg extdiff -p difft` (assumes the `difft` binary is
on your `$PATH`).然后你可以运行`hg extdiff -p difft`命令(假定`difft`二进制文件存放在你的`$PATH`中。
然后你可以运行`hg extdiff -p difft`命令(假定`difft`二进制文件存放在你的`$PATH`中。
You can also define an alias to run difftastic with hg. Add the
following to your `.hgrc` to run difftastic with `hg dft`.你也可以为带有hg的difftastic的语句定义一个别名。在你的`.hgrc`中添加以下内容,以便用`hg dft`运行Difftastic。
你也可以为带有hg的difftastic的语句定义一个别名。在你的`.hgrc`中添加以下内容,以便用`hg dft`运行Difftastic。
```
[extdiff]
@ -24,15 +19,12 @@ opts.dft = --missing-as-empty
## hg log -p
Mercurial does not have a way of changing the default diff tool, at
least to the author's knowledge. Mercurial没有办法改变默认的差异工具至少就作者所知。
Mercurial没有办法改变默认的差异工具至少就作者所知。
If you just want to view the diff of the most recent commit, you can
use the following.如果你只想查看最近的一次提交的差异,你可以使用下面的方法。
如果你只想查看最近的一次提交的差异,你可以使用下面的方法。
```
GIT_PAGER_IN_USE=1 hg dft -r .^ -r . | less
```
This is equivalent to `hg log -l 1 -p`, although it does not show the
commit message.这就等同于`hg log -l 1 -p`,尽管它不显示提交信息。
这就等同于`hg log -l 1 -p`,尽管它不显示提交信息。

@ -1,22 +1,18 @@
# Vendoring
# 包管理
## Git Subtrees
Tree-sitter parsers are sometimes packaged on npm, sometimes packaged
on crates.io, and have different release frequencies. Difftastic uses
git subtrees (not git submodules) to track parsers.Tree-sitter有时被打包在npm上有时被打包在crates.io上并且它们的发布频率不一样。Difftastic使用git subtrees而不是git submodules来追踪解析器。
Tree-sitter有时被打包在npm上有时被打包在crates.io上并且它们的发布频率不一样。Difftastic使用git subtrees而不是git submodules来追踪解析器。
## Updating a parser升级解析器
## 升级解析器
To update a parser, pull commits from the upstream git repository. For
example, the following command will update the Java parser:如果要更新解析器可以从上游的git仓库拉取提交。例如下面的命令将更新Java解析器
如果要更新解析器可以从上游的git仓库拉取提交。例如下面的命令将更新Java解析器
```
$ git subtree pull --prefix=vendor/tree-sitter-java git@github.com:tree-sitter/tree-sitter-java.git master
```
To see when each parser was last updated, use the following shell
command:如果要查看每个解析器最后一次更新的时间请使用以下的Shell命令。
如果要查看每个解析器最后一次更新的时间请使用以下的Shell命令
```
$ for d in $(git log | grep git-subtree-dir | tr -d ' ' | cut -d ":" -f2 | sort); do echo "$d"; git log --pretty=" %cs" -n 1 $d; done

@ -1,15 +1,10 @@
# 解析代码
Difftastic uses
[tree-sitter](https://tree-sitter.github.io/tree-sitter/) to build a
parse tree. The parse tree is then converted to a simpler tree which
can be diffed.Difftastic会使用[tree-sitter](https://tree-sitter.github.io/tree-sitter/) 来建立一个语法树。然后,该语法树被转换为一个可以用来对比差异的简化版语法树。
Difftastic会使用[tree-sitter](https://tree-sitter.github.io/tree-sitter/) 来建立一个语法树。然后,该语法树被转换为一个可以用来对比差异的简化版语法树。
## Parsing with Tree-sitter
## 使用Tree-sitter解析代码
Difftastic relies on tree-sitter to understand syntax. You can view
the parse tree that tree-sitter produces using the `--dump-ts`
flag.Difftastic依靠tree-sitter来理解语法。你可以使用`--dump-ts`来查看tree-sitter的语法树。
Difftastic依靠tree-sitter来理解语法。你可以使用`--dump-ts`来查看tree-sitter的语法树。
```
$ difft --dump-ts sample_files/javascript_simple_before.js | head
@ -27,14 +22,9 @@ program (0, 0) - (7, 0)
## 简化的语法
Difftastic converts the tree-sitter parse tree to a simplified syntax
tree. The syntax tree is a uniform representation where everything is
either an atom (e.g. integer literals, comments, variable names) or a
list (consisting of the open delimiter, children and the close
delimiter).Difftastic将tree-sitter语法树转换为简化版的语法树。语法树是一种统一的表示方式其中所有东西都是原子例如整数、注释、变量名或者是一个列表由开放分界符、子句和关闭分界符组成以及分隔符。
Difftastic将tree-sitter语法树转换为简化版的语法树。语法树是一种统一的表示方式其中所有东西都是原子例如整数、注释、变量名或者是一个列表由开放分界符、子句和关闭分界符组成以及分隔符。
The flag `--dump-syntax` will display the syntax tree generated for a
file.`--dump-syntax`将显示出当前文件所对应的语法树。
`--dump-syntax`将显示出当前文件所对应的语法树。
```
$ difft --dump-syntax sample_files/before.js
@ -50,24 +40,15 @@ $ difft --dump-syntax sample_files/before.js
...
```
### Conversion Process转换过程
### 转换过程
The simple representation of the difftastic parse tree makes diffing
much easier. Converting the detailed tree-sitter parse tree is a
recursive tree walk, treating tree-sitter leaf nodes as atoms. There
are two exceptions.Difftastic语法树的简单表达方式使得差异分析变得更加容易。Difftastic是通过一种递归树的行走方式来将tree-sitter树进行简化将tree-sitter的节点视作原子来处理。但有两个例外。
Difftastic语法树的简单表达方式使得差异分析变得更加容易。Difftastic是通过一种递归树的行走方式来将tree-sitter树进行简化将tree-sitter的节点视作原子来处理。但有两个例外。
(1) Tree-sitter parse trees sometimes include unwanted structure. Some
grammars consider string literals to be a single token, whereas others
treat strings as a complex structure where the delimiters are
separate.Tree-sitter语法树有时会包括不需要的一些结构有些语法会认为字符串是一种单一的字符而有些则会将字符串视作为复杂的结构此时的分隔符就会将字符串分割开。
(1) Tree-sitter语法树有时会包括不需要的一些结构有些语法会认为字符串是一种单一的字符而有些则会将字符串视作为复杂的结构此时的分隔符就会将字符串分割开。
`tree_sitter_parser.rs` uses `atom_nodes` to mark specific tree-sitter
node names as flat atoms even if the node has children.`tree-sitter_parser.rs`使用`atom_nodes`来标记特定的tree-sitter节点为平原子即使该节点存在子节点。
`tree-sitter_parser.rs`使用`atom_nodes`来标记特定的tree-sitter节点为平原子即使该节点存在子节点。
(2) Tree-sitter parse trees include open and closing delimiters as
tokens. A list `[1]` will have a parse tree that includes `[` and `]`
as nodes.Tree-sitter分析树包括开放和关闭定界符作为其代码。列表`[1]`将有一个包括`[`和`]`的节点的语法树。
(2) Tree-sitter分析树包括开放和关闭定界符作为其代码。列表`[1]`将有一个包括`[`和`]`的节点的语法树。
```
$ echo '[1]' > example.js
@ -80,18 +61,10 @@ program (0, 0) - (1, 0)
] (0, 2) - (0, 3) "]"
```
`tree_sitter_parser.rs` uses `open_delimiter_tokens` to ensure that
`[` and `]` are used as delimiter content in the enclosing list,
rather than converitng them to atoms.`tree_sitter_parser.rs`使用`open_delimiter_tokens`来确保`[`和`]`被用作包围列表内容的分隔符,而不会将其转换为原子。
`tree_sitter_parser.rs`使用`open_delimiter_tokens`来确保`[`和`]`被用作包围列表内容的分隔符,而不会将其转换为原子。
Difftastic can match up atoms that occur in different parts of the
simplified syntax tree. If e.g. a `[` is treated as an atom,
difftastic might match it with another `[` elsewhere. The resulting
diff would be unbalanced, highlighting different numbers of open and
close delimiters.Difftastic可以将出现简化语法树中不同部分的原子进行匹配。例如如果一个`[`被当作一个原子Difftastic可能会在其他地方将其与另一个`]`进行匹配。如果开放和关闭分界符的数量不同,最终的差异分析结果将会是不平衡的。
Difftastic可以将出现简化语法树中不同部分的原子进行匹配。例如如果一个`[`被当作一个原子Difftastic可能会在其他地方将其与另一个`]`进行匹配。如果开放和关闭分界符的数量不同,最终的差异分析结果将会是不平衡的。
### Lossy Syntax Trees
### Lossy Syntax Trees简化的语法树
The simplified syntax tree only stores node content and node
position. It does not store whitespace between nodes, and position is
largely ignored during diffing. 简化的语法树只存储节点内容与节点的位置,不会存储节点之间的空白,而且在差异分析的过程中,空格将会被忽略。
简化的语法树只存储节点内容与节点的位置,不会存储节点之间的空白,而且在差异分析的过程中,空格将会被忽略。

@ -1,123 +1,84 @@
# Tree Diffing
# 树状差异分析
This page summarises some of the other tree diffing tools available.本页总结了一些其他可用的树形差异分析工具。
本页总结了一些其他可用的树形差异分析工具。
If you're in a hurry, start by looking at Autochrome. It's extremely
capable, and has an excellent description of the design.如果你很着急可以先看看Autochrome。它的能力很强并且对设计有着很好的描述。
如果你很着急可以先看看Autochrome。它的能力很强并且对设计有着很好的描述。
If you're interested in a summary of the academic literature, [this
blog
post](http://useless-factor.blogspot.com/2008/01/matching-diffing-and-merging-xml.html)
(and its [accompanying
paper](http://useless-factor.blogspot.com/2008/01/matching-diffing-and-merging-xml.html)
-- mirrored under a CC BY-NC license) are great resources. 如果你对学术文献的摘要感兴趣,[这个帖子](http://useless-factor.blogspot.com/2008/01/matching-diffing-and-merging-xml.html)(和它[附带的论文](http://useless-factor.blogspot.com/2008/01/matching-diffing-and-merging-xml.html)--在CC BY-NC的许可下可以被复制将是一个很好的资源。
如果你对学术文献的摘要感兴趣,[这个帖子](http://useless-factor.blogspot.com/2008/01/matching-diffing-and-merging-xml.html)(和它[附带的论文](http://useless-factor.blogspot.com/2008/01/matching-diffing-and-merging-xml.html)--在CC BY-NC的许可下可以被复制将是一个很好的资源。
## json-diff (2012)
Languages: JSON 语言JSON
Algorithm: Pairwise comparison 算法Pairwise comparison
Output: CLI colours 输出CLI colours
语言JSON
算法Pairwise comparison
输出CLI colours
[json-diff](https://github.com/andreyvit/json-diff) performs a
structural diff of JSON files. It considers subtrees to be different
if they don't match exactly, so e.g. `"foo"` and `["foo"]` are
entirely different.[json-diff](https://github.com/andreyvit/json-diff)展示了JSON文件的结构层面的差异分析。如果两者是不完全匹配的那么它们的子树将是完全不同。例如`"foo"`和`["foo"]`是完全不同的。
[json-diff](https://github.com/andreyvit/json-diff)展示了JSON文件的结构层面的差异分析。如果两者是不完全匹配的那么它们的子树将是完全不同。例如`"foo"`和`["foo"]`是完全不同的。
json-diff is also noteworthy for its extremely readable display of
results.可以注意的是json-diff的结果显示十分方便查看。
可以注意的是json-diff的结果显示十分方便查看。
## GumTree (2014)
Languages: [~10 programming
languages](https://github.com/GumTreeDiff/gumtree/wiki/Languages) 语言:[约有10种编程语言](https://github.com/GumTreeDiff/gumtree/wiki/Languages)
Parser: Several, including [srcML](https://www.srcml.org/) 分析器:多种,包括 [srcML](https://www.srcml.org/)
Algorithm: Top-down, then bottom-up 算法Top-down随后bottom-up
Ouput: HTML, Swing GUI, or text 输出HTMLSwing GUI或者text
[GumTree](https://github.com/GumTreeDiff/gumtree) can parse several
programming languages and then performs a tree-based diff, outputting
an HTML display.[GumTree](https://github.com/GumTreeDiff/gumtree)可以分析多种编程语言并且进行基于树结构的差异分析输出一个HTML的结果界面。
The GumTree algorithm is described in the associated paper
'Fine-grained and accurate source code differencing' by Falleri et al
([DOI](http://doi.acm.org/10.1145/2642937.2642982),
[PDF](https://hal.archives-ouvertes.fr/hal-01054552/document)). It
performs a greedy top-down search for identical subtrees, then
performs a bottom-up search to match up the rest.GumTree算法在Falleri等人的相关论文《细粒度源码差异分析》中有所描述[DOI](http://doi.acm.org/10.1145/2642937.2642982),
语言:[约有10种编程语言](https://github.com/GumTreeDiff/gumtree/wiki/Languages)
分析器:多种,包括 [srcML](https://www.srcml.org/)
算法Top-down随后bottom-up
输出HTMLSwing GUI或者text
[GumTree](https://github.com/GumTreeDiff/gumtree)可以分析多种编程语言并且进行基于树结构的差异分析输出一个HTML的结果界面。
GumTree算法在Falleri等人的相关论文《细粒度源码差异分析》中有所描述[DOI](http://doi.acm.org/10.1145/2642937.2642982),
[PDF](https://hal.archives-ouvertes.fr/hal-01054552/document))。它对相同的子树进行贪婪的自下而上的搜索,随后进行自下而上的搜索来匹配其余的子树。
## Tree Diff (2017)
Languages: S-expression data format 语言S-表达式数据格式
Algorithm: A* search 算法A*搜索
Output: Merged s-expression file 输出合并后的S-表达式文件
语言S-表达式数据格式
算法A*搜索
输出合并后的S-表达式文件
Tristan Hume wrote a tree diffing algorithm during his 2017 internship
and Jane Street. The source code is not available, but [he has a blog
post](https://thume.ca/2017/06/17/tree-diffing/) discussing the design
in depth. Tristan Hume在他2017年实习期间和在Jane Street期间写了一个树状差分算法。源代码是不可以用的但是[他写了一篇博客](https://thume.ca/2017/06/17/tree-diffing/)来对该设计进行了深入讨论。
Tristan Hume在他2017年实习期间和在Jane Street期间写了一个树状差分算法。源代码是不可以用的但是[他写了一篇博客](https://thume.ca/2017/06/17/tree-diffing/)来对该设计进行了深入讨论。
This project finds minimal diffs between s-expression files used as
configuration by Jane Street. It uses A* search to find the minimal
diff between them, and builds a new s-expression with a section marked
with `:date-switch` for the differing parts. 该项目找到了Jane Street用作配置文件的s-表达式文件之间的最小差异。它使用了A*搜索来找到他们之间最小的差异,兵建立一个具有`:date-switch`进行标记差异的新的s-表达式文件。
该项目找到了Jane Street用作配置文件的s-表达式文件之间的最小差异。它使用了A*搜索来找到他们之间最小的差异,兵建立一个具有`:date-switch`进行标记差异的新的s-表达式文件。
(Jane Street also has patdiff, but that seems to be a line-oriented
diff with some whitespace/integer display polish. It doesn't
understand that e.g. whitespace in `"foo "` is meaningful). Jane Street一样有patdiff但那似乎是一个面向行的差异分析并不带着一些空格及整数差异显示。这个工具它并不理解在`"foo "`中的空格是具有意义的。)
Jane Street一样有patdiff但那似乎是一个面向行的差异分析并不带着一些空格及整数差异显示。这个工具它并不理解在`"foo "`中的空格是具有意义的。)
## Autochrome (2017)
Languages: Clojure 语言Clojure
Parser: Custom, preserves comments 分析器Custom并保留注释
Algorithm: Dijkstra (previously A* search) 算法Dijkstra算法A*搜索的先前版本)
Output: HTML 输出HTML
语言Clojure
分析器Custom并保留注释
算法Dijkstra算法A*搜索的先前版本)
输出HTML
[Autochrome](https://fazzone.github.io/autochrome.html) parses Clojure
with a custom parser that preserves comments. Autochrome uses
Dijkstra's algorithm to compare syntax trees.[Autochrome](https://fazzone.github.io/autochrome.html)使用了一个定制的、保留注释的解析器来分析Clojure。Autochrome使用Dijkstra算法来比较语法树之间的差异。
[Autochrome](https://fazzone.github.io/autochrome.html)使用了一个定制的、保留注释的解析器来分析Clojure。Autochrome使用Dijkstra算法来比较语法树之间的差异。
Autochrome's webpage includes worked examples of the algorithm and a
discussion of design tradeoffs. It's a really great resource for
understanding tree diffing techniques in general. Auto chrome的网页包括该算法的工作实例以及对该设计权衡的讨论。这是一个用来了解树形差异分析的重要资源。
Auto chrome的网页包括该算法的工作实例以及对该设计权衡的讨论。这是一个用来了解树形差异分析的重要资源。
## graphtage (2020)
Languages: JSON, XML, HTML, YAML, plist, and CSS 语言JSON, XML, HTML, YAML, plist, and CSS
Parser: json5, pyYAML, ignores comments 解析器json5, pyYAML, ignores comments
Algorithm: Levenshtein distance 算法Levenshtein距离
Output: CLI colours 输出CLI colours
语言JSON, XML, HTML, YAML, plist, and CSS
解析器json5, pyYAML, ignores comments
算法Levenshtein距离
输出CLI colours
[graphtage](https://blog.trailofbits.com/2020/08/28/graphtage/)
compares structured data by parsing into a generic file format, then
displaying a diff. It even allows things like diffing JSON against
YAML. [graphtage](https://blog.trailofbits.com/2020/08/28/graphtage/)通过将结构化数据解析为通用文件格式随后进行差异分析。它甚至允许比较JSON文件和YAML文件之间的区别。
[graphtage](https://blog.trailofbits.com/2020/08/28/graphtage/)通过将结构化数据解析为通用文件格式随后进行差异分析。它甚至允许比较JSON文件和YAML文件之间的区别。
As with json-diff, it does not consider `["foo"]` and `"foo"` to have
any similarities.与json-diff一样它不认为 `["foo"]`和`"foo"`之间有任何相似之处。
与json-diff一样它不认为 `["foo"]`和`"foo"`之间有任何相似之处。
## Diffsitter (2020)
Parser: [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) 解析器:[Tree-sitter](https://tree-sitter.github.io/tree-sitter/)
Algorithm: Longest-common-subsequence 算法LCSLongest-common-subsequence
Output: CLI colours 输出CLI colours
解析器:[Tree-sitter](https://tree-sitter.github.io/tree-sitter/)
算法LCSLongest-common-subsequence
输出CLI colours
[Diffsitter](https://github.com/afnanenayet/diffsitter) is another
tree-sitter based diff tool. It uses [LCS diffing on the leaves of the
syntax
tree](https://github.com/afnanenayet/diffsitter/blob/b0fd72612c6fcfdb8c061d3afa3bea2b0b754f33/src/ast.rs#L310-L313).[Diffsitter](https://github.com/afnanenayet/diffsitter)是另一个使用了tree-sitter解析器的差异分析工具。它使用了[LCS分析语法树中的子树](https://github.com/afnanenayet/diffsitter/blob/b0fd72612c6fcfdb8c061d3afa3bea2b0b754f33/src/ast.rs#L310-L313)。
[Diffsitter](https://github.com/afnanenayet/diffsitter)是另一个使用了tree-sitter解析器的差异分析工具。它使用了[LCS分析语法树中的子树](https://github.com/afnanenayet/diffsitter/blob/b0fd72612c6fcfdb8c061d3afa3bea2b0b754f33/src/ast.rs#L310-L313)。
## sdiff (2021)
Languages: Scheme 语言Scheme
Parser: Scheme's built-in `read`, ignores comments 解析器Scheme内置的`read`,并忽略注释
Algorithm: MH-Diff from the Chawathe paper算法Chawathe论文中的MH-Diff
Output: CLI colours 输出CLI colours
语言Scheme
解析器Scheme内置的`read`,并忽略注释
算法Chawathe论文中的MH-Diff
输出CLI colours
[Semantically meaningful S-expression diff: Tree-diff for lisp source
code](https://archive.fosdem.org/2021/schedule/event/sexpressiondiff/)
was presented at FOSDEM 2021.[Semantically meaningful S-expression diff: Tree-diff for lisp source
code](https://archive.fosdem.org/2021/schedule/event/sexpressiondiff/)
在FOSDEM 2021中被发表。

@ -1,11 +1,10 @@
# Tricky Cases棘手的例子
# 棘手的例子
Tree diffing is challenging in some situations. This page demonstrates
difficult cases observed during development.在某些情况下,树状图的差异分析是具有挑战性的。本页展示了在开发过程中所观察到的困难情况。
在某些情况下,树状图的差异分析是具有挑战性的。本页展示了在开发过程中所观察到的困难情况。
Not all of these cases work well in difftastic yet.并非所有这些情况在Difftastic中都能很好地工作。
并非所有这些情况在Difftastic中都能很好地工作。
## Adding Delimiters添加定界符
## 添加定界符
```
;; Before
@ -15,17 +14,13 @@ x
(x)
```
Desired result: <code><span style="background-color: PaleGreen">(</span>x<span style="background-color: PaleGreen">)</span></code>理想输出: <code><span style="background-color: PaleGreen">(</span>x<span style="background-color: PaleGreen">)</span></code>
理想输出: <code><span style="background-color: PaleGreen">(</span>x<span style="background-color: PaleGreen">)</span></code>
This is tricky because `x` has changed its depth in the tree, but `x`
itself is unchanged.
这个是十分棘手,因为`x`已经改变了它在树中的深度,但`x`本身却未发生改变。
Not all tree diff algorithms handle this case. It is also challenging
to display this case clearly: we want to highlight the changed
delimiters, but not their content. This is challenging in larger
expressions.
并不是所有的树形差异分析算法可以处理这个例子。同时仔细地展示出范例是具有挑战性的:我们希望去高亮出已改变的定界符,但不是他们的内容。这同样在更大的表达式是具有挑战性的。
## Changing Delimiters
## 改变定界符
```
;; Before
@ -35,10 +30,9 @@ expressions.
[x]
```
As with the wrapping case, we want to highlight the delimiters rather
than the `x`.
正如这个包裹的例子,我们想要去高亮出定界符而不是`x`这个内容。
## Expanding Delimiters
## 拓展定界符
```
;; Before
@ -48,12 +42,11 @@ than the `x`.
(x y)
```
Desired output: <code>(x <span style="background-color: PaleGreen">y</span>)</code>
理想输出:<code>(x <span style="background-color: PaleGreen">y</span>)</code>
In this case, we want to highlight `y`. Highlighting the delimiters
could make `x` look changed.
在这个例子下,我们想要去高亮`y`。高亮显示定界符的话可能会让`x`看起来有所变化。
## Contracting Delimiters
## 缩小定界符
```
;; Before
@ -63,9 +56,9 @@ could make `x` look changed.
(x) y
```
This should be highlighted similar to the expanding delimiter case.
这应该与扩展定界符的情况类似,去高亮定界符。
## Disconnected Delimiters
## 使定界符不连贯
```
;; Before
@ -75,13 +68,12 @@ This should be highlighted similar to the expanding delimiter case.
(foo (novel) (bar))
```
Desired result: <code>(foo <span style="background-color:PaleGreen">(novel)</span> (bar)</code>
理想输出:<code>(foo <span style="background-color:PaleGreen">(novel)</span> (bar)</code>
It is easy to end up with
<code>(foo (<span style="background-color:PaleGreen">novel</span>) <span style="background-color:PaleGreen">(</span>bar<span style="background-color:PaleGreen">)</span>)</code>,
where a later pair of delimiters are chosen.
很容易会变成:<code>(foo (<span style="background-color:PaleGreen">novel</span>) <span style="background-color:PaleGreen">(</span>bar<span style="background-color:PaleGreen">)</span>)</code>,
其中后一组的定界符会被选中。
## Rewrapping Large Nodes
## 重新组织大节点
```
;; Before
@ -92,14 +84,10 @@ where a later pair of delimiters are chosen.
([[foo]] x y)
```
We want to highlight `[[foo]]` being moved inside the
parentheses. However, a naive syntax differ prefers consider a removal
of `()` in the before and an addition of `()` in the after to be more
minimal diff.
我们想高亮`[[foo]]`被移到括号内了。然而,一个简单的语法差异者更倾向于认为在前面删除`()`,在后面增加`()`,是最小的差异表现。
(见[issue 44](https://github.com/Wilfred/difftastic/issues/44)。)
(Reported as [issue 44](https://github.com/Wilfred/difftastic/issues/44).)
## Reordering Within A List
## 在列表内重新排列
```
;; Before
@ -109,11 +97,11 @@ minimal diff.
(y x)
```
Desired result: <code>(<span style="background-color: PaleGreen">y</span> <span style="background-color: PaleGreen">x</span>)</code>
理想输出:<code>(<span style="background-color: PaleGreen">y</span> <span style="background-color: PaleGreen">x</span>)</code>
We want to highlight the list contents and not the delimiters.
我们想突出显示列表的内容,而不是定界符。
## Middle Insertions
## 中间插入
```
// Before
@ -123,19 +111,15 @@ foo(bar(123))
foo(extra(bar(123)))
```
Desired result: <code>foo(<span style="background-color: PaleGreen">extra(</span>bar(123)<span style="background-color: PaleGreen">)</span>)</code>
理想输出:<code>foo(<span style="background-color: PaleGreen">extra(</span>bar(123)<span style="background-color: PaleGreen">)</span>)</code>
We want to consider both `foo` and `bar` to be unchanged. This case is
challenging for diffing algorithms that do a bottom-up then top-down
matching of trees.
我们想把`foo`和`bar`都看作是不变的。这种情况对于对树进行自下而上然后自上而下匹配的衍合算法来说是具有挑战性的。
## Sliders (Flat)
## 滑块(平移)
Sliders are a common problem in text based diffs, where lines are
matched in a confusing way.
在基于文本的差异分析中,滑块是一个常见的问题,即行与行之间以混乱的方式进行匹配。
They typically look like this. The diff has to arbitrarily choose a
line containing delimiter, and it chooses the wrong one.
它们通常看起来像这样。差异分析必须任意选择一个包含分隔符的行,但它选择了错误的行。
```
+ }
@ -144,10 +128,9 @@ line containing delimiter, and it chooses the wrong one.
}
```
git-diff has some heuristics to reduce the risk of this (e.g. the
"patience diff"), but it can still occur.
git-diff有一些启发式方法来减少这种风险比如说"patience diff"),但这个问题仍然可能发生。
There's a similar problem in tree diffs.
接下来是一个在树状差异分析时常见的问题。
```
;; Before
@ -160,12 +143,9 @@ A B
C D
```
Ideally we'd prefer marking contiguous nodes as novel, so we highlight
`A B` rather than `B\nA`. From the perspective of a
longest-common-subsequence algorithm, these two choices are
equivalent.
理想情况下,我们更愿意将连续的节点标记为新的,所以我们强调`A B`而不是`B/nA`。从最长公序算法的角度来看,这两种选择是等价的。
## Sliders (Nested)
## 滑块(嵌套)
```
// Before
@ -175,14 +155,12 @@ old1(old2)
old1(new1(old2))
```
Should this be <code>old1(<span style="background-color: PaleGreen">new1(</span>old2<span style="background-color: PaleGreen">)</span>)</code> or
这个应该是 <code>old1(<span style="background-color: PaleGreen">new1(</span>old2<span style="background-color: PaleGreen">)</span>)</code> 还是
<code>old1<span style="background-color: PaleGreen">(new1</span>(old2)<span style="background-color: PaleGreen">)</span></code>?
The correct answer depends on the language. Most languages want to
prefer the inner delimiter, whereas Lisps and JSON prefer the outer
delimiter.
正确的答案是取决于语言。大多数语言希望优先使用内部分隔符而Lisps和JSON则喜欢使用外部分隔符。
## Minimising Depth Changes
## 最小化深度改变
```
// Before
@ -195,10 +173,10 @@ foo(456);
foo(789);
```
Do we consider `foo(123)` or `foo(456)` to match with `foo(789)`?
Difftastic prefers `foo(456)` by preferring nodes at the same nesting depth.
我们认为`foo(123)`还是`foo(456)`与`foo(789)`匹配?
Difftastic优先考虑`foo(456)`,通过优先考虑相同嵌套深度的节点。
## Replacements With Minor Similarities
## 有少量相似处的替代做法
```
// Before
@ -208,17 +186,11 @@ function foo(x) { return x + 1; }
function bar(y) { baz(y); }
```
In this example, we've deleted a function and written a completely
different one. A tree-based diff could match up the `function` and the
outer delimiters, resulting in a confusing display showing lots of
small changes.
在这个例子中,我们删除了一个函数,写了一个完全不同的函数。基于树状结构的差异可能会匹配 "函数 "和外部定界符,从而导致显示出许多令人困惑的小的变化。
As with sliders, the replacement problem can also occur in textual
line-based diffs. Line-diffs struggle if there are a small number of
common lines. The more precise, granular behaviour of tree diffs makes
this problem much more common though.
与滑块一样,替换问题也可能发生在基于文本的行差中。如果有少量的共同行,行差就会陷入困境。但树形差分的更精确、更细化的行为使这个问题更加普遍。
## Matching Substrings In Comments
## 匹配注释中的子字符串
```
// Before
@ -230,11 +202,9 @@ foobar();
foobaz();
```
`foobar` and `foobaz` are completely different, and their common
prefix `fooba` should not be matched up. However, matching common
prefixes or suffixes for comments is desirable.
`foobar`和`foobaz`是完全不同的,它们的共同前缀`fooba`不应该被匹配起来。然而,为注释匹配共同的前缀或后缀是可取的。
## Multiline Comments
## 多行注释
```
// Before
@ -248,12 +218,11 @@ if (x) {
}
```
The inner content of these two comments is technically different. We
want to treat them as identical however.
这两个注释的内部内容在技术上是不同的。然而,我们想把它们当作是相同的。
## Reflowing Doc Comments
## 文档注释的换行
Block comments have prefixes that aren't meaningful.
块状评论的前缀并没有什么意义。
```
// Before
@ -265,11 +234,9 @@ Block comments have prefixes that aren't meaningful.
* jumps over the lazy dog. */
```
The inner content has changed from `jumps * over` to `immediately *
jumps over`. However, the `*` is decorative and we don't care that
it's moved.
里面的内容已经从 `jumps * over`变成了`immediately * jumps over`。然而,`*`是装饰性的,我们并不关心它的移动。
## Small Changes To Large Strings
## 长字符串的小变化
```
// Before
@ -283,19 +250,13 @@ with lots of NOVEL words about
lots of stuff."""
```
It would be correct to highlight the entire string literal as being
removed and replaced with a new string literal. However, this makes it
hard to see what's actually changed.
将整个字符串字头突出显示为被删除并被一个新的字符串字头取代是正确的。然而,这让人很难看出实际改变了什么。
It's clear that variable names should be treated atomically, and
comments are safe to show subword changes. It's not clear how to
handle a small change in a 20 line string literal.
很明显,变量名应该被原子化处理,并且 注释是安全的可以显示子字的变化。但不清楚如何处理一个20行字符串字面的小变化。
It's tempting to split strings on spaces and diff that, but users
still want to know when whitespace changes inside strings. `" "` and
`" "` are not the same.
在空格上分割字符串并加以区别是很具有挑战的,但用户仍然想知道字符串内部的空白何时改变。`" "`和`" "`是不一样的。
## Autoformatter Punctuation
## 自动格式化工具的拼写
```
// Before
@ -309,18 +270,13 @@ foo(
);
```
Autoformatters (e.g. [prettier](https://prettier.io/)) will sometimes
add or remove punctuation when formatting. Commas and parentheses are
the most common.
自动格式化(例如[prettier](https://prettier.io/))有时会在格式化时添加或删除标点符号。逗号和括号是最常见的。
Syntactic diffing can ignore whitespace changes, but it has to assume
punctuation is meaningful. This can lead to punctuation changes being
highlighted, which may be quite far from the relevant content change.
语法差异可以忽略空白处的变化,但它必须假设标点符号是有意义的。这可能导致标点符号的变化被突出显示,而这可能与相关的内容变化相差甚远。
## Novel Blank Lines
## 新空行
Blank lines are challenging for syntactic diffs. We are comparing
syntactic tokens, so we don't see blank lines.
空行对于句法差异来说是一种挑战。我们要比较的是语法标记,所以我们不会看到空行。
```
// Before
@ -333,11 +289,9 @@ A
B
```
Generally we want syntactic diffing to ignore blank lines. In this
first example, this should show no changes.
一般来说,我们希望语法差异能够忽略空行。在第一个例子中,这应该不会显示任何变化。
This is occasionally problematic, as it can hide accidental code
reformatting.
这有时是有问题的,因为它可以会意外地隐藏被重新格式化地代码。
```
// Before
@ -352,8 +306,7 @@ Y
B
```
In this second example, we've inserted X and Y and a blank line. We
want to highlight the blank line as an addition.
在这第二个例子中我们插入了X和Y以及一个空行。我们想把空行作为一个补充来高亮。
```
// Before
@ -368,15 +321,10 @@ X
B
```
In this third example, the syntactic diffing only sees an
addition. From the user's perspective, there has also been a removal
of two blank lines.
在这第三个例子中,语法上的差异只看到了一个增加。从用户的角度来看,也有两个空行被删除。
## Invalid Syntax
## 无效语法
There's no guarantee that the input we're given is valid syntax. Even
if the code is valid, it might use syntax that isn't supported by the
parser.
我们不能保证我们得到的输入是有效的语法。即使代码是有效的,它也可能使用解析器不支持的语法。
Tree-sitter provided explicit error nodes, and difftastic treats them
as atoms so it can run the same tree diff algorithm regardless.
Tree-sitter可以显示出显式的错误节点而Difftastic会将它们视为原子因此它可以不顾一切地运行相同的树形差异算法。

@ -1,31 +1,26 @@
# Usage使用方法
# 使用方法
## Diffing Files差异比较文件
## 差异比较文件
```
$ difft sample_files/before.js sample_files/after.js
```
## Diffing Directories差异比较文件夹
## 差异比较文件夹
```
$ difft sample_files/dir_before/ sample_files/dir_after/
```
Difftastic will recursively walk the two directories, diffing files
with the same name.Difftastic会递归地浏览这两个文件对同名的文件进行差异分析。
Difftastic会递归地浏览这两个文件对同名的文件进行差异分析。
The `--skip-unchanged` option is useful when diffing directories that
contain many unchanged files.当对比的文件夹之间许多未改变的文件时,`--skip-unchanged`选项将会十分有用。
当对比的文件夹之间许多未改变的文件时,`--skip-unchanged`选项将会十分有用。
## Language Detection语言检测
## 语言检测
Difftastic guesses the language used based on the file extension, file
name, and the contents of the first lines.Difftastic根据文件的扩展名、文件名和第一行的内容来猜测所使用的语言。
Difftastic根据文件的扩展名、文件名和第一行的内容来猜测所使用的语言。
You can override the language detection by passing the `--language`
option. Difftastic will treat input files as if they had that
extension, and ignore other language detection heuristics.你可以通过`--language`选项来覆盖语言检测。如果输入的文件有所设定的后缀Difftastic将会处理它们并且忽略其他语言。
你可以通过`--language`选项来覆盖语言检测。如果输入的文件有所设定的后缀Difftastic将会处理它们并且忽略其他语言。
```
@ -34,11 +29,8 @@ $ difft --language cpp before.c after.c
## Options选项
Difftastic includes a range of configuration CLI options, see `difft --help` for the full list.Difftastic包括一系列的命令行选项见`difft --help`获得完整列表。
Difftastic包括一系列的命令行选项见`difft --help`获得完整列表。
Difftastic can also be configured with environment variables. These
are also visible in `--help`.Difftastic也可以用环境变量进行配置。这些可以在`--help`中看到。
Difftastic也可以用环境变量进行配置。这些可以在`--help`中看到。
For example, `DFT_BACKGROUND=light` is equivalent to
`--background=light`. This is useful when using VCS tools like git,
where you are not invoking the `difft` binary directly.例如,`DFT_BACKGROUND=light`就相当于`--background=light`。这在使用VCS工具例如git的时候会很有用因为此时无法直接调用`difft`二进制文件。
例如,`DFT_BACKGROUND=light`就相当于`--background=light`。这在使用VCS工具例如git的时候会很有用因为此时无法直接调用`difft`二进制文件。