jj resolve --list: make output aligned

If all file names are short enough, this will align the conflict
description at 4 spaces past the longest file name, as follows.

```
src/templater.rs            2-sided conflict
src/templater_parsers.rs    2-sided conflict
```

If there is a long file name, conflict descriptions will either start
or column 35 or one space from a file name, whichever is later.

Previously, a single tab was used to separate file name from conflict
description. This didn't look as nice as I hoped when multiple files
are involved. I also don't think `jj` generally uses tabs in output.
The tab uncovered a bug in a watcher program I was using.
This commit is contained in:
Ilya Grigoriev 2023-01-07 11:09:55 -08:00
parent 5b1b35cbfe
commit 9a3329ee25
2 changed files with 41 additions and 24 deletions

View file

@ -2467,7 +2467,18 @@ fn print_conflicted_paths(
formatter: &mut dyn Formatter,
workspace_command: &WorkspaceCommandHelper,
) -> Result<(), CommandError> {
for (repo_path, conflict_id) in conflicts.iter() {
let formatted_paths = conflicts
.iter()
.map(|(path, _id)| workspace_command.format_file_path(path))
.collect_vec();
let max_path_len = formatted_paths.iter().map(|p| p.len()).max().unwrap_or(0);
let formatted_paths = formatted_paths
.into_iter()
.map(|p| format!("{:width$}", p, width = max_path_len.min(32) + 3));
for ((repo_path, conflict_id), formatted_path) in
std::iter::zip(conflicts.iter(), formatted_paths)
{
let conflict = tree.store().read_conflict(repo_path, conflict_id)?;
let n_adds = conflict.adds.len();
let sides = n_adds.max(conflict.removes.len() + 1);
@ -2506,11 +2517,7 @@ fn print_conflicted_paths(
);
}
write!(
formatter,
"{}\t",
&workspace_command.format_file_path(repo_path)
)?;
write!(formatter, "{formatted_path} ",)?;
formatter.with_label("conflict_description", |formatter| {
let print_pair = |formatter: &mut dyn Formatter, (text, label): &(String, &str)| {
formatter.with_label(label, |fmt| fmt.write_str(text))

View file

@ -63,7 +63,9 @@ fn test_resolution() {
o
"###);
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list"]),
@"file 2-sided conflict");
@r###"
file 2-sided conflict
"###);
insta::assert_snapshot!(
std::fs::read_to_string(repo_path.join("file")).unwrap()
, @r###"
@ -182,7 +184,7 @@ conflict
Working copy now at: 0bb40c908c8b conflict
Added 0 files, modified 1 files, removed 0 files
After this operation, some files at this revision still have conflicts:
file 2-sided conflict
file 2-sided conflict
"###);
insta::assert_snapshot!(
std::fs::read_to_string(test_env.env_root().join("editor2")).unwrap(), @r###"
@ -207,7 +209,9 @@ conflict
7 7: >>>>>>>
"###);
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list"]),
@"file 2-sided conflict");
@r###"
file 2-sided conflict
"###);
// Check that if merge tool leaves conflict markers in output file but
// `merge-tool-edits-conflict-markers=false` or is not specified,
@ -306,7 +310,9 @@ fn test_normal_conflict_input_files() {
o
"###);
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list"]),
@"file 2-sided conflict");
@r###"
file 2-sided conflict
"###);
insta::assert_snapshot!(
std::fs::read_to_string(repo_path.join("file")).unwrap()
, @r###"
@ -345,7 +351,9 @@ fn test_baseless_conflict_input_files() {
o
"###);
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list"]),
@"file 2-sided conflict");
@r###"
file 2-sided conflict
"###);
insta::assert_snapshot!(
std::fs::read_to_string(repo_path.join("file")).unwrap()
, @r###"
@ -374,11 +382,13 @@ fn test_too_many_parents() {
create_commit(&test_env, &repo_path, "c", &["base"], &[("file", "c\n")]);
create_commit(&test_env, &repo_path, "conflict", &["a", "b", "c"], &[]);
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list"]),
@"file 3-sided conflict");
@r###"
file 3-sided conflict
"###);
// Test warning color
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list", "--color=always"]),
@r###"
file 3-sided conflict
file 3-sided conflict
"###);
let error = test_env.jj_cmd_failure(&repo_path, &["resolve"]);
@ -411,7 +421,7 @@ fn test_edit_delete_conflict_input_files() {
"###);
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list"]),
@r###"
file 2-sided conflict including 1 deletion
file 2-sided conflict including 1 deletion
"###);
insta::assert_snapshot!(
std::fs::read_to_string(repo_path.join("file")).unwrap()
@ -456,7 +466,7 @@ fn test_file_vs_dir() {
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list"]),
@r###"
file 2-sided conflict including a directory
file 2-sided conflict including a directory
"###);
let error = test_env.jj_cmd_failure(&repo_path, &["resolve"]);
insta::assert_snapshot!(error, @r###"
@ -505,12 +515,12 @@ fn test_description_with_dir_and_deletion() {
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list"]),
@r###"
file 3-sided conflict including 1 deletion and a directory
file 3-sided conflict including 1 deletion and a directory
"###);
// Test warning color. The deletion is fine, so it's not highlighted
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list", "--color=always"]),
@r###"
file 3-sided conflict including 1 deletion and a directory
file 3-sided conflict including 1 deletion and a directory
"###);
let error = test_env.jj_cmd_failure(&repo_path, &["resolve"]);
insta::assert_snapshot!(error, @r###"
@ -604,14 +614,14 @@ fn test_multiple_conflicts() {
"###);
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list"]),
@r###"
another_file 2-sided conflict
this_file_has_a_very_long_name_to_test_padding 2-sided conflict
another_file 2-sided conflict
this_file_has_a_very_long_name_to_test_padding 2-sided conflict
"###);
// Test colors
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list", "--color=always"]),
@r###"
another_file 2-sided conflict
this_file_has_a_very_long_name_to_test_padding 2-sided conflict
another_file 2-sided conflict
this_file_has_a_very_long_name_to_test_padding 2-sided conflict
"###);
let editor_script = test_env.set_up_fake_editor();
@ -623,7 +633,7 @@ fn test_multiple_conflicts() {
Working copy now at: 07feb084c0d2 conflict
Added 0 files, modified 1 files, removed 0 files
After this operation, some files at this revision still have conflicts:
this_file_has_a_very_long_name_to_test_padding 2-sided conflict
this_file_has_a_very_long_name_to_test_padding 2-sided conflict
"###);
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["diff"]),
@r###"
@ -638,7 +648,7 @@ fn test_multiple_conflicts() {
"###);
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list"]),
@r###"
this_file_has_a_very_long_name_to_test_padding 2-sided conflict
this_file_has_a_very_long_name_to_test_padding 2-sided conflict
"###);
// Repeat the above with the `--quiet` option.
@ -674,7 +684,7 @@ fn test_multiple_conflicts() {
"###);
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["resolve", "--list"]),
@r###"
this_file_has_a_very_long_name_to_test_padding 2-sided conflict
this_file_has_a_very_long_name_to_test_padding 2-sided conflict
"###);
std::fs::write(
&editor_script,