From 268ac4c0476f56453639aba36715f8042e542815 Mon Sep 17 00:00:00 2001 From: Peter Tripp Date: Thu, 21 Nov 2024 18:10:25 +0000 Subject: [PATCH] Implement readline/emacs/macos style ctrl-k cut and ctrl-y yank (#21003) - Added support for ctrl-k / ctrl-y alternate cut/yank buffer on macos. Co-authored-by: Conrad Irwin --- assets/keymaps/default-macos.json | 3 ++- crates/editor/src/actions.rs | 2 ++ crates/editor/src/editor.rs | 42 ++++++++++++++++++++++++++----- crates/editor/src/element.rs | 2 ++ 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index 82edba3305..5b416db9b2 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -49,8 +49,9 @@ "ctrl-d": "editor::Delete", "tab": "editor::Tab", "shift-tab": "editor::TabPrev", - "ctrl-k": "editor::CutToEndOfLine", "ctrl-t": "editor::Transpose", + "ctrl-k": "editor::KillRingCut", + "ctrl-y": "editor::KillRingYank", "cmd-k q": "editor::Rewrap", "cmd-k cmd-q": "editor::Rewrap", "cmd-backspace": "editor::DeleteToBeginningOfLine", diff --git a/crates/editor/src/actions.rs b/crates/editor/src/actions.rs index dcfc291968..5b11b18bc2 100644 --- a/crates/editor/src/actions.rs +++ b/crates/editor/src/actions.rs @@ -271,6 +271,8 @@ gpui::actions!( Hover, Indent, JoinLines, + KillRingCut, + KillRingYank, LineDown, LineUp, MoveDown, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index cc450c573f..b31938bcfd 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -74,7 +74,7 @@ use gpui::{ div, impl_actions, point, prelude::*, px, relative, size, uniform_list, Action, AnyElement, AppContext, AsyncWindowContext, AvailableSpace, BackgroundExecutor, Bounds, ClipboardEntry, ClipboardItem, Context, DispatchPhase, ElementId, EventEmitter, FocusHandle, FocusOutEvent, - FocusableView, FontId, FontWeight, HighlightStyle, Hsla, InteractiveText, KeyContext, + FocusableView, FontId, FontWeight, Global, HighlightStyle, Hsla, InteractiveText, KeyContext, ListSizingBehavior, Model, ModelContext, MouseButton, PaintQuad, ParentElement, Pixels, Render, ScrollStrategy, SharedString, Size, StrikethroughStyle, Styled, StyledText, Subscription, Task, TextStyle, TextStyleRefinement, UTF16Selection, UnderlineStyle, UniformListScrollHandle, View, @@ -7364,7 +7364,7 @@ impl Editor { .update(cx, |buffer, cx| buffer.edit(edits, None, cx)); } - pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext) { + pub fn cut_common(&mut self, cx: &mut ViewContext) -> ClipboardItem { let mut text = String::new(); let buffer = self.buffer.read(cx).snapshot(cx); let mut selections = self.selections.all::(cx); @@ -7408,11 +7408,38 @@ impl Editor { s.select(selections); }); this.insert("", cx); - cx.write_to_clipboard(ClipboardItem::new_string_with_json_metadata( - text, - clipboard_selections, - )); }); + ClipboardItem::new_string_with_json_metadata(text, clipboard_selections) + } + + pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext) { + let item = self.cut_common(cx); + cx.write_to_clipboard(item); + } + + pub fn kill_ring_cut(&mut self, _: &KillRingCut, cx: &mut ViewContext) { + self.change_selections(None, cx, |s| { + s.move_with(|snapshot, sel| { + if sel.is_empty() { + sel.end = DisplayPoint::new(sel.end.row(), snapshot.line_len(sel.end.row())) + } + }); + }); + let item = self.cut_common(cx); + cx.set_global(KillRing(item)) + } + + pub fn kill_ring_yank(&mut self, _: &KillRingYank, cx: &mut ViewContext) { + let (text, metadata) = if let Some(KillRing(item)) = cx.try_global() { + if let Some(ClipboardEntry::String(kill_ring)) = item.entries().first() { + (kill_ring.text().to_string(), kill_ring.metadata_json()) + } else { + return; + } + } else { + return; + }; + self.do_paste(&text, metadata, false, cx); } pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext) { @@ -15145,4 +15172,7 @@ fn check_multiline_range(buffer: &Buffer, range: Range) -> Range { } } +pub struct KillRing(ClipboardItem); +impl Global for KillRing {} + const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50); diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 6e4538ae6d..0c403022a3 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -217,6 +217,8 @@ impl EditorElement { register_action(view, cx, Editor::transpose); register_action(view, cx, Editor::rewrap); register_action(view, cx, Editor::cut); + register_action(view, cx, Editor::kill_ring_cut); + register_action(view, cx, Editor::kill_ring_yank); register_action(view, cx, Editor::copy); register_action(view, cx, Editor::paste); register_action(view, cx, Editor::undo);