T44d Web · Stories stand alone: nested ones surface, hidden ones drop their demos, early themes land, pastes arrive
This commit is contained in:
1 parent
edab58e91a
commit
2463bb0ac9
22 files changed
+352
-172
No files matched your search
+2
-5
@@ -382,13 +382,10 @@ impl CodeEditor {
|
||||
}
|
||||
|
||||
/// Pastes one line at each cursor when the counts match, else the whole text at every one.
|
||||
pub(crate) fn paste(&mut self, cx: &mut Context<Self>) {
|
||||
pub(crate) fn paste(&mut self, text: &str, cx: &mut Context<Self>) {
|
||||
if !self.editable() {
|
||||
return;
|
||||
}
|
||||
let Some(text) = cx.read_from_clipboard().and_then(|item| item.text()) else {
|
||||
return;
|
||||
};
|
||||
let lines: Vec<&str> = text.split('\n').collect();
|
||||
let edits = if lines.len() == self.selections.len() && lines.len() > 1 {
|
||||
self.in_order()
|
||||
@@ -399,7 +396,7 @@ impl CodeEditor {
|
||||
} else {
|
||||
self.selections
|
||||
.iter()
|
||||
.map(|selection| (selection.range(), text.clone()))
|
||||
.map(|selection| (selection.range(), text.to_string()))
|
||||
.collect()
|
||||
};
|
||||
self.apply(edits, false, cx);
|
||||
|
||||
+8
-2
@@ -1,8 +1,8 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use gpui::{
|
||||
App, Bounds, Context, EntityInputHandler, FontStyle, HighlightStyle, Pixels, Point,
|
||||
UTF16Selection, Window, point,
|
||||
App, Bounds, ClipboardItem, Context, EntityInputHandler, FontStyle, HighlightStyle, Pixels,
|
||||
Point, UTF16Selection, Window, point,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -107,6 +107,12 @@ impl CodeEditor {
|
||||
}
|
||||
|
||||
impl EntityInputHandler for CodeEditor {
|
||||
fn paste(&mut self, item: ClipboardItem, _: &mut Window, cx: &mut Context<Self>) {
|
||||
if let Some(text) = item.text() {
|
||||
self.paste(&text, cx);
|
||||
}
|
||||
}
|
||||
|
||||
fn text_for_range(
|
||||
&mut self,
|
||||
range_utf16: Range<usize>,
|
||||
|
||||
+9
-2
@@ -91,13 +91,16 @@ pub(crate) fn bind_keys(cx: &mut App) {
|
||||
KeyBinding::new("secondary-a", SelectAll, context),
|
||||
KeyBinding::new("secondary-c", Copy, context),
|
||||
KeyBinding::new("secondary-x", Cut, context),
|
||||
KeyBinding::new("secondary-v", Paste, context),
|
||||
KeyBinding::new("secondary-d", SelectNext, context),
|
||||
KeyBinding::new("escape", SingleCursor, context),
|
||||
KeyBinding::new("secondary-/", ToggleComment, context),
|
||||
KeyBinding::new("secondary-alt-[", Fold, context),
|
||||
KeyBinding::new("secondary-alt-]", Unfold, context),
|
||||
];
|
||||
// The browser's paste event carries the clipboard to the input handler.
|
||||
if !cfg!(target_family = "wasm") {
|
||||
bindings.push(KeyBinding::new("secondary-v", Paste, context));
|
||||
}
|
||||
if cfg!(target_os = "macos") {
|
||||
bindings.extend([
|
||||
KeyBinding::new("cmd-left", LineStart, context),
|
||||
@@ -261,7 +264,11 @@ pub(crate) fn listen<E: InteractiveElement>(root: E, cx: &mut Context<CodeEditor
|
||||
let root = on!(root, SelectAll, |e, _, cx| e.select_all(cx));
|
||||
let root = on!(root, Copy, |e, _, cx| e.copy(cx));
|
||||
let root = on!(root, Cut, |e, _, cx| e.cut(cx));
|
||||
let root = on!(root, Paste, |e, _, cx| e.paste(cx));
|
||||
let root = on!(root, Paste, |e, _, cx| {
|
||||
if let Some(text) = cx.read_from_clipboard().and_then(|item| item.text()) {
|
||||
e.paste(&text, cx)
|
||||
}
|
||||
});
|
||||
let root = on!(root, AddCursorAbove, |e, _, cx| e.add_cursor(false, cx));
|
||||
let root = on!(root, AddCursorBelow, |e, _, cx| e.add_cursor(true, cx));
|
||||
let root = on!(root, SelectNext, |e, _, cx| e.select_next(cx));
|
||||
|
||||
+17
-1
@@ -1,6 +1,9 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use gpui::{Entity, EntityInputHandler, KeyUpEvent, Keystroke, TestAppContext, VisualTestContext};
|
||||
use gpui::{
|
||||
ClipboardItem, Entity, EntityInputHandler, KeyUpEvent, Keystroke, TestAppContext,
|
||||
VisualTestContext,
|
||||
};
|
||||
|
||||
use super::{CodeEditor, GhostText, InlayHint, LineNumbers, layout::Row};
|
||||
use crate::theme::Theme;
|
||||
@@ -240,3 +243,16 @@ impl CodeEditor {
|
||||
super::layout::rows(&self.buffer, &hide, &self.marks).contains(&Row::Line(line))
|
||||
}
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn a_browser_paste_gives_each_cursor_its_line(cx: &mut TestAppContext) {
|
||||
let (editor, cx) = editor("a\nb", cx);
|
||||
cx.update(|window, cx| {
|
||||
editor.update(cx, |editor, cx| {
|
||||
let (first, second) = (1..1, 3..3);
|
||||
editor.select([first, second], cx);
|
||||
EntityInputHandler::paste(editor, ClipboardItem::new_string("1\n2".into()), window, cx);
|
||||
assert_eq!(editor.text(), "a1\nb2");
|
||||
})
|
||||
});
|
||||
}
|
||||
+18
-2
@@ -7,8 +7,8 @@ mod tags;
|
||||
mod upload;
|
||||
|
||||
use gpui::{
|
||||
AppContext as _, Context, Entity, EntityInputHandler, IntoElement, KeyUpEvent, Keystroke,
|
||||
ParentElement, Render, TestAppContext, VisualTestContext, Window, div, px,
|
||||
AppContext as _, ClipboardItem, Context, Entity, EntityInputHandler, IntoElement, KeyUpEvent,
|
||||
Keystroke, ParentElement, Render, TestAppContext, VisualTestContext, Window, div, px,
|
||||
};
|
||||
|
||||
use super::{Input, MaskedInput, NumberInput, PinInput, TextInput, bind_keys};
|
||||
@@ -146,6 +146,22 @@ fn a_committed_composition_obeys_the_filter_and_length(cx: &mut TestAppContext)
|
||||
assert_eq!(text(field, cx), "");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn a_browser_paste_undoes_apart_from_the_typing(cx: &mut TestAppContext) {
|
||||
let (fields, cx) = open(1, false, cx);
|
||||
let field = &fields[0];
|
||||
focus(field, cx);
|
||||
cx.simulate_input("ab");
|
||||
cx.update(|window, cx| {
|
||||
field.update(cx, |input, cx| {
|
||||
EntityInputHandler::paste(input, ClipboardItem::new_string("cd".into()), window, cx)
|
||||
})
|
||||
});
|
||||
assert_eq!(text(field, cx), "abcd");
|
||||
cx.simulate_keystrokes("cmd-z");
|
||||
assert_eq!(text(field, cx), "ab");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn undo_leaves_a_disabled_field_alone(cx: &mut TestAppContext) {
|
||||
let (fields, cx) = open(1, false, cx);
|
||||
|
||||
@@ -82,7 +82,6 @@ pub(crate) fn bind_keys(cx: &mut App) {
|
||||
KeyBinding::new("secondary-a", SelectAll, Some(CONTEXT)),
|
||||
KeyBinding::new("secondary-c", Copy, Some(CONTEXT)),
|
||||
KeyBinding::new("secondary-x", Cut, Some(CONTEXT)),
|
||||
KeyBinding::new("secondary-v", Paste, Some(CONTEXT)),
|
||||
KeyBinding::new("secondary-z", Undo, Some(CONTEXT)),
|
||||
KeyBinding::new("secondary-shift-z", Redo, Some(CONTEXT)),
|
||||
KeyBinding::new("enter", Enter, Some(CONTEXT)),
|
||||
@@ -90,6 +89,10 @@ pub(crate) fn bind_keys(cx: &mut App) {
|
||||
KeyBinding::new("secondary-enter", Submit, Some(CONTEXT)),
|
||||
KeyBinding::new("secondary-enter", Submit, Some(FORM_CONTEXT)),
|
||||
];
|
||||
// The browser's paste event carries the clipboard to the input handler.
|
||||
if !cfg!(target_family = "wasm") {
|
||||
bindings.push(KeyBinding::new("secondary-v", Paste, Some(CONTEXT)));
|
||||
}
|
||||
if cfg!(target_os = "macos") {
|
||||
bindings.extend([
|
||||
KeyBinding::new("cmd-left", Home, Some(CONTEXT)),
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use gpui::{Bounds, Context, EntityInputHandler, Pixels, Point, UTF16Selection, Window};
|
||||
use gpui::{
|
||||
Bounds, ClipboardItem, Context, EntityInputHandler, Pixels, Point, UTF16Selection, Window,
|
||||
};
|
||||
|
||||
use super::{
|
||||
TextInput,
|
||||
@@ -18,6 +20,12 @@ impl TextInput {
|
||||
}
|
||||
|
||||
impl EntityInputHandler for TextInput {
|
||||
fn paste(&mut self, item: ClipboardItem, _: &mut Window, cx: &mut Context<Self>) {
|
||||
if let Some(text) = item.text() {
|
||||
self.replace(self.selection.clone(), &text, false, cx);
|
||||
}
|
||||
}
|
||||
|
||||
fn text_for_range(
|
||||
&mut self,
|
||||
range_utf16: Range<usize>,
|
||||
|
||||
@@ -284,6 +284,7 @@ pub(crate) fn keys(
|
||||
))),
|
||||
("v", true) => {
|
||||
let Some(text) = cx.read_from_clipboard().and_then(|item| item.text()) else {
|
||||
log::info!("grid: the clipboard holds no text to paste");
|
||||
return;
|
||||
};
|
||||
let edits = pasted(&text, (row, col), (rows, cols));
|
||||
|
||||
Reference in new issue
Block a user