#diff #editor #ui #view #editing #run #merge

程序+库 diffedit3

在3窗格视图中编辑差异

6个版本 (3个破坏性版本)

0.4.0 2024年5月6日
0.3.0 2024年4月11日
0.2.0 2024年4月5日
0.1.2 2024年3月19日

#644 in 命令行工具

Apache-2.0

600KB
15K SLoC

JavaScript 14K SLoC // 0.0% comments Rust 1K SLoC // 0.1% comments

Logo Diffedit3

概述

该仓库中的工具是一个用于在三个窗格视图中编辑差异的用户界面。它旨在与jj一起使用,其核心希望成为jj的一部分。

有关diffedit3用途的解释,请参阅下面,以了解对不熟悉jj的人。

Screenshot of v. 0.1.2

当在实验性3窗格差异编辑模式下使用时,diffedit3的界面与Meld非常相似。Meld的界面更加完善,所以当您能够轻松使用Meld时,应该首选Meld。然而,只要可以访问网络浏览器(例如通过SSH端口转发、通过WSL等),diffedit3就可以在Meld难以安装或运行时使用。

为了尽可能便携,diffedit3运行一个本地HTTP服务器。UI在您的浏览器中运行,地址为http://127.0.0.1:8080,与Jupyter非常相似。UI的大部分内容都是围绕CodeMirror编辑器/库的包装。有关更多信息,请参阅下面

安装diffedit3

有几种安装diffedit3的方法。

  • 您可以从该仓库的发布页面获取diffedit3。下载适用于您系统的存档,解压缩它,并将可执行文件放入您的PATH。

  • 如果您已安装 Rust,可以使用以下命令进行安装 cargo install diffedit3 --locked

  • 如果您有 cargo binstall,则可以执行以下命令:cargo binstall diffedit3。然后建议安装并使用 cargo-update 来更新 diffedit3cargo-binstall

获取二进制文件后,您可以通过运行 diffedit3 --demo 来测试它是否正常工作。

关于不支持的 Tauri 二进制文件说明

发布页面还包含名为 "unsupported-tauri-gui" 的二进制文件,其中包含一个 diffedit3-gui 可执行文件。

如果您更喜欢基于 Tauri 的 GUI 应用程序而不是 Jupyter 风格的网页应用程序,可以使用这些文件与常规的 diffedit3 可执行文件互换。如果您只想试用,请运行 diffedit3-gui --demo

但是,diffedit3-gui 的支持非常有限,并且存在已知错误(主要是与快捷键相关),作者不确定如何修复。您还需要手动配置 jj 来使用它。

使用 diffedit3jj

对于 jj 0.18+,diffedit3 应该预先配置。您只需在您的 jj 配置 中设置 ui.diff-editor="diffedit3" 即可。您也可以使用 --tool diffedit3 参数调用 jj 命令。如果 diffedit3 可执行文件不在您的 PATH 中,您还可以将 merge-tools.diffedit3.program 设置为可执行文件路径。(待办事项:链接到文档,并在 PR 包含文档和配置后删除此待办事项。)

要使用较旧版本的 jjdiffedit3,请将以下片段添加到您的 jj 配置

[ui]
diff-editor = "diffedit3"

[merge-tools.diffedit3]
# Replace `program` with the full path to the
# binary if it is not in your PATH.
program = "diffedit3"  
edit-args = ["$left", "$right", "$output"]

然后,该工具将用于 jj split 和许多其他命令。

diffedit3 的潜在用途

diffedit3 向用户显示两个或三个目录之间的三路比较。用户可以编辑中间面板,创建他们喜欢的任何中间数据版本。此界面并不新颖,Meld 可以以相同的方式进行配置。然而,我认为它应该更为人所知,并得到更广泛的应用。

如果您不熟悉在 jj 中使用此功能的各种操作,最明显的用例是

  • 拆分提交,正如我在功能请求中详细解释的那样

  • 作为 git add -p 的交互式版本。目前尚未实现,但 diffedit3 可以设置在左侧面板显示 HEAD 的状态,在右侧面板显示工作副本的状态,并允许用户在中间面板编辑暂存区域。

    这样,您可以轻松地暂存文件的某些部分,或者您可以决定稍微修改您从工作副本中暂存的变化。这也会是安全的:您所做的一切都不会影响工作副本或 HEAD 提交,直到您明确地提交暂存的变化或从暂存的变化中恢复工作副本。

"交互式 git add -p" 可以通过某种脚本实现,该脚本将首先在磁盘上的三个目录中实例化库的三个版本(可能限制为修改的文件)。在 diffedit3 完成之后,脚本必须处理输出并告诉 Git 将该输出作为暂存区域的新内容。这类似于 StackOverflow 问题

或者,使用类似 gixgit2 的工具创建一个专用工具可能更容易,假设它们提供了轻松修改暂存区域的方法。

关于实现和替代方案的建议

目前,代码只是概念验证级别的。我试图让它足够实用,以便人们可以快速了解这个工具。

这个工具的大部分是网络应用程序,它是对 CodeMirror 5 合并插件 的薄包装。还有一些 Rust 代码用于 IO 和设置本地服务器(或设置 Tauri)。

CodeMirror 5 是过时的软件,其中存在不太可能修复的 bug(特别是在合并插件中)。希望我们最终会转向使用其他软件,但目前它具有这个工具非常方便的功能集。

我们可以考虑的 CodeMirror 5 的替代方案

  • CodeMirror 6 有一个 合并插件,但它目前只支持双面板差异。我发起了一个 Discourse 讨论,请求三面板差异的功能。

    目前还没有回应,但根据其他讨论,CodeMirror 的作者愿意被雇佣为顾问以实现新功能。

  • mismerge 很有前途。目前它缺少一些功能(请参阅仓库中的问题)。

CodeMirror5 的一些限制示例

  • 在更改是否换行时省略未更改的块时存在 bug。
  • 差异质量远非完美
  • 不支持暗黑主题
  • 难以区分空白行和丢失的行。
  • 不知道它何时会被遗弃和不再受支持。
  • 很难使其与现代 Web 框架一起工作。

潜在的未来功能和它们的替代方案

具有三面板 diffedit 视图的 TUI 工具

这会很棒 :)

应该能够实现Vim和可能Emacs支持类似于diffedit3提供的接口。我不了解任何现成的用于目录三向差分编辑的选项。对于单个文件的三种版本(与目录相对),Vim今天已经可以做到这一点。

即使有人编写或改进了Vim插件来完成这项工作(这将非常棒!),也仍然需要这样的工具,而不需要用户学习Vim或Emacs的方式。

在4窗格视图中解决合并冲突

一个显示冲突基础、冲突的两边以及用户可以解决冲突的输出窗格的用户界面将是diffedit3的一个理想的补充。这可能是件苦差事。我不知道是否有现成的JS库实现这样的UI。另一方面,有许多现有的、经过不同程度润色的替代程序可以做到这一点。

作为jj的替代方案,我建议设置kdiff3二进制文件)或VS Code作为合并工具。后者可以用于在远程计算机上合并文件,使用其远程开发模式。jj支持默认解决冲突。

还有很多其他替代方案,包括像Araxis/Beyond Compare这样的付费软件。

UI更改,例如使用标签视图而不是滚动,更改编辑器的大小...

欢迎补丁:()。任何此类更改都存在遇到CodeMirror5合并插件错误的危险,所以请小心检查您的更改是否正常工作。

自动换行,按钮从左右窗格获取所有更改

这是计划中的。这需要销毁CodeMirror小部件并创建一个新的(为了避开CodeMirror5的错误)。

从源代码构建diffedit3

对于本地服务器版本,运行cargo build --release就足够了。这假设webapp/dist中的编译JavaScript是最新的,因此不需要安装npm

对于GUI(Tauri)版本,步骤如下

  1. 安装Rust
  2. 安装cargo-tauri CLI(待办:更好的解释)。不要使用node Tauri CLI;它似乎不适用于该项目以Rust为重点的目录结构。
  3. 安装node/npm。进入backend-tauri目录。
  4. 运行npm install(只需运行一次)。
  5. 运行cargo tauri build。不要使用常规的cargo build,因为它会产生损坏的二进制文件。

在这两种情况下,二进制文件将在target/release目录中生成。

开发

关于分支的说明

dev分支的提交历史很混乱。分支可能随时被强制推送。

预v0.0.1的提交也很混乱,位于v0.0.1-ish分支上。

先决条件

选项1:使用backend-local-server

  1. (如果您打算接触HTML/CSS/JS)安装 node/npm,运行 npm install

  2. (如果您接触HTML/CSS/JS)在单独的终端中运行 npm run watch。这将在您更改 webapp/ 中的文件时自动更新 webapp//dist

  3. 使用 cargo run -p backend-local-server -- --demo 来运行应用程序。如果接触webapp,记得在运行/构建应用程序之前手动确保 npm run watch 没有显示任何错误。

  4. (推荐)设置您的编辑器,使用[Prettier]和 cargo +nightly fmt 在保存时格式化。对于VS Code,您可以安装https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscodehttps://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer,然后添加以下内容到您的 workspace(或全局) settings.json

    "[rust]": {
        "editor.formatOnSave": true
    },
    "[typescript]": {
        "editor.formatOnSave": true
    },
    "[html]": {
        "editor.formatOnSave": true
    },
    "[yaml]": {
        "editor.formatOnSave": true
    },
    "[github-actions-workflow]": {
        "editor.formatOnSave": true
    },
    

    运行 npm run build 也会通过 npm run format 运行 prettier

选项2:使用 backend-tauri

  1. 遵循GUI/Tauri版本的"构建"步骤。您可以跳过最后的构建步骤。
  2. 运行 cargo tauri dev -- -- --demo(注意两个 --)。这将自动刷新应用程序以使用从 webapp/(而不是 `webapp/dist`) 中获取的最新版本webapp(在开发模式下)。

中期待办事项

允许忽略空格

似乎不支持CodeMirror

参见下面的"更好的合并"。错误的合并似乎支持这一点。

跟踪重新加载时打开的文件标签页

需要定期发送数据到服务器。

定期检查本地服务器是否存活

这主要需要一个UI。服务器可以有一个 /api/ping 路由。我们可以验证它是否是同时启动webapp的同服务器,尽管更好的做法可能是进行更通用的检查,即检查磁盘上的目录状态是否符合预期(参见下一条)。

警告未保存的更改,更漂亮的保存按钮

跟踪自上次保存以来内容是否已更改。在这种情况下,将保存按钮变灰。(这意味着在保存时,我们需要跟踪最后一次成功保存的状态和我们要保存的状态)。告诉用户最后一次成功保存发生的时间。

更好的合并

简单:检查配置diff库参数。

困难:使用更新的库在Rust中进行计算。这需要一个可以导入此类diff的UI。《mismerge》很接近。

按文件保存

简单部分:不要覆盖未更改的文件

困难:每个文件都有自己的保存按钮,可能还有一个总的保存按钮。

短期待办事项和已知问题

如果右侧的文件被删除,工具在保存时会用空文件替代,这是不应该发生的。

对于Tauri应用(diffedit3-gui),Ctrl-C/Cmd-C复制似乎并不总是有效。使用Ctrl-Up和Cmd-Up切换到上一个差异功能也不起作用。Web应用diffedit3版本不受影响

切换选项,如换行、折叠相似区域或右侧面板,会丢失CodeMirror视口和选择。

这是因为编辑器需要重新创建以避免CodeMirror5的bug。光标位置被保留。

当窗口较窄时,固定视图菜单的滚动条看起来很丑。

这与事实有关,即<details>似乎不支持display: flex。解决方案是将<details>替换为自定义实现。

依赖项

~17–28MB
~408K SLoC