feat(plugins): add PastedText Event (#3962)

* working with text paste

* handle utf8 conversion error

* feat(plugins): add PastedText Event
This commit is contained in:
Aram Drevekenin 2025-01-31 16:49:24 +01:00 committed by GitHub
parent ed12efd454
commit af120de6db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 64 additions and 6 deletions

View file

@ -100,6 +100,7 @@ pub(crate) struct PluginPane {
arrow_fonts: bool,
styled_underlines: bool,
should_be_suppressed: bool,
text_being_pasted: Option<Vec<u8>>,
}
impl PluginPane {
@ -154,6 +155,7 @@ impl PluginPane {
arrow_fonts,
styled_underlines,
should_be_suppressed: false,
text_being_pasted: None,
};
for client_id in currently_connected_clients {
plugin.handle_plugin_bytes(client_id, initial_loading_message.as_bytes().to_vec());
@ -248,8 +250,9 @@ impl Pane for PluginPane {
fn adjust_input_to_terminal(
&mut self,
key_with_modifier: &Option<KeyWithModifier>,
raw_input_bytes: Vec<u8>,
mut raw_input_bytes: Vec<u8>,
_raw_input_bytes_are_kitty: bool,
client_id: Option<ClientId>,
) -> Option<AdjustedInput> {
if let Some(requesting_permissions) = &self.requesting_permissions {
let permissions = requesting_permissions.permissions.clone();
@ -286,10 +289,29 @@ impl Pane for PluginPane {
}
} else if let Some(key_with_modifier) = key_with_modifier {
Some(AdjustedInput::WriteKeyToPlugin(key_with_modifier.clone()))
} else if raw_input_bytes.as_slice() == BRACKETED_PASTE_BEGIN
|| raw_input_bytes.as_slice() == BRACKETED_PASTE_END
{
// plugins do not need bracketed paste
} else if raw_input_bytes.as_slice() == BRACKETED_PASTE_BEGIN {
self.text_being_pasted = Some(vec![]);
None
} else if raw_input_bytes.as_slice() == BRACKETED_PASTE_END {
if let Some(text_being_pasted) = self.text_being_pasted.take() {
match String::from_utf8(text_being_pasted) {
Ok(pasted_text) => {
let _ = self
.send_plugin_instructions
.send(PluginInstruction::Update(vec![(
Some(self.pid),
client_id,
Event::PastedText(pasted_text),
)]));
},
Err(e) => {
log::error!("Failed to convert pasted bytes as utf8 {:?}", e);
},
}
}
None
} else if let Some(pasted_text) = self.text_being_pasted.as_mut() {
pasted_text.append(&mut raw_input_bytes);
None
} else {
Some(AdjustedInput::WriteBytesToTerminal(raw_input_bytes))

View file

@ -213,6 +213,7 @@ impl Pane for TerminalPane {
key_with_modifier: &Option<KeyWithModifier>,
raw_input_bytes: Vec<u8>,
raw_input_bytes_are_kitty: bool,
_client_id: Option<ClientId>,
) -> Option<AdjustedInput> {
// there are some cases in which the terminal state means that input sent to it
// needs to be adjusted.

View file

@ -229,6 +229,7 @@ pub trait Pane {
_key_with_modifier: &Option<KeyWithModifier>,
_raw_input_bytes: Vec<u8>,
_raw_input_bytes_are_kitty: bool,
_client_id: Option<ClientId>,
) -> Option<AdjustedInput> {
None
}
@ -1874,6 +1875,7 @@ impl Tab {
key_with_modifier,
raw_input_bytes,
raw_input_bytes_are_kitty,
client_id,
) {
Some(AdjustedInput::WriteBytesToTerminal(adjusted_input)) => {
self.senders
@ -1916,6 +1918,7 @@ impl Tab {
key_with_modifier,
raw_input_bytes,
raw_input_bytes_are_kitty,
client_id,
) {
Some(AdjustedInput::WriteKeyToPlugin(key_with_modifier)) => {
self.senders

View file

@ -11,7 +11,7 @@ pub struct Event {
pub name: i32,
#[prost(
oneof = "event::Payload",
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25"
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26"
)]
pub payload: ::core::option::Option<event::Payload>,
}
@ -68,10 +68,18 @@ pub mod event {
HostFolderChangedPayload(super::HostFolderChangedPayload),
#[prost(message, tag = "25")]
FailedToChangeHostFolderPayload(super::FailedToChangeHostFolderPayload),
#[prost(message, tag = "26")]
PastedTextPayload(super::PastedTextPayload),
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct PastedTextPayload {
#[prost(string, tag = "1")]
pub pasted_text: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct FailedToChangeHostFolderPayload {
#[prost(string, optional, tag = "1")]
pub error_message: ::core::option::Option<::prost::alloc::string::String>,
@ -494,6 +502,7 @@ pub enum EventType {
ListClients = 26,
HostFolderChanged = 27,
FailedToChangeHostFolder = 28,
PastedText = 29,
}
impl EventType {
/// String value of the enum field names used in the ProtoBuf definition.
@ -531,6 +540,7 @@ impl EventType {
EventType::ListClients => "ListClients",
EventType::HostFolderChanged => "HostFolderChanged",
EventType::FailedToChangeHostFolder => "FailedToChangeHostFolder",
EventType::PastedText => "PastedText",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
@ -565,6 +575,7 @@ impl EventType {
"ListClients" => Some(Self::ListClients),
"HostFolderChanged" => Some(Self::HostFolderChanged),
"FailedToChangeHostFolder" => Some(Self::FailedToChangeHostFolder),
"PastedText" => Some(Self::PastedText),
_ => None,
}
}

View file

@ -914,6 +914,7 @@ pub enum Event {
ListClients(Vec<ClientInfo>),
HostFolderChanged(PathBuf), // PathBuf -> new host folder
FailedToChangeHostFolder(Option<String>), // String -> the error we got when changing
PastedText(String),
}
#[derive(

View file

@ -52,6 +52,7 @@ enum EventType {
ListClients = 26;
HostFolderChanged = 27;
FailedToChangeHostFolder = 28;
PastedText = 29;
}
message EventNameList {
@ -85,9 +86,14 @@ message Event {
ListClientsPayload list_clients_payload = 23;
HostFolderChangedPayload host_folder_changed_payload = 24;
FailedToChangeHostFolderPayload failed_to_change_host_folder_payload = 25;
PastedTextPayload pasted_text_payload = 26;
}
}
message PastedTextPayload {
string pasted_text = 1;
}
message FailedToChangeHostFolderPayload {
optional string error_message = 1;
}

View file

@ -349,6 +349,12 @@ impl TryFrom<ProtobufEvent> for Event {
)),
_ => Err("Malformed payload for the FailedToChangeHostFolder Event"),
},
Some(ProtobufEventType::PastedText) => match protobuf_event.payload {
Some(ProtobufEventPayload::PastedTextPayload(pasted_text_payload)) => {
Ok(Event::PastedText(pasted_text_payload.pasted_text))
},
_ => Err("Malformed payload for the PastedText Event"),
},
None => Err("Unknown Protobuf Event"),
}
}
@ -713,6 +719,12 @@ impl TryFrom<Event> for ProtobufEvent {
FailedToChangeHostFolderPayload { error_message },
)),
}),
Event::PastedText(pasted_text) => Ok(ProtobufEvent {
name: ProtobufEventType::PastedText as i32,
payload: Some(event::Payload::PastedTextPayload(PastedTextPayload {
pasted_text,
})),
}),
}
}
}
@ -1268,6 +1280,7 @@ impl TryFrom<ProtobufEventType> for EventType {
ProtobufEventType::ListClients => EventType::ListClients,
ProtobufEventType::HostFolderChanged => EventType::HostFolderChanged,
ProtobufEventType::FailedToChangeHostFolder => EventType::FailedToChangeHostFolder,
ProtobufEventType::PastedText => EventType::PastedText,
})
}
}
@ -1305,6 +1318,7 @@ impl TryFrom<EventType> for ProtobufEventType {
EventType::ListClients => ProtobufEventType::ListClients,
EventType::HostFolderChanged => ProtobufEventType::HostFolderChanged,
EventType::FailedToChangeHostFolder => ProtobufEventType::FailedToChangeHostFolder,
EventType::PastedText => ProtobufEventType::PastedText,
})
}
}