feat: add configurable three-pane conflict views
This commit is contained in:
+97
-5
@@ -45,8 +45,8 @@ use crate::{
|
||||
RowKind, ViewMode,
|
||||
},
|
||||
editor::{
|
||||
Completion, Cursor, Editor, Hover, Input, Mode, Palette, ResolverStatus, ResolverView,
|
||||
ResolverWorkspace, Selection, StartupDiagnostic, WhitespaceScope,
|
||||
Completion, Cursor, Editor, Hover, Input, Mode, Palette, ResolverLayout, ResolverStatus,
|
||||
ResolverView, ResolverWorkspace, Selection, StartupDiagnostic, WhitespaceScope,
|
||||
},
|
||||
files::{DockSide, FilePicker, FilePresentation, FileView},
|
||||
panes::{PaneRect, SplitAxis, split_rect},
|
||||
@@ -698,7 +698,12 @@ impl BufferViewports {
|
||||
editor.set_pane_bounds(pane_rect(workspace));
|
||||
self.rects.clear();
|
||||
if resolver_history {
|
||||
let layout = resolver_history_layout(workspace, editor.resolver().unwrap(), focused);
|
||||
let layout = resolver_history_layout(
|
||||
workspace,
|
||||
editor.resolver().unwrap(),
|
||||
focused,
|
||||
editor.resolve_history_layout,
|
||||
);
|
||||
draw_resolver_heading(frame, editor.resolver().unwrap(), layout.heading);
|
||||
self.draw_resolver_history(frame, editor, &layout);
|
||||
} else if resolver_resolution {
|
||||
@@ -963,7 +968,7 @@ impl BufferViewports {
|
||||
.iter()
|
||||
.flatten()
|
||||
.map(|(_, _, area)| usize::from(area.height))
|
||||
.max()
|
||||
.min()
|
||||
.unwrap_or(0);
|
||||
history.top.continuation = history
|
||||
.top
|
||||
@@ -2097,6 +2102,7 @@ fn resolver_history_layout(
|
||||
area: Rect,
|
||||
resolver: &ResolverWorkspace,
|
||||
focused: usize,
|
||||
mode: ResolverLayout,
|
||||
) -> ResolverHistoryLayout {
|
||||
let [heading, documents] = Layout::vertical([
|
||||
Constraint::Length(u16::from(area.height >= 4)),
|
||||
@@ -2126,7 +2132,8 @@ fn resolver_history_layout(
|
||||
sources.push(index);
|
||||
}
|
||||
}
|
||||
if documents.width < 60 {
|
||||
let base_below = mode == ResolverLayout::BaseBelow && sources.len() == 3;
|
||||
if documents.width < 60 || (base_below && documents.height < 4) {
|
||||
let selected = sources
|
||||
.iter()
|
||||
.copied()
|
||||
@@ -2135,6 +2142,12 @@ fn resolver_history_layout(
|
||||
if let Some(selected) = selected {
|
||||
layout.history.push((selected, documents));
|
||||
}
|
||||
} else if base_below {
|
||||
let [inputs, base] = Layout::vertical([Constraint::Fill(1); 2]).areas(documents);
|
||||
let [left, right] = Layout::horizontal([Constraint::Fill(1); 2]).areas(inputs);
|
||||
layout
|
||||
.history
|
||||
.extend([(sources[0], left), (sources[2], right), (sources[1], base)]);
|
||||
} else {
|
||||
let columns = Layout::horizontal(vec![Constraint::Fill(1); sources.len()]).split(documents);
|
||||
layout
|
||||
@@ -8183,6 +8196,85 @@ mod tests {
|
||||
assert_eq!(session.editor().cursor(), draft_cursor);
|
||||
assert_eq!(views.panels.diff.as_ref().unwrap().viewport, draft_viewport);
|
||||
assert_eq!(restored_caret, searched_caret);
|
||||
{
|
||||
let config = directory.file(
|
||||
"base-below.rb",
|
||||
"Vamp.configure do |config|\n config.clipboard_mode = 'separate'\n config.resolve_history_layout = 'base_below'\nend\n",
|
||||
);
|
||||
let mut bottom = EditorSession::open(
|
||||
Some(directory.0.join("first.txt")),
|
||||
vec!["text".into()],
|
||||
Some(&config),
|
||||
)
|
||||
.unwrap();
|
||||
bottom.execute("resolve");
|
||||
ready(&mut bottom);
|
||||
let draft = bottom.editor().context().text;
|
||||
bottom.execute("resolve.history");
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(120, 30)).unwrap();
|
||||
let mut views = BufferViewports::default();
|
||||
render(&mut terminal, &mut views, &mut bottom);
|
||||
let resolver = bottom.editor().resolver().unwrap();
|
||||
let left = resolver.history_panes[resolver.history_sources[0]];
|
||||
let right = resolver.history_panes[resolver.history_sources[1]];
|
||||
let base = resolver.history_panes[resolver.selected_base.unwrap()];
|
||||
assert_eq!(views.rects.len(), 3);
|
||||
assert_eq!(
|
||||
views
|
||||
.rects
|
||||
.iter()
|
||||
.map(|(pane, _)| *pane)
|
||||
.collect::<Vec<_>>(),
|
||||
[left, right, base]
|
||||
);
|
||||
let [left_area, right_area, base_area] =
|
||||
std::array::from_fn(|index| views.rects[index].1);
|
||||
assert_eq!(left_area.right(), right_area.x);
|
||||
assert_eq!(left_area.y, right_area.y);
|
||||
assert_eq!(base_area.x, left_area.x);
|
||||
assert_eq!(base_area.right(), right_area.right());
|
||||
assert!(base_area.y >= left_area.bottom());
|
||||
for (area, value) in [
|
||||
(left_area, "value = left;"),
|
||||
(right_area, "value = right;"),
|
||||
(base_area, "value = base;"),
|
||||
] {
|
||||
assert!(line_at(&terminal, area, area.y).contains(value));
|
||||
}
|
||||
bottom.handle(Input::Char('\t'));
|
||||
assert_eq!(bottom.editor().pane_id(), right);
|
||||
bottom.handle(Input::Char('\t'));
|
||||
assert_eq!(bottom.editor().pane_id(), base);
|
||||
bottom.handle(Input::BackTab);
|
||||
assert_eq!(bottom.editor().pane_id(), right);
|
||||
bottom.execute("pane.focus_down");
|
||||
let caret = render(&mut terminal, &mut views, &mut bottom);
|
||||
assert_eq!(bottom.editor().pane_id(), base);
|
||||
assert!(base_area.contains(caret));
|
||||
assert!(views.scroll(
|
||||
&mut bottom,
|
||||
document_wheel(MouseEventKind::ScrollDown, base_area.x, base_area.y)
|
||||
));
|
||||
render(&mut terminal, &mut views, &mut bottom);
|
||||
for area in [left_area, right_area, base_area] {
|
||||
assert!(line_at(&terminal, area, area.y).contains("context 02"));
|
||||
}
|
||||
let readonly = bottom.editor().context().text;
|
||||
bottom.handle(Input::Char('i'));
|
||||
bottom.handle(Input::Paste("must not edit base".into()));
|
||||
bottom.handle(Input::Escape);
|
||||
assert_eq!(bottom.editor().context().text, readonly);
|
||||
terminal.backend_mut().resize(44, 20);
|
||||
render(&mut terminal, &mut views, &mut bottom);
|
||||
assert_eq!(views.rects.len(), 1);
|
||||
assert_eq!(views.rects[0].0, base);
|
||||
terminal.backend_mut().resize(120, 6);
|
||||
render(&mut terminal, &mut views, &mut bottom);
|
||||
assert_eq!(views.rects.len(), 1);
|
||||
assert_eq!(views.rects[0].0, base);
|
||||
bottom.execute("resolve.draft");
|
||||
assert_eq!(bottom.editor().context().text, draft);
|
||||
}
|
||||
|
||||
for (key, action) in [
|
||||
("ctrl+e", "core.file_explorer"),
|
||||
|
||||
Reference in New Issue
Block a user