From c780bc064c84cc299b01189b7b225c335dd00da7 Mon Sep 17 00:00:00 2001 From: clover caruso Date: Thu, 15 Oct 2026 14:14:45 -0700 Subject: [PATCH] feat: move lines and list items with Alt+Up and Alt+Down, as in VS Code Alt+Up and Alt+Down now move the selected paragraphs, list items included, past their sibling on Windows and Linux, alongside OneNote's Alt+Shift+Up and Down. On macOS, Option+Up and Down do the same, as VS Code binds them there, taking over from plain Option's jump to the paragraph start or end; Option-Shift still extends the selection to the paragraph ends, and Option-Command keeps moving paragraphs as OneNote for Mac does. Fixes #151 Assisted-by: claude-opus-5.5 --- crates/draw/src/edit.rs | 67 +++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/crates/draw/src/edit.rs b/crates/draw/src/edit.rs index a85270749f17334f02052aa982c644bd724f87e8..b51cbc955af33d11d88b650ebf3bceb2105f6c38 100644 --- a/crates/draw/src/edit.rs +++ b/crates/draw/src/edit.rs @@ -88,7 +88,8 @@ pub enum Command { /// Moves the caret a page and the view with it, extending the selection with Shift. MovePage { up: bool }, /// Moves the selected paragraphs past their sibling above or below: OneNote's Alt+Shift+Up - /// and Down, Option-Command on macOS as OneNote for Mac binds them. + /// and Down, Option-Command on macOS as OneNote for Mac binds them, and VS Code's Alt or + /// Option with Up and Down. MoveParagraphs { up: bool }, } @@ -289,7 +290,7 @@ fn mac_command(key: &Key, modifiers: Modifiers) -> Option { }; match key { Key::Named(arrow @ (NamedKey::ArrowUp | NamedKey::ArrowDown)) - if command && option && !shift && !control => + if option && !shift && !control => { Some(Command::MoveParagraphs { up: *arrow == NamedKey::ArrowUp, @@ -351,14 +352,11 @@ fn mac_command(key: &Key, modifiers: Modifiers) -> Option { /// and End reaches the document's ends; Control with Up and Down moves by paragraphs. fn pc_command(key: &Key, modifiers: Modifiers) -> Option { let Modifiers { - shift, - control, - option, - .. + control, option, .. } = modifiers; if option { return match key { - _ if !shift || control => None, + _ if control => None, Key::Named(NamedKey::ArrowUp) => Some(Command::MoveParagraphs { up: true }), Key::Named(NamedKey::ArrowDown) => Some(Command::MoveParagraphs { up: false }), _ => None, @@ -605,11 +603,6 @@ mod tests { with(|m| (m.command, m.option) = (true, true)), Some(Command::Move(Movement::LineEnd)), ), - ( - named(NamedKey::ArrowUp), - with(|m| m.option = true), - Some(Command::Move(Movement::ParagraphStart)), - ), (named(NamedKey::Home), Modifiers::default(), None), ( named(NamedKey::End), @@ -652,11 +645,36 @@ mod tests { with(|m| (m.command, m.option) = (true, true)), Some(Command::MoveParagraphs { up: false }), ), + ( + named(NamedKey::ArrowUp), + with(|m| (m.command, m.option) = (true, true)), + Some(Command::MoveParagraphs { up: true }), + ), + ( + named(NamedKey::ArrowUp), + with(|m| m.option = true), + Some(Command::MoveParagraphs { up: true }), + ), + ( + named(NamedKey::ArrowDown), + with(|m| m.option = true), + Some(Command::MoveParagraphs { up: false }), + ), ( named(NamedKey::ArrowUp), with(|m| (m.shift, m.option) = (true, true)), Some(Command::Move(Movement::ParagraphStart)), ), + ( + named(NamedKey::ArrowDown), + with(|m| (m.shift, m.option) = (true, true)), + Some(Command::Move(Movement::ParagraphEnd)), + ), + ( + named(NamedKey::ArrowUp), + with(|m| (m.control, m.option) = (true, true)), + Some(Command::Move(Movement::ParagraphStart)), + ), ]; for (key, modifiers, command) in cases { assert_eq!( @@ -688,7 +706,30 @@ mod tests { alt_shift, Some(Command::MoveParagraphs { up: true }), ), - (named(NamedKey::ArrowUp), alt, None), + ( + named(NamedKey::ArrowDown), + alt_shift, + Some(Command::MoveParagraphs { up: false }), + ), + ( + named(NamedKey::ArrowUp), + alt, + Some(Command::MoveParagraphs { up: true }), + ), + ( + named(NamedKey::ArrowDown), + alt, + Some(Command::MoveParagraphs { up: false }), + ), + ( + named(NamedKey::ArrowUp), + Modifiers { + control: true, + command: true, + ..alt + }, + None, + ), ( named(NamedKey::ArrowLeft), control, -- 2.54.0