#![allow(
clippy::significant_drop_tightening,
clippy::uninlined_format_args,
clippy::drop_non_drop
)]
use super::super::*;
use {
reovim_driver_command::{CommandContext, CommandHandler, CommandResult},
reovim_driver_session::{
ClientId, ExtensionMap, Session, SessionRuntime, WindowLayout, testing::StubExecutor,
},
reovim_kernel::{
api::{
ModeStack,
v1::{
Buffer, BufferId, CommandId, HistoryRing, Jumplist, KernelContext, MarkBank,
ModeId, ModuleId, Position, Register, RegisterBank, RwLock,
},
},
testing::create_test_context,
},
std::sync::Arc,
};
fn run_command<C: CommandHandler>(
cmd: &C,
ctx: &KernelContext,
args: &CommandContext,
) -> CommandResult {
let home_mode = ModeId::new(ModuleId::new("test"), "normal");
let mut session = Session::new(ClientId::new(1), home_mode.clone()); let executor = StubExecutor;
let mut mode_stack = ModeStack::new(home_mode);
let mut windows = WindowLayout::empty();
let mut extensions = ExtensionMap::new();
let mut compositor = None;
let mut tabs = reovim_driver_session::TabPageSet::new();
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut local_marks = MarkBank::new();
let mut jumplist = Jumplist::new();
let mut active_buffer = None;
let mut terminal_size = (80u16, 24u16);
let mut runtime = SessionRuntime::new(
&mut session,
reovim_driver_session::ClientContext {
mode_stack: &mut mode_stack,
windows: &mut windows,
extensions: &mut extensions,
compositor: &mut compositor,
tabs: &mut tabs,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
local_marks: &mut local_marks,
jumplist: &mut jumplist,
active_buffer: &mut active_buffer,
terminal_size: &mut terminal_size,
},
ctx,
&executor,
);
cmd.execute(&mut runtime, args)
}
#[test]
fn test_delete_operator_id() {
let delete = DeleteOperator;
assert_eq!(delete.id(), "delete");
}
#[test]
fn test_delete_is_text_modifying() {
let delete = DeleteOperator;
assert!(delete.is_text_modifying());
}
#[test]
fn test_delete_is_not_linewise_by_default() {
let delete = DeleteOperator;
assert!(!delete.is_linewise());
}
#[test]
fn test_delete_buffer_not_found() {
let ctx = create_test_context();
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id: BufferId::from_raw(999),
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 0), Position::new(0, 5));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_err());
}
#[test]
fn test_delete_characterwise_single_line() {
let ctx = create_test_context();
let buffer = Buffer::from_string("hello world");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 0), Position::new(0, 5));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &[" world"]);
drop(op_ctx);
assert_eq!(registers.get().text, "hello");
}
#[test]
fn test_delete_characterwise_partial() {
let ctx = create_test_context();
let buffer = Buffer::from_string("hello world");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 6),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 6), Position::new(0, 11));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &["hello "]);
drop(op_ctx);
assert_eq!(registers.get().text, "world");
}
#[test]
fn test_delete_characterwise_multi_line() {
let ctx = create_test_context();
let buffer = Buffer::from_string("hello\nworld\nfoo");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 3),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 3), Position::new(1, 3));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
drop(op_ctx);
assert_eq!(registers.get().text, "lo\nwor");
}
#[test]
fn test_delete_linewise_first_line_of_multiple() {
let ctx = create_test_context();
let buffer = Buffer::from_string("line1\nline2\nline3");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(0, 0), Position::new(0, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &["line2", "line3"]);
drop(op_ctx);
assert_eq!(registers.get().text, "line1\n");
}
#[test]
fn test_delete_linewise_last_line_not_only() {
let ctx = create_test_context();
let buffer = Buffer::from_string("line1\nline2");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(1, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(1, 0), Position::new(1, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &["line1"]);
drop(op_ctx);
assert_eq!(registers.get().text, "line2\n");
}
#[test]
fn test_delete_linewise_only_line() {
let ctx = create_test_context();
let buffer = Buffer::from_string("only line");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(0, 0), Position::new(0, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &[""]);
drop(op_ctx);
assert_eq!(registers.get().text, "only line\n");
}
#[test]
fn test_delete_linewise_multiple_lines() {
let ctx = create_test_context();
let buffer = Buffer::from_string("a\nb\nc\nd");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(1, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(1, 0), Position::new(2, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &["a", "d"]);
drop(op_ctx);
assert_eq!(registers.get().text, "b\nc\n");
}
#[test]
fn test_delete_to_named_register() {
let ctx = create_test_context();
let buffer = Buffer::from_string("hello world");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Slot('a'),
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 0), Position::new(0, 5));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
drop(op_ctx);
assert_eq!(registers.get_named('a').map(|r| r.text.as_str()), Some("hello"));
}
#[test]
fn test_delete_linewise_clamped_end() {
let ctx = create_test_context();
let buffer = Buffer::from_string("a\nb");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(0, 0), Position::new(99, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &[""]);
}
#[test]
fn test_delete_characterwise_empty_range() {
let ctx = create_test_context();
let buffer = Buffer::from_string("hello");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 3),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 3), Position::new(0, 3));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &["hello"]);
}
#[test]
fn test_delete_linewise_last_two_of_three() {
let ctx = create_test_context();
let buffer = Buffer::from_string("a\nb\nc");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(1, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(1, 0), Position::new(2, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &["a"]);
}
#[test]
fn test_delete_characterwise_three_lines() {
let ctx = create_test_context();
let buffer = Buffer::from_string("aaa\nbbb\nccc");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 1),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 1), Position::new(2, 2));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
drop(op_ctx);
assert_eq!(registers.get().text, "aa\nbbb\ncc");
}
#[test]
fn test_delete_linewise_middle_line_of_three() {
let ctx = create_test_context();
let buffer = Buffer::from_string("first\nsecond\nthird");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(1, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(1, 0), Position::new(1, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &["first", "third"]);
drop(op_ctx);
assert_eq!(registers.get().text, "second\n");
}
#[test]
fn test_delete_characterwise_single_char() {
let ctx = create_test_context();
let buffer = Buffer::from_string("hello");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 0), Position::new(0, 1));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &["ello"]);
drop(op_ctx);
assert_eq!(registers.get().text, "h");
}
#[test]
fn test_delete_to_register_b() {
let ctx = create_test_context();
let buffer = Buffer::from_string("hello world");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Slot('b'),
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 0), Position::new(0, 5));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
drop(op_ctx);
assert_eq!(registers.get_named('b').map(|r| r.text.as_str()), Some("hello"));
}
#[test]
fn test_delete_linewise_all_lines_three() {
let ctx = create_test_context();
let buffer = Buffer::from_string("a\nb\nc");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(0, 0), Position::new(2, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &[""]);
drop(op_ctx);
assert_eq!(registers.get().text, "a\nb\nc\n");
}
#[test]
fn test_delete_operator_clone() {
let delete = DeleteOperator;
let cloned = delete;
assert_eq!(cloned.id(), "delete");
}
#[test]
fn test_delete_operator_copy() {
let delete = DeleteOperator;
let copied: DeleteOperator = delete;
assert_eq!(copied.id(), "delete");
}
#[test]
fn test_delete_operator_debug() {
let debug = format!("{:?}", DeleteOperator);
assert!(debug.contains("DeleteOperator"));
}
#[test]
fn test_delete_characterwise_entire_line_content() {
let ctx = create_test_context();
let buffer = Buffer::from_string("hello");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 0), Position::new(0, 5));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &[""]);
drop(op_ctx);
assert_eq!(registers.get().text, "hello");
}
#[test]
fn test_delete_characterwise_column_beyond_line() {
let ctx = create_test_context();
let buffer = Buffer::from_string("hi");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 0), Position::new(0, 100));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let buf = ctx.buffers.get(buffer_id).unwrap();
let buf = buf.read();
assert_eq!(buf.lines(), &[""]);
drop(op_ctx);
assert_eq!(registers.get().text, "hi");
}
use {
reovim_driver_undo::{
UndoKey, UndoPersistError, UndoProvider, UndoProviderRegistry, UndoRecord,
},
reovim_driver_vfs::VfsDriver,
reovim_kernel::api::v1::{Edit, UndoResult, UndoTree},
};
struct MockUndoProvider {
records: RwLock<Vec<UndoRecord>>,
}
impl MockUndoProvider {
fn new() -> Self {
Self {
records: RwLock::new(Vec::new()),
}
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl UndoProvider for MockUndoProvider {
fn undo(&self, _: BufferId) -> Option<UndoResult> {
None
}
fn redo(&self, _: BufferId) -> Option<UndoResult> {
None
}
fn redo_branch(&self, _: BufferId, _: usize) -> Option<UndoResult> {
None
}
fn record(
&self,
buffer_id: BufferId,
edits: Vec<Edit>,
cursor_before: Position,
cursor_after: Position,
) {
self.records.write().push(UndoRecord {
buffer_id,
edits,
cursor_before,
cursor_after,
});
}
fn has_history(&self, _: BufferId) -> bool {
false
}
fn remove(&self, _: BufferId) {}
fn buffer_count(&self) -> usize {
0
}
fn get_tree(&self, _: BufferId) -> Option<UndoTree> {
None
}
fn begin_batch(&self, _: BufferId, _: Position) {}
fn end_batch(&self, _: BufferId, _: Position) {}
fn is_batching(&self, _: BufferId) -> bool {
false
}
fn persist(&self, _: BufferId, _: &str, _: &dyn VfsDriver) -> Result<(), UndoPersistError> {
Ok(())
}
fn load(&self, _: BufferId, _: &str, _: &dyn VfsDriver) -> Result<bool, UndoPersistError> {
Ok(false)
}
}
fn create_test_context_with_undo() -> (KernelContext, Arc<MockUndoProvider>) {
let ctx = create_test_context();
let mock_undo = Arc::new(MockUndoProvider::new());
let undo_registry = Arc::new(UndoProviderRegistry::new());
undo_registry.register(UndoKey::Buffer, mock_undo.clone() as Arc<dyn UndoProvider>);
ctx.services.register(undo_registry);
(ctx, mock_undo)
}
#[test]
fn test_delete_linewise_records_undo() {
let (ctx, mock_undo) = create_test_context_with_undo();
let buffer = Buffer::from_string("line1\nline2\nline3");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(0, 0), Position::new(0, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let records = mock_undo.records.read();
assert_eq!(records.len(), 1);
assert_eq!(records[0].buffer_id, buffer_id);
assert!(matches!(&records[0].edits[0], Edit::Delete { .. }));
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_delete_characterwise_records_undo() {
let (ctx, mock_undo) = create_test_context_with_undo();
let buffer = Buffer::from_string("hello world");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 0), Position::new(0, 5));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let records = mock_undo.records.read();
assert_eq!(records.len(), 1);
assert_eq!(records[0].buffer_id, buffer_id);
if let Edit::Delete { position, text } = &records[0].edits[0] {
assert_eq!(*position, Position::new(0, 0));
assert_eq!(text, "hello");
} else {
panic!("Expected Delete edit");
}
}
#[test]
fn test_delete_linewise_last_line_empty_after_delete() {
let (ctx, _mock_undo) = create_test_context_with_undo();
let buffer = Buffer::from_string("\n");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(1, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(1, 0), Position::new(1, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_delete_linewise_case2_records_undo_with_newline_prefix() {
let (ctx, mock_undo) = create_test_context_with_undo();
let buffer = Buffer::from_string("first\nsecond");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(1, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(1, 0), Position::new(1, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let records = mock_undo.records.read();
assert_eq!(records.len(), 1);
if let Edit::Delete { text, .. } = &records[0].edits[0] {
assert_eq!(text, "\nsecond");
} else {
panic!("Expected Delete edit");
}
}
#[test]
fn test_delete_run_command_helper_with_noop() {
struct NoopCmd;
#[cfg_attr(coverage_nightly, coverage(off))]
impl reovim_driver_command::Command for NoopCmd {
fn id(&self) -> CommandId {
CommandId::new(ModuleId::new("test"), "noop")
}
fn description(&self) -> &'static str {
"noop"
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for NoopCmd {
fn execute(&self, _: &mut SessionRuntime<'_>, _: &CommandContext) -> CommandResult {
CommandResult::Success
}
}
let ctx = create_test_context();
let args = CommandContext::new();
let result = run_command(&NoopCmd, &ctx, &args);
assert_eq!(result, CommandResult::Success);
}
#[test]
fn test_delete_characterwise_register_is_characterwise() {
let ctx = create_test_context();
let buffer = Buffer::from_string("hello world");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 0), Position::new(0, 5));
delete.execute(&mut op_ctx, range).unwrap();
drop(op_ctx);
assert!(registers.get().is_characterwise());
}
#[test]
fn test_delete_linewise_register_is_linewise() {
let ctx = create_test_context();
let buffer = Buffer::from_string("hello\nworld");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(0, 0), Position::new(0, 0));
delete.execute(&mut op_ctx, range).unwrap();
drop(op_ctx);
assert!(registers.get().is_linewise());
}
#[test]
fn test_delete_undo_records_cursor_positions() {
let (ctx, mock_undo) = create_test_context_with_undo();
let buffer = Buffer::from_string("hello world");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let cursor_before = Position::new(0, 3);
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: cursor_before,
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 3), Position::new(0, 8));
delete.execute(&mut op_ctx, range).unwrap();
let records = mock_undo.records.read();
assert_eq!(records.len(), 1);
assert_eq!(records[0].cursor_before, cursor_before);
assert_eq!(records[0].cursor_after, Position::new(0, 3));
}
#[test]
fn test_delete_linewise_undo_records_cursor_positions() {
let (ctx, mock_undo) = create_test_context_with_undo();
let buffer = Buffer::from_string("line1\nline2\nline3");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let cursor_before = Position::new(1, 2);
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: cursor_before,
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(1, 0), Position::new(1, 0));
delete.execute(&mut op_ctx, range).unwrap();
let records = mock_undo.records.read();
assert_eq!(records.len(), 1);
assert_eq!(records[0].cursor_before, cursor_before);
assert_eq!(records[0].cursor_after, Position::new(1, 0));
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_delete_characterwise_multiline_records_undo() {
let (ctx, mock_undo) = create_test_context_with_undo();
let buffer = Buffer::from_string("hello\nworld");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 3),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 3), Position::new(1, 3));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
let records = mock_undo.records.read();
assert_eq!(records.len(), 1);
if let Edit::Delete { text, .. } = &records[0].edits[0] {
assert_eq!(text, "lo\nwor");
} else {
panic!("Expected Delete edit");
}
}
#[test]
fn test_delete_linewise_sets_cursor_after_case1() {
let ctx = create_test_context();
let buffer = Buffer::from_string("aaa\nbbb\nccc");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(0, 0), Position::new(0, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
assert_eq!(op_ctx.cursor_after, Some(Position::new(0, 0)));
}
#[test]
fn test_delete_linewise_sets_cursor_after_case2() {
let ctx = create_test_context();
let buffer = Buffer::from_string("aaa\nbbb");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(1, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(1, 0), Position::new(1, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
assert_eq!(op_ctx.cursor_after, Some(Position::new(0, 2)));
}
#[test]
fn test_delete_linewise_sets_cursor_after_case3() {
let ctx = create_test_context();
let buffer = Buffer::from_string("only");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::linewise(Position::new(0, 0), Position::new(0, 0));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
assert_eq!(op_ctx.cursor_after, Some(Position::new(0, 0)));
}
#[test]
fn test_delete_characterwise_sets_cursor_after() {
let ctx = create_test_context();
let buffer = Buffer::from_string("hello world");
let buffer_id = ctx.buffers.register(buffer);
let delete = DeleteOperator;
let mut registers = RegisterBank::new();
let mut clipboard_history = HistoryRing::new();
let mut op_ctx = OperatorContext {
kernel: &ctx,
registers: &mut registers,
clipboard_history: &mut clipboard_history,
buffer_id,
register: Register::Default,
count: 1,
cursor_position: Position::new(0, 0),
cursor_after: None,
};
let range = super::super::Range::new(Position::new(0, 0), Position::new(0, 5));
let result = delete.execute(&mut op_ctx, range);
assert!(result.is_ok());
assert_eq!(op_ctx.cursor_after, Some(Position::new(0, 0)));
}