Cargo.lock 🔗
@@ -5356,6 +5356,7 @@ dependencies = [
"alacritty_terminal",
"anyhow",
"client",
+ "context_menu",
"dirs 4.0.0",
"editor",
"futures",
Mikayla Maki created
Terminal context menu
Cargo.lock | 1
crates/terminal/Cargo.toml | 1
crates/terminal/src/connected_el.rs | 10 ++++++
crates/terminal/src/connected_view.rs | 41 ++++++++++++++++++++++++++--
crates/terminal/src/terminal.rs | 3 -
crates/terminal/src/terminal_view.rs | 10 ++++--
6 files changed, 56 insertions(+), 10 deletions(-)
@@ -5356,6 +5356,7 @@ dependencies = [
"alacritty_terminal",
"anyhow",
"client",
+ "context_menu",
"dirs 4.0.0",
"editor",
"futures",
@@ -16,6 +16,7 @@ theme = { path = "../theme" }
settings = { path = "../settings" }
workspace = { path = "../workspace" }
project = { path = "../project" }
+context_menu = { path = "../context_menu" }
smallvec = { version = "1.6", features = ["union"] }
smol = "1.2.5"
mio-extras = "2.0.6"
@@ -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| {
@@ -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<ContextMenu>,
}
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<Self>) {
+ 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>) {
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()
}
@@ -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);
}
@@ -1,9 +1,10 @@
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 workspace::{Item, Workspace};
@@ -17,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
@@ -138,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::<Settings>();
let container_style = settings.theme.terminal.modal_container;