feat: support keybinding configuration for terminal copy/paste and update hint text

This commit is contained in:
TomZz
2026-06-25 02:33:34 +08:00
parent fd19daedad
commit bfc7c9ac83
7 changed files with 46 additions and 7 deletions
+3 -1
View File
@@ -117,7 +117,9 @@ software_builtin: "Built-in"
retry: "Retry"
right_click_copy_paste: "Right-click Copy/Paste"
keyword_highlight: "Terminal Keyword Highlighting"
copy_paste_hint: "Regardless of this switch, you can always use %{key} + C/V to copy/paste."
copy_paste_hint: "Selected text can also be copied by left-clicking."
settings_copy: "Copy Selection"
settings_paste: "Paste Clipboard"
edit_file: "Edit File"
edit_file_tooltip: "Download to temporary directory, open in default editor, and auto upload on save."
auto_saved_and_uploaded: "Auto-saved & uploaded: %{base}"
+3 -1
View File
@@ -118,7 +118,9 @@ software_builtin: "软件内置"
retry: "重试"
right_click_copy_paste: "右键复制/粘贴"
keyword_highlight: "终端关键词高亮"
copy_paste_hint: "不管是否开启此开关,都可以使用 %{key} + C/V 快捷键进行复制和粘贴。"
copy_paste_hint: "选中后左键点击也可复制。"
settings_copy: "复制选区"
settings_paste: "粘贴剪贴板"
edit_file: "编辑文件"
edit_file_tooltip: "下载到临时目录,使用默认编辑器打开,并在保存后自动上传。"
auto_saved_and_uploaded: "已自动保存并上传: %{base}"
+1 -1
View File
@@ -1594,7 +1594,7 @@ impl Ashell {
.into_any_element()
}
})
).description(t!("copy_paste_hint", key = if cfg!(target_os = "macos") { "Command" } else { "Ctrl" }).to_string())
).description(t!("copy_paste_hint").to_string())
)
.item(
SettingItem::new(
+18 -2
View File
@@ -29,7 +29,9 @@ gpui::actions!(
SplitPaneRight,
SplitPaneUp,
SplitPaneDown,
ClosePane
ClosePane,
Copy,
Paste
]
);
@@ -123,6 +125,16 @@ pub(crate) const WORKSPACE_ACTIONS: &[WorkspaceAction] = &[
label_key: "settings_close_pane",
default_suffix: "w",
},
WorkspaceAction {
id: "Copy",
label_key: "settings_copy",
default_suffix: if cfg!(target_os = "macos") { "c" } else { "shift-c" },
},
WorkspaceAction {
id: "Paste",
label_key: "settings_paste",
default_suffix: if cfg!(target_os = "macos") { "v" } else { "shift-v" },
},
];
pub(crate) fn default_modifier() -> &'static str {
@@ -224,6 +236,8 @@ pub(crate) fn unbind_all_workspace_keys(cx: &mut App, config: &ConfigStore) {
unbind_action!("SplitPaneUp", crate::SplitPaneUp);
unbind_action!("SplitPaneDown", crate::SplitPaneDown);
unbind_action!("ClosePane", crate::ClosePane);
unbind_action!("Copy", crate::Copy);
unbind_action!("Paste", crate::Paste);
cx.bind_keys(bindings);
}
@@ -280,6 +294,8 @@ fn bind_workspace_actions(cx: &mut App, config: &ConfigStore) {
bind_action!("SplitPaneUp", crate::SplitPaneUp);
bind_action!("SplitPaneDown", crate::SplitPaneDown);
bind_action!("ClosePane", crate::ClosePane);
bind_action!("Copy", crate::Copy);
bind_action!("Paste", crate::Paste);
cx.bind_keys(bindings);
}
@@ -289,7 +305,7 @@ impl KeybindingsPage {
let groups = [
(
"settings_group_keybind_general",
vec!["OpenSettings", "OpenSession", "OpenTransfers", "NewSsh", "OpenSearch"],
vec!["OpenSettings", "OpenSession", "OpenTransfers", "NewSsh", "OpenSearch", "Copy", "Paste"],
),
(
"settings_group_keybind_zoom",
+19
View File
@@ -2723,6 +2723,25 @@ impl Render for Ashell {
this.close_tab(active_id, cx);
}
}))
.on_action(cx.listener(|this, _: &crate::Copy, window, cx| {
if let Some(text) = this.active_terminal_selection_text() {
cx.write_to_clipboard(gpui::ClipboardItem::new_string(text));
if let Some(active_id) = &this.active_tab {
if let Some(tab) = this.tabs.iter_mut().find(|tab| &tab.id == active_id) {
tab.clear_selection();
}
}
window.prevent_default();
cx.stop_propagation();
}
}))
.on_action(cx.listener(|this, _: &crate::Paste, window, cx| {
if let Some(clipboard) = cx.read_from_clipboard() {
if let Some(text) = clipboard.text() {
this.paste_into_terminal(&text, window, cx);
}
}
}))
.when(self.active_title_bar_style == crate::session::config::TitleBarStyle::Integrated, |this| {
this.child(
div()
+1 -1
View File
@@ -18,7 +18,7 @@ gpui::actions!(ashell_terminal, [TerminalTabKey, TerminalBacktabKey]);
pub(crate) use app::keybinding_recorder::{
ClosePane, FocusPaneDown, FocusPaneLeft, FocusPaneRight, FocusPaneUp, NewSsh, OpenSearch,
OpenSession, OpenSettings, OpenTransfers, SplitPaneDown, SplitPaneLeft, SplitPaneRight,
SplitPaneUp, ToggleSftpZoom, ToggleSidebar,
SplitPaneUp, ToggleSftpZoom, ToggleSidebar, Copy, Paste,
};
pub(crate) use app::{
+1 -1
View File
@@ -190,7 +190,7 @@ impl Ashell {
.and_then(|tab| tab.selection_text())
}
fn paste_into_terminal(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
pub(crate) fn paste_into_terminal(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
let Some(active_id) = self.active_tab.clone() else {
return;
};