From 6ffa4bb84b55fc7910dd2bb3a503ed85ffa38133 Mon Sep 17 00:00:00 2001 From: ifengqi <362254883@qq.com> Date: Tue, 16 Jul 2024 16:50:34 +0800 Subject: [PATCH] Terminal: right-click to add "clear all" function (#3368) * Terminal: right-click to add "clear all" function * format imports * format imports --- lapce-app/src/command.rs | 6 +++ lapce-app/src/panel/terminal_view.rs | 73 ++++++++++++++++++++-------- lapce-app/src/window_tab.rs | 33 +++++++++++++ 3 files changed, 92 insertions(+), 20 deletions(-) diff --git a/lapce-app/src/command.rs b/lapce-app/src/command.rs index f80d819287..eadc032618 100644 --- a/lapce-app/src/command.rs +++ b/lapce-app/src/command.rs @@ -3,6 +3,7 @@ use std::{path::PathBuf, rc::Rc, sync::Arc}; pub use floem::views::editor::command::CommandExecuted; use floem::{ keyboard::Modifiers, peniko::kurbo::Vec2, views::editor::command::Command, + ViewId, }; use indexmap::IndexMap; use lapce_core::command::{ @@ -732,6 +733,11 @@ pub enum InternalCommand { program: String, arguments: Vec, }, + ClearTerminalBuffer { + view_id: ViewId, + tab_index: usize, + terminal_index: usize, + }, } #[derive(Clone)] diff --git a/lapce-app/src/panel/terminal_view.rs b/lapce-app/src/panel/terminal_view.rs index 39c20840ea..74caabc05c 100644 --- a/lapce-app/src/panel/terminal_view.rs +++ b/lapce-app/src/panel/terminal_view.rs @@ -1,23 +1,26 @@ use std::rc::Rc; use floem::{ + action::show_context_menu, event::{Event, EventListener, EventPropagation}, kurbo::Size, + menu::{Menu, MenuItem}, reactive::create_rw_signal, views::{ container, dyn_stack, empty, label, scroll::{scroll, Thickness, VerticalScrollAsHorizontal}, stack, svg, tab, Decorators, }, - View, + View, ViewId, }; use super::kind::PanelKind; use crate::{ app::clickable_icon, - command::LapceWorkbenchCommand, + command::{InternalCommand, LapceWorkbenchCommand}, config::{color::LapceColor, icon::LapceIcons}, debug::RunDebugMode, + listener::Listener, terminal::{ panel::TerminalPanelData, tab::TerminalTabData, view::terminal_view, }, @@ -252,6 +255,7 @@ fn terminal_tab_header(window_tab_data: Rc) -> impl View { fn terminal_tab_split( terminal_panel_data: TerminalPanelData, terminal_tab_data: TerminalTabData, + tab_index: usize, ) -> impl View { let config = terminal_panel_data.common.config; let internal_command = terminal_panel_data.common.internal_command; @@ -273,7 +277,7 @@ fn terminal_tab_split( let terminal_panel_data = terminal_panel_data.clone(); let terminal_scope = terminal.scope; container({ - terminal_view( + let terminal_view = terminal_view( terminal.term_id, terminal.raw.read_only(), terminal.mode.read_only(), @@ -282,22 +286,32 @@ fn terminal_tab_split( terminal.launch_error, internal_command, workspace.clone(), - ) - .on_event_cont(EventListener::PointerDown, move |_| { - active.set(index.get_untracked()); - }) - .on_event(EventListener::PointerWheel, move |event| { - if let Event::PointerWheel(pointer_event) = event { - terminal.clone().wheel_scroll(pointer_event.delta.y); - EventPropagation::Stop - } else { - EventPropagation::Continue - } - }) - .on_cleanup(move || { - terminal_scope.dispose(); - }) - .style(|s| s.size_pct(100.0, 100.0)) + ); + let view_id = terminal_view.id(); + terminal_view + .on_event_cont(EventListener::PointerDown, move |_| { + active.set(index.get_untracked()); + }) + .on_secondary_click_stop(move |_| { + tab_secondary_click( + internal_command, + view_id, + tab_index, + index.get_untracked(), + ); + }) + .on_event(EventListener::PointerWheel, move |event| { + if let Event::PointerWheel(pointer_event) = event { + terminal.clone().wheel_scroll(pointer_event.delta.y); + EventPropagation::Stop + } else { + EventPropagation::Continue + } + }) + .on_cleanup(move || { + terminal_scope.dispose(); + }) + .style(|s| s.size_pct(100.0, 100.0)) }) .style(move |s| { s.size_pct(100.0, 100.0).padding_horiz(10.0).apply_if( @@ -323,7 +337,26 @@ fn terminal_tab_content(window_tab_data: Rc) -> impl View { move || terminal.tab_info.with(|info| info.active), move || terminal.tab_info.with(|info| info.tabs.clone()), |(_, tab)| tab.terminal_tab_id, - move |(_, tab)| terminal_tab_split(terminal.clone(), tab), + move |(tab_index, tab)| { + terminal_tab_split(terminal.clone(), tab, tab_index.get_untracked()) + }, ) .style(|s| s.size_pct(100.0, 100.0)) } + +fn tab_secondary_click( + internal_command: Listener, + view_id: ViewId, + tab_index: usize, + terminal_index: usize, +) { + let mut menu = Menu::new(""); + menu = menu.entry(MenuItem::new("Clear All").action(move || { + internal_command.send(InternalCommand::ClearTerminalBuffer { + view_id, + tab_index, + terminal_index, + }); + })); + show_context_menu(menu, None); +} diff --git a/lapce-app/src/window_tab.rs b/lapce-app/src/window_tab.rs index 113b3ffea8..2e963b5b58 100644 --- a/lapce-app/src/window_tab.rs +++ b/lapce-app/src/window_tab.rs @@ -1,3 +1,4 @@ +use alacritty_terminal::vte::ansi::Handler; use std::{ collections::{BTreeMap, HashSet}, env, @@ -1790,6 +1791,38 @@ impl WindowTabData { } }; } + InternalCommand::ClearTerminalBuffer { + view_id, + tab_index, + terminal_index, + } => { + let Some(tab) = self.terminal.tab_info.with_untracked(|x| { + x.tabs.iter().find_map(|(index, data)| { + if index.get_untracked() == tab_index { + Some(data.clone()) + } else { + None + } + }) + }) else { + error!("cound not find terminal tab data: index={tab_index}"); + return; + }; + let Some(raw) = tab.terminals.with_untracked(|x| { + x.iter().find_map(|(index, data)| { + if index.get_untracked() == terminal_index { + Some(data.raw.get_untracked()) + } else { + None + } + }) + }) else { + error!("cound not find terminal data: index={terminal_index}"); + return; + }; + raw.write().term.reset_state(); + view_id.request_paint(); + } } }