feat: mark diff files as reviewed
This commit is contained in:
+186
-2
@@ -766,6 +766,12 @@ core_actions![
|
||||
&[Mode::Normal],
|
||||
true,
|
||||
),
|
||||
(
|
||||
"core.diff.review.toggle",
|
||||
Action::DiffReviewToggle,
|
||||
&[Mode::Normal],
|
||||
true,
|
||||
),
|
||||
(
|
||||
"core.word_wrap.toggle",
|
||||
Action::WordWrapToggle,
|
||||
@@ -3246,6 +3252,7 @@ impl Editor {
|
||||
| Action::DiffModeToggle
|
||||
| Action::DiffViewToggle
|
||||
| Action::DiffOrientationToggle
|
||||
| Action::DiffReviewToggle
|
||||
| Action::WordWrapToggle
|
||||
| Action::GitBlameToggle
|
||||
| Action::Quit
|
||||
@@ -6185,6 +6192,7 @@ impl Editor {
|
||||
| Action::DiffModeToggle
|
||||
| Action::DiffViewToggle
|
||||
| Action::DiffOrientationToggle
|
||||
| Action::DiffReviewToggle
|
||||
| Action::WordWrapToggle
|
||||
| Action::GitBlameToggle
|
||||
| Action::LspDefinition
|
||||
@@ -7002,13 +7010,25 @@ impl Editor {
|
||||
}
|
||||
if matches!(
|
||||
entry.action,
|
||||
Action::DiffModeToggle | Action::DiffViewToggle | Action::DiffOrientationToggle
|
||||
Action::DiffModeToggle
|
||||
| Action::DiffViewToggle
|
||||
| Action::DiffOrientationToggle
|
||||
| Action::DiffReviewToggle
|
||||
) {
|
||||
let name = entry.ex.expect("diff display action has an Ex command");
|
||||
let name = entry.ex.expect("diff action has an Ex command");
|
||||
if !args.is_empty() {
|
||||
self.set_message(format!("The {name} command takes no arguments"));
|
||||
return None;
|
||||
}
|
||||
if entry.action == Action::DiffReviewToggle
|
||||
&& self
|
||||
.file_picker
|
||||
.as_ref()
|
||||
.is_some_and(|picker| picker.focused)
|
||||
{
|
||||
self.set_message("Select a file in the comparison");
|
||||
return None;
|
||||
}
|
||||
if let Some(owner) = self.diff_owner.filter(|owner| *owner != self.pane_id) {
|
||||
return self.with_pane(owner, |editor| editor.execute_action(entry, args));
|
||||
}
|
||||
@@ -7036,6 +7056,14 @@ impl Editor {
|
||||
self.set_message("No comparison is open");
|
||||
return None;
|
||||
};
|
||||
if entry.action == Action::DiffReviewToggle {
|
||||
match diff.toggle_reviewed() {
|
||||
Ok(true) => self.set_message("File marked reviewed"),
|
||||
Ok(false) => self.set_message("File marked unreviewed"),
|
||||
Err(error) => self.set_message(error),
|
||||
}
|
||||
return None;
|
||||
}
|
||||
if entry.action == Action::DiffViewToggle {
|
||||
diff.set_view_mode(match diff.view_mode {
|
||||
ViewMode::Split => ViewMode::Unified,
|
||||
@@ -10285,6 +10313,7 @@ fn atomic_save(
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::plugin::CompletionEdit;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
struct Directory(PathBuf);
|
||||
impl Directory {
|
||||
@@ -13479,6 +13508,161 @@ mod tests {
|
||||
assert_eq!(editor.lines(), ["beta"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diff_review_actions_preserve_readonly_text_history_and_parked_tabs() {
|
||||
let directory = Directory::new();
|
||||
let mut editor = editor();
|
||||
editor.execute("diff.review.toggle");
|
||||
assert_eq!(editor.message(), "No comparison is open");
|
||||
historical_diff(
|
||||
&mut editor,
|
||||
&directory.0,
|
||||
vec!["before".into(), "second".into()],
|
||||
vec!["after".into(), "second".into()],
|
||||
);
|
||||
editor
|
||||
.bind("normal", "ctrl+y", Some("core.diff.review.toggle".into()))
|
||||
.unwrap();
|
||||
let text = editor.lines().to_vec();
|
||||
let carets = editor.carets();
|
||||
let revision = editor.text_revision();
|
||||
let undo = editor.active.undo.len();
|
||||
let redo = editor.active.redo.len();
|
||||
let dirty = editor.dirty();
|
||||
assert!(editor.mutation_blocked());
|
||||
editor.handle(Input::Ctrl('y'));
|
||||
assert_eq!(editor.diff().unwrap().reviewed_files, BTreeSet::from([0]));
|
||||
editor.execute("diff.review.toggle unexpected");
|
||||
assert!(editor.message().contains("takes no arguments"));
|
||||
assert_eq!(editor.diff().unwrap().reviewed_files, BTreeSet::from([0]));
|
||||
editor.handle(Input::Ctrl('p'));
|
||||
type_text(&mut editor, "diff.review.toggle");
|
||||
editor.handle(Input::Enter);
|
||||
assert!(editor.diff().unwrap().reviewed_files.is_empty());
|
||||
assert_eq!(editor.lines(), text);
|
||||
assert_eq!(editor.carets(), carets);
|
||||
assert_eq!(editor.text_revision(), revision);
|
||||
assert_eq!(editor.active.undo.len(), undo);
|
||||
assert_eq!(editor.active.redo.len(), redo);
|
||||
assert_eq!(editor.dirty(), dirty);
|
||||
assert!(!directory.path("file.txt").exists());
|
||||
editor.handle(Input::Char('\t'));
|
||||
assert_eq!(editor.diff().unwrap().focus, Focus::After);
|
||||
assert!(editor.mutation_blocked());
|
||||
editor.execute(":diff.review.toggle");
|
||||
editor.execute("diff.view.toggle");
|
||||
editor.execute("diff.view.toggle");
|
||||
editor.execute("diff.orientation.toggle");
|
||||
let first_tab = editor.tab_id();
|
||||
editor.execute("tab.new");
|
||||
historical_diff(
|
||||
&mut editor,
|
||||
&directory.0,
|
||||
vec!["base".into()],
|
||||
vec!["different".into()],
|
||||
);
|
||||
assert!(editor.diff().unwrap().reviewed_files.is_empty());
|
||||
editor.execute("tab.previous");
|
||||
assert_eq!(editor.tab_id(), first_tab);
|
||||
assert_eq!(editor.diff().unwrap().reviewed_files, BTreeSet::from([0]));
|
||||
editor.execute("diff.close");
|
||||
historical_diff(
|
||||
&mut editor,
|
||||
&directory.0,
|
||||
vec!["before".into()],
|
||||
vec!["after".into()],
|
||||
);
|
||||
assert!(editor.diff().unwrap().reviewed_files.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diff_review_files_action_targets_highlight_without_stealing_filter_text() {
|
||||
let directory = Directory::new();
|
||||
fs::write(directory.path("z.txt"), "z").unwrap();
|
||||
fs::write(directory.path("a.txt"), "a").unwrap();
|
||||
let mut editor = editor();
|
||||
working_diff(&mut editor, &directory.0, &["z.txt", "a.txt"]);
|
||||
editor
|
||||
.bind("normal", "ctrl+y", Some("core.diff.review.toggle".into()))
|
||||
.unwrap();
|
||||
editor
|
||||
.bind("normal", "Q", Some("core.diff.review.toggle".into()))
|
||||
.unwrap();
|
||||
let files = editor.diff.as_mut().unwrap().files.as_mut().unwrap();
|
||||
files.set_view(FileView::List);
|
||||
files.reveal_path(Path::new("a.txt"));
|
||||
editor.handle(Input::Ctrl('y'));
|
||||
assert_eq!(editor.diff().unwrap().file, 0);
|
||||
assert_eq!(editor.diff().unwrap().reviewed_files, BTreeSet::from([1]));
|
||||
editor.handle(Input::Char('Q'));
|
||||
assert_eq!(editor.file_picker().unwrap().query, "Q");
|
||||
assert_eq!(editor.diff().unwrap().reviewed_files, BTreeSet::from([1]));
|
||||
editor.handle(Input::Ctrl('u'));
|
||||
let files = editor.diff.as_mut().unwrap().files.as_mut().unwrap();
|
||||
files.set_view(FileView::Tree);
|
||||
files.start_search();
|
||||
editor.handle(Input::Char('Q'));
|
||||
assert_eq!(editor.file_picker().unwrap().query, "Q");
|
||||
assert_eq!(editor.diff().unwrap().reviewed_files, BTreeSet::from([1]));
|
||||
editor.handle(Input::Ctrl('y'));
|
||||
assert_eq!(editor.message(), "No changed file is selected");
|
||||
assert_eq!(editor.diff().unwrap().reviewed_files, BTreeSet::from([1]));
|
||||
editor.file_picker = Some(
|
||||
FilePicker::scan(
|
||||
directory.0.clone(),
|
||||
FilePresentation::Docked,
|
||||
FileView::List,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
editor.execute("diff.review.toggle");
|
||||
assert_eq!(editor.message(), "Select a file in the comparison");
|
||||
assert_eq!(editor.diff().unwrap().reviewed_files, BTreeSet::from([1]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn working_review_marks_survive_save_and_clear_only_the_edited_file() {
|
||||
let directory = Directory::new();
|
||||
let first = directory.path("first.txt");
|
||||
fs::write(&first, "base\n").unwrap();
|
||||
fs::write(directory.path("second.txt"), "second").unwrap();
|
||||
let mut editor = Editor::open(Some(first.clone()), vec![]).unwrap();
|
||||
working_diff(&mut editor, &directory.0, &["first.txt", "second.txt"]);
|
||||
editor.execute("diff.review.toggle");
|
||||
editor
|
||||
.diff
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.files
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.reveal_path(Path::new("second.txt"));
|
||||
editor.execute("diff.review.toggle");
|
||||
assert_eq!(
|
||||
editor.diff().unwrap().reviewed_files,
|
||||
BTreeSet::from([0, 1])
|
||||
);
|
||||
editor.handle(Input::BackTab);
|
||||
assert!(editor.diff_editing());
|
||||
editor.execute("w");
|
||||
assert_eq!(
|
||||
editor.diff().unwrap().reviewed_files,
|
||||
BTreeSet::from([0, 1])
|
||||
);
|
||||
type_text(&mut editor, "iX");
|
||||
editor.handle(Input::Escape);
|
||||
assert_eq!(editor.diff().unwrap().reviewed_files, BTreeSet::from([1]));
|
||||
editor.execute("diff.review.toggle");
|
||||
editor.execute("w");
|
||||
assert_eq!(
|
||||
editor.diff().unwrap().reviewed_files,
|
||||
BTreeSet::from([0, 1])
|
||||
);
|
||||
assert_eq!(fs::read_to_string(&first).unwrap(), "Xbase\n");
|
||||
editor.handle(Input::Char('u'));
|
||||
assert_eq!(editor.diff().unwrap().reviewed_files, BTreeSet::from([1]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diff_display_defaults_tabs_and_remaps_preserve_native_snapshot_carets() {
|
||||
let directory = Directory::new();
|
||||
|
||||
Reference in New Issue
Block a user