cli: make diff editor configurable

This patch adds a simple `ui.diff-editor` config, which defaults to
`meld`. This fixes issue #10.
This commit is contained in:
Martin von Zweigbergk 2021-05-31 09:05:16 -07:00
parent 38a3462d4e
commit 03ea8779df
3 changed files with 25 additions and 9 deletions

View file

@ -426,9 +426,15 @@ try `jj l --at-op=401652a2f61e` but use the hash from your own `jj op log`.
You have already seen how `jj squash` can combine the changes from two commits You have already seen how `jj squash` can combine the changes from two commits
into one. There are several other commands for changing the contents of existing into one. There are several other commands for changing the contents of existing
commits. These commands require you to have `meld` installed for now commits. These commands assume that you have `meld` installed. If you prefer
(https://github.com/martinvonz/jj/issues/10). We'll need some more complex `vimdiff`, add this to your `~/.jjconfig` file:
content to test these commands, so let's create a few more commits: ```
[ui]
diff-editor = "vimdiff"
```
We'll need some more complex content to test these commands, so let's create a
few more commits:
```shell script ```shell script
$ jj co origin/main $ jj co origin/main
Working copy now at: 61b0efa09dbe Working copy now at: 61b0efa09dbe

View file

@ -1643,7 +1643,7 @@ fn cmd_squash(
short_commit_description(&parent) short_commit_description(&parent)
); );
new_parent_tree_id = new_parent_tree_id =
crate::diff_edit::edit_diff(&parent.tree(), &commit.tree(), &instructions)?; crate::diff_edit::edit_diff(ui, &parent.tree(), &commit.tree(), &instructions)?;
if &new_parent_tree_id == parent.tree().id() { if &new_parent_tree_id == parent.tree().id() {
return Err(CommandError::UserError(String::from("No changes selected"))); return Err(CommandError::UserError(String::from("No changes selected")));
} }
@ -1702,7 +1702,7 @@ fn cmd_unsquash(
short_commit_description(&commit) short_commit_description(&commit)
); );
new_parent_tree_id = new_parent_tree_id =
crate::diff_edit::edit_diff(&parent_base_tree, &parent.tree(), &instructions)?; crate::diff_edit::edit_diff(ui, &parent_base_tree, &parent.tree(), &instructions)?;
if &new_parent_tree_id == parent_base_tree.id() { if &new_parent_tree_id == parent_base_tree.id() {
return Err(CommandError::UserError(String::from("No changes selected"))); return Err(CommandError::UserError(String::from("No changes selected")));
} }
@ -1775,7 +1775,7 @@ fn cmd_restore(
short_commit_description(&to_commit) short_commit_description(&to_commit)
); );
tree_id = tree_id =
crate::diff_edit::edit_diff(&from_commit.tree(), &to_commit.tree(), &instructions)?; crate::diff_edit::edit_diff(ui, &from_commit.tree(), &to_commit.tree(), &instructions)?;
} else if sub_matches.is_present("paths") { } else if sub_matches.is_present("paths") {
let paths = sub_matches.values_of("paths").unwrap(); let paths = sub_matches.values_of("paths").unwrap();
let mut tree_builder = repo.store().tree_builder(to_commit.tree().id().clone()); let mut tree_builder = repo.store().tree_builder(to_commit.tree().id().clone());
@ -1830,7 +1830,7 @@ fn cmd_edit(
don't make any changes, then the operation will be aborted.\n", don't make any changes, then the operation will be aborted.\n",
short_commit_description(&commit) short_commit_description(&commit)
); );
let tree_id = crate::diff_edit::edit_diff(&base_tree, &commit.tree(), &instructions)?; let tree_id = crate::diff_edit::edit_diff(ui, &base_tree, &commit.tree(), &instructions)?;
if &tree_id == commit.tree().id() { if &tree_id == commit.tree().id() {
ui.write("Nothing changed.\n")?; ui.write("Nothing changed.\n")?;
} else { } else {
@ -1867,7 +1867,7 @@ fn cmd_split(
any changes, then the operation will be aborted.\n", any changes, then the operation will be aborted.\n",
short_commit_description(&commit) short_commit_description(&commit)
); );
let tree_id = crate::diff_edit::edit_diff(&base_tree, &commit.tree(), &instructions)?; let tree_id = crate::diff_edit::edit_diff(ui, &base_tree, &commit.tree(), &instructions)?;
if &tree_id == commit.tree().id() { if &tree_id == commit.tree().id() {
ui.write("Nothing changed.\n")?; ui.write("Nothing changed.\n")?;
} else { } else {

View file

@ -28,6 +28,8 @@ use jujutsu_lib::working_copy::{CheckoutError, TreeState};
use tempfile::tempdir; use tempfile::tempdir;
use thiserror::Error; use thiserror::Error;
use crate::ui::Ui;
#[derive(Debug, Error, PartialEq, Eq)] #[derive(Debug, Error, PartialEq, Eq)]
pub enum DiffEditError { pub enum DiffEditError {
#[error("The diff tool exited with a non-zero code")] #[error("The diff tool exited with a non-zero code")]
@ -95,6 +97,7 @@ fn set_readonly_recursively(path: &Path) {
} }
pub fn edit_diff( pub fn edit_diff(
ui: &mut Ui,
left_tree: &Tree, left_tree: &Tree,
right_tree: &Tree, right_tree: &Tree,
instructions: &str, instructions: &str,
@ -145,8 +148,15 @@ pub fn edit_diff(
file.write_all(instructions.as_bytes()).unwrap(); file.write_all(instructions.as_bytes()).unwrap();
} }
// TODO: Make this configuration have a table of possible editors and detect the
// best one here.
let editor_binary = ui
.settings()
.config()
.get_str("ui.diff-editor")
.unwrap_or_else(|_| "meld".to_string());
// Start a diff editor on the two directories. // Start a diff editor on the two directories.
let exit_status = Command::new("meld") let exit_status = Command::new(&editor_binary)
.arg(&left_wc_dir) .arg(&left_wc_dir)
.arg(&right_wc_dir) .arg(&right_wc_dir)
.status() .status()