Copy/paste images into editors (Mac only) (#15782)

For future reference: WIP branch of copy/pasting a mixture of images and
text: https://github.com/zed-industries/zed/tree/copy-paste-images -
we'll come back to that one after landing this one.

Release Notes:

- You can now paste images into the Assistant Panel to include them as
context. Currently works only on Mac, and with Anthropic models. Future
support is planned for more models, operating systems, and image
clipboard operations.

---------

Co-authored-by: Antonio <antonio@zed.dev>
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Jason <jason@zed.dev>
Co-authored-by: Kyle <kylek@zed.dev>
This commit is contained in:
Richard Feldman 2024-08-13 13:18:25 -04:00 committed by GitHub
parent e3b0de5dda
commit b1a581e81b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
58 changed files with 2983 additions and 1708 deletions

View file

@ -361,7 +361,8 @@ mod test {
Mode::Normal,
);
assert_eq!(
cx.read_from_clipboard().map(|item| item.text().clone()),
cx.read_from_clipboard()
.map(|item| item.text().unwrap().to_string()),
Some("jumps".into())
);
cx.simulate_keystrokes("d d p");
@ -373,10 +374,11 @@ mod test {
Mode::Normal,
);
assert_eq!(
cx.read_from_clipboard().map(|item| item.text().clone()),
cx.read_from_clipboard()
.map(|item| item.text().unwrap().to_string()),
Some("jumps".into())
);
cx.write_to_clipboard(ClipboardItem::new("test-copy".to_string()));
cx.write_to_clipboard(ClipboardItem::new_string("test-copy".to_string()));
cx.simulate_keystrokes("shift-p");
cx.assert_state(
indoc! {"

View file

@ -5,7 +5,7 @@ use crate::surrounds::SurroundsType;
use crate::{motion::Motion, object::Object};
use collections::HashMap;
use editor::{Anchor, ClipboardSelection};
use gpui::{Action, ClipboardItem, KeyContext};
use gpui::{Action, ClipboardEntry, ClipboardItem, KeyContext};
use language::{CursorShape, Selection, TransactionId};
use serde::{Deserialize, Serialize};
use ui::SharedString;
@ -129,20 +129,24 @@ pub struct Register {
impl From<Register> for ClipboardItem {
fn from(register: Register) -> Self {
let item = ClipboardItem::new(register.text.into());
if let Some(clipboard_selections) = register.clipboard_selections {
item.with_metadata(clipboard_selections)
ClipboardItem::new_string_with_json_metadata(register.text.into(), clipboard_selections)
} else {
item
ClipboardItem::new_string(register.text.into())
}
}
}
impl From<ClipboardItem> for Register {
fn from(value: ClipboardItem) -> Self {
Register {
text: value.text().to_owned().into(),
clipboard_selections: value.metadata::<Vec<ClipboardSelection>>(),
fn from(item: ClipboardItem) -> Self {
// For now, we don't store metadata for multiple entries.
match item.entries().first() {
Some(ClipboardEntry::String(value)) if item.entries().len() == 1 => Register {
text: value.text().to_owned().into(),
clipboard_selections: value.metadata_json::<Vec<ClipboardSelection>>(),
},
// For now, registers can't store images. This could change in the future.
_ => Register::default(),
}
}
}

View file

@ -247,7 +247,12 @@ impl NeovimBackedTestContext {
register: '"',
state: self.shared_state().await,
neovim: self.neovim.read_register('"').await,
editor: self.read_from_clipboard().unwrap().text().clone(),
editor: self
.read_from_clipboard()
.unwrap()
.text()
.unwrap()
.to_owned(),
}
}

View file

@ -586,7 +586,7 @@ impl Vim {
} else {
self.workspace_state.last_yank = cx
.read_from_clipboard()
.map(|item| item.text().to_owned().into());
.and_then(|item| item.text().map(|string| string.into()))
}
self.workspace_state.registers.insert('"', content.clone());
@ -663,7 +663,7 @@ impl Vim {
fn system_clipboard_is_newer(&self, cx: &mut AppContext) -> bool {
cx.read_from_clipboard().is_some_and(|item| {
if let Some(last_state) = &self.workspace_state.last_yank {
last_state != item.text()
Some(last_state.as_ref()) != item.text().as_deref()
} else {
true
}

View file

@ -927,7 +927,7 @@ mod test {
the lazy dog"});
assert_eq!(
cx.read_from_clipboard()
.map(|item| item.text().clone())
.map(|item| item.text().unwrap().to_string())
.unwrap(),
"The q"
);