diff --git a/crates/terminal/src/connected_el.rs b/crates/terminal/src/connected_el.rs index b4369ab55e..000338c680 100644 --- a/crates/terminal/src/connected_el.rs +++ b/crates/terminal/src/connected_el.rs @@ -33,7 +33,9 @@ use std::{ use std::{fmt::Debug, ops::Sub}; use crate::{ - connected_view::ConnectedView, mappings::colors::convert_color, Terminal, TerminalSize, + connected_view::{ConnectedView, DeployContextMenu}, + mappings::colors::convert_color, + Terminal, TerminalSize, }; ///Scrolling is unbearably sluggish by default. Alacritty supports a configurable @@ -463,6 +465,12 @@ impl TerminalEl { } }, ) + .on_click( + MouseButton::Right, + move |MouseButtonEvent { position, .. }, cx| { + cx.dispatch_action(DeployContextMenu { position }); + }, + ) .on_drag( MouseButton::Left, move |_, MouseMovedEvent { position, .. }, cx| { diff --git a/crates/terminal/src/connected_view.rs b/crates/terminal/src/connected_view.rs index e6e10c84bf..5e336dcb03 100644 --- a/crates/terminal/src/connected_view.rs +++ b/crates/terminal/src/connected_view.rs @@ -1,8 +1,14 @@ use alacritty_terminal::term::TermMode; +use context_menu::{ContextMenu, ContextMenuItem}; use gpui::{ - actions, keymap::Keystroke, AppContext, Element, ElementBox, ModelHandle, MutableAppContext, - View, ViewContext, + actions, + elements::{ChildView, ParentElement, Stack}, + geometry::vector::Vector2F, + impl_internal_actions, + keymap::Keystroke, + AppContext, Element, ElementBox, ModelHandle, MutableAppContext, View, ViewContext, ViewHandle, }; +use workspace::pane; use crate::{connected_el::TerminalEl, Event, Terminal}; @@ -10,10 +16,16 @@ use crate::{connected_el::TerminalEl, Event, Terminal}; #[derive(Clone, Debug, PartialEq)] pub struct ScrollTerminal(pub i32); +#[derive(Clone, PartialEq)] +pub struct DeployContextMenu { + pub position: Vector2F, +} + actions!( terminal, [Up, Down, CtrlC, Escape, Enter, Clear, Copy, Paste,] ); +impl_internal_actions!(project_panel, [DeployContextMenu]); pub fn init(cx: &mut MutableAppContext) { //Global binding overrrides @@ -23,6 +35,7 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(ConnectedView::escape); cx.add_action(ConnectedView::enter); //Useful terminal views + cx.add_action(ConnectedView::deploy_context_menu); cx.add_action(ConnectedView::copy); cx.add_action(ConnectedView::paste); cx.add_action(ConnectedView::clear); @@ -36,6 +49,7 @@ pub struct ConnectedView { has_bell: bool, // Only for styling purposes. Doesn't effect behavior modal: bool, + context_menu: ViewHandle, } impl ConnectedView { @@ -67,6 +81,7 @@ impl ConnectedView { has_new_content: true, has_bell: false, modal, + context_menu: cx.add_view(|cx| ContextMenu::new(cx)), } } @@ -87,6 +102,18 @@ impl ConnectedView { cx.emit(Event::Wakeup); } + pub fn deploy_context_menu(&mut self, action: &DeployContextMenu, cx: &mut ViewContext) { + let menu_entries = vec![ + ContextMenuItem::item("Clear Buffer", Clear), + ContextMenuItem::item("Close Terminal", pane::CloseActiveItem), + ]; + + self.context_menu + .update(cx, |menu, cx| menu.show(action.position, menu_entries, cx)); + + cx.notify(); + } + fn clear(&mut self, _: &Clear, cx: &mut ViewContext) { self.terminal.update(cx, |term, _| term.clear()); } @@ -151,8 +178,14 @@ impl View for ConnectedView { fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox { let terminal_handle = self.terminal.clone().downgrade(); - TerminalEl::new(cx.handle(), terminal_handle, self.modal) - .contained() + + Stack::new() + .with_child( + TerminalEl::new(cx.handle(), terminal_handle, self.modal) + .contained() + .boxed(), + ) + .with_child(ChildView::new(&self.context_menu).boxed()) .boxed() } diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 4c27795d97..4e5ca37a9d 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -27,7 +27,6 @@ use futures::{ use modal::deploy_modal; use settings::{Settings, Shell}; use std::{collections::HashMap, fmt::Display, path::PathBuf, sync::Arc, time::Duration}; -use terminal_view::TerminalView; use thiserror::Error; use gpui::{ @@ -43,9 +42,9 @@ use crate::mappings::{ ///Initialize and register all of our action handlers pub fn init(cx: &mut MutableAppContext) { - cx.add_action(TerminalView::deploy); cx.add_action(deploy_modal); + terminal_view::init(cx); connected_view::init(cx); } diff --git a/crates/terminal/src/terminal_view.rs b/crates/terminal/src/terminal_view.rs index 309b3be11a..ba6f49af02 100644 --- a/crates/terminal/src/terminal_view.rs +++ b/crates/terminal/src/terminal_view.rs @@ -1,11 +1,11 @@ use crate::connected_view::ConnectedView; use crate::{Event, Terminal, TerminalBuilder, TerminalError}; + use dirs::home_dir; use gpui::{ - actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, View, ViewContext, - ViewHandle, + actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MutableAppContext, View, + ViewContext, ViewHandle, }; -use theme::ContextMenu; use workspace::{Item, Workspace}; use crate::TerminalSize; @@ -18,6 +18,10 @@ use crate::connected_el::TerminalEl; actions!(terminal, [DeployModal]); +pub fn init(cx: &mut MutableAppContext) { + cx.add_action(TerminalView::deploy); +} + //Make terminal view an enum, that can give you views for the error and non-error states //Take away all the result unwrapping in the current TerminalView by making it 'infallible' //Bubble up to deploy(_modal)() calls @@ -40,7 +44,6 @@ pub struct TerminalView { modal: bool, pub content: TerminalContent, associated_directory: Option, - context_menu: ViewHandle, } pub struct ErrorView { @@ -113,7 +116,6 @@ impl TerminalView { modal, content, associated_directory: working_directory, - context_menu: cx.add_view(|cx| ContextMenu::new(cx)), } } @@ -141,7 +143,6 @@ impl View for TerminalView { TerminalContent::Connected(connected) => ChildView::new(connected), TerminalContent::Error(error) => ChildView::new(error), }; - if self.modal { let settings = cx.global::(); let container_style = settings.theme.terminal.modal_container;