feat: add configurable three-pane conflict views

This commit is contained in:
Valdemar Lorenzen
2026-10-16 16:19:54 +02:00
parent a6310594c5
commit de6a57e67d
11 changed files with 176 additions and 20 deletions
+14 -3
View File
@@ -58,6 +58,7 @@ pub struct Config {
pub diff_view_mode: crate::diff::ViewMode,
pub diff_split_orientation: crate::panes::SplitAxis,
pub diff_follow_working_copy: bool,
pub resolve_history_layout: crate::editor::ResolverLayout,
}
#[derive(Debug, Deserialize)]
@@ -111,6 +112,7 @@ impl Default for Config {
diff_view_mode: crate::diff::ViewMode::Split,
diff_split_orientation: crate::panes::SplitAxis::Vertical,
diff_follow_working_copy: true,
resolve_history_layout: crate::editor::ResolverLayout::Columns,
}
}
}
@@ -151,6 +153,7 @@ pub fn load_config(path: &Path) -> Result<Config, String> {
diff_view_mode,
diff_split_orientation,
diff_follow_working_copy,
resolve_history_layout,
..
} = *response;
let mut config = Config::default();
@@ -192,6 +195,7 @@ pub fn load_config(path: &Path) -> Result<Config, String> {
config.diff_view_mode = diff_view_mode;
config.diff_split_orientation = diff_split_orientation;
config.diff_follow_working_copy = diff_follow_working_copy;
config.resolve_history_layout = resolve_history_layout;
Ok(config)
}
Response::Error {
@@ -552,6 +556,7 @@ struct ConfigFrame {
diff_view_mode: crate::diff::ViewMode,
diff_split_orientation: crate::panes::SplitAxis,
diff_follow_working_copy: bool,
resolve_history_layout: crate::editor::ResolverLayout,
}
fn whitespace_characters<'de, D: serde::Deserializer<'de>>(
@@ -1084,6 +1089,7 @@ mod tests {
"tab_spaces": null, "language_tab_spaces": {},
"diff_context_lines": 10, "diff_expand_lines": 15,
"diff_view_mode": "split", "diff_split_orientation": "vertical",
"resolve_history_layout": "columns",
"diff_follow_working_copy": true
});
for value in [serde_json::Value::Null, serde_json::json!("reviews")] {
@@ -1512,9 +1518,9 @@ end
assert!(load_config(&path).unwrap_err().contains(error), "{value}");
}
for frame in [
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"review_directory":null,"bindings":[],"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","git_blame":true,"git_gutter":"bar","scroll_distance":0,"highlight_trailing_whitespace":false,"whitespace_characters":{},"whitespace_scope":"all","tab_spaces":null,"language_tab_spaces":{},"top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"vertical","diff_follow_working_copy":true}"#,
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"review_directory":null,"bindings":[],"leader":null,"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","git_blame":true,"git_gutter":"bar","scroll_distance":0,"highlight_trailing_whitespace":false,"whitespace_characters":{},"whitespace_scope":"all","tab_spaces":null,"language_tab_spaces":{},"top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"vertical","diff_follow_working_copy":true}"#,
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"review_directory":null,"bindings":[],"leader":7,"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","git_blame":true,"git_gutter":"bar","scroll_distance":0,"highlight_trailing_whitespace":false,"whitespace_characters":{},"whitespace_scope":"all","tab_spaces":null,"language_tab_spaces":{},"top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"vertical","diff_follow_working_copy":true}"#,
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"review_directory":null,"bindings":[],"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","git_blame":true,"git_gutter":"bar","scroll_distance":0,"highlight_trailing_whitespace":false,"whitespace_characters":{},"whitespace_scope":"all","tab_spaces":null,"language_tab_spaces":{},"top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"vertical","diff_follow_working_copy":true,"resolve_history_layout":"columns"}"#,
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"review_directory":null,"bindings":[],"leader":null,"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","git_blame":true,"git_gutter":"bar","scroll_distance":0,"highlight_trailing_whitespace":false,"whitespace_characters":{},"whitespace_scope":"all","tab_spaces":null,"language_tab_spaces":{},"top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"vertical","diff_follow_working_copy":true,"resolve_history_layout":"columns"}"#,
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"review_directory":null,"bindings":[],"leader":7,"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","git_blame":true,"git_gutter":"bar","scroll_distance":0,"highlight_trailing_whitespace":false,"whitespace_characters":{},"whitespace_scope":"all","tab_spaces":null,"language_tab_spaces":{},"top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"vertical","diff_follow_working_copy":true,"resolve_history_layout":"columns"}"#,
] {
assert!(serde_json::from_str::<Response>(frame).is_err(), "{frame}");
}
@@ -1599,6 +1605,7 @@ end
"top_bar": {}, "bottom_bar": {}, "popup": {"command": {}, "search": {}},
"labels": {}, "diff_context_lines": 10, "diff_expand_lines": 15,
"diff_view_mode": "split", "diff_split_orientation": "vertical",
"resolve_history_layout": "columns",
"diff_follow_working_copy": true
});
assert!(serde_json::from_value::<Response>(frame.clone()).is_ok());
@@ -1739,6 +1746,7 @@ end"#,
"top_bar": {}, "bottom_bar": {}, "popup": {"command": {}, "search": {}},
"labels": {}, "diff_context_lines": 10, "diff_expand_lines": 15,
"diff_view_mode": "split", "diff_split_orientation": "vertical",
"resolve_history_layout": "columns",
"diff_follow_working_copy": true
});
for value in ["all", "leading"] {
@@ -2002,6 +2010,7 @@ end
"popup": {"command": {}, "search": {}},
"clipboard_mode": "system", "diff_context_lines": 0, "diff_expand_lines": 7,
"diff_view_mode": "split", "diff_split_orientation": "vertical",
"resolve_history_layout": "columns",
"diff_follow_working_copy": true
});
for setting in ["diff_context_lines", "diff_expand_lines"] {
@@ -2114,6 +2123,7 @@ end"
"popup": {"command": {}, "search": {}},
"diff_context_lines": 10, "diff_expand_lines": 15,
"diff_view_mode": "split", "diff_split_orientation": "vertical",
"resolve_history_layout": "columns",
"diff_follow_working_copy": true, "scroll_distance": 0
});
for distance in [None, Some(0), Some(7), Some(usize::MAX)] {
@@ -2547,6 +2557,7 @@ end"#,
"popup": {"command": {}, "search": {}},
"clipboard_mode": "system", "diff_context_lines": 10, "diff_expand_lines": 15,
"diff_view_mode": "split", "diff_split_orientation": "vertical",
"resolve_history_layout": "columns",
"diff_follow_working_copy": true
});
let Response::Config(config) = serde_json::from_value::<Response>(frame.clone()).unwrap()