mirror of
https://github.com/wez/wezterm.git
synced 2024-12-24 13:52:55 +03:00
wezterm: add confirm parameter to CloseCurrentPane
When confirmation is enabled, a really basic overlay is rendered over the top of the pane to request confirmation. ```lua action=wezterm.action{CloseCurrentPane={confirm=true}} action=wezterm.action{CloseCurrentPane={confirm=false}} ``` refs: https://github.com/wez/wezterm/issues/157 refs: https://github.com/wez/wezterm/issues/280
This commit is contained in:
parent
f3bccc7d08
commit
1b9d561e56
60
src/frontend/gui/overlay/confirm_close_pane.rs
Normal file
60
src/frontend/gui/overlay/confirm_close_pane.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use crate::mux::tab::PaneId;
|
||||
use crate::mux::window::WindowId;
|
||||
use crate::mux::Mux;
|
||||
use crate::termwiztermtab::TermWizTerminal;
|
||||
use termwiz::color::ColorAttribute;
|
||||
use termwiz::input::{InputEvent, KeyCode, KeyEvent};
|
||||
use termwiz::surface::{Change, Position};
|
||||
use termwiz::terminal::Terminal;
|
||||
|
||||
pub fn confirm_close_pane(
|
||||
pane_id: PaneId,
|
||||
mut term: TermWizTerminal,
|
||||
mux_window_id: WindowId,
|
||||
) -> anyhow::Result<()> {
|
||||
term.set_raw_mode()?;
|
||||
|
||||
let changes = vec![
|
||||
Change::ClearScreen(ColorAttribute::Default),
|
||||
Change::CursorPosition {
|
||||
x: Position::Absolute(0),
|
||||
y: Position::Absolute(0),
|
||||
},
|
||||
Change::Text("Really kill this pane? [y/n]\r\n".to_string()),
|
||||
];
|
||||
|
||||
term.render(&changes)?;
|
||||
term.flush()?;
|
||||
|
||||
while let Ok(Some(event)) = term.poll_input(None) {
|
||||
match event {
|
||||
InputEvent::Key(KeyEvent {
|
||||
key: KeyCode::Char('y'),
|
||||
..
|
||||
}) => {
|
||||
promise::spawn::spawn_into_main_thread(async move {
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(mux_window_id) {
|
||||
Some(tab) => tab,
|
||||
None => return,
|
||||
};
|
||||
tab.kill_pane(pane_id);
|
||||
});
|
||||
break;
|
||||
}
|
||||
InputEvent::Key(KeyEvent {
|
||||
key: KeyCode::Char('n'),
|
||||
..
|
||||
})
|
||||
| InputEvent::Key(KeyEvent {
|
||||
key: KeyCode::Escape,
|
||||
..
|
||||
}) => {
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
@ -1,14 +1,16 @@
|
||||
use crate::frontend::gui::termwindow::TermWindow;
|
||||
use crate::mux::tab::{Pane, Tab, TabId};
|
||||
use crate::mux::tab::{Pane, PaneId, Tab, TabId};
|
||||
use crate::termwiztermtab::{allocate, TermWizTerminal};
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
|
||||
mod confirm_close_pane;
|
||||
mod copy;
|
||||
mod launcher;
|
||||
mod search;
|
||||
mod tabnavigator;
|
||||
|
||||
pub use confirm_close_pane::confirm_close_pane;
|
||||
pub use copy::CopyOverlay;
|
||||
pub use launcher::launcher;
|
||||
pub use search::SearchOverlay;
|
||||
@ -40,3 +42,30 @@ where
|
||||
|
||||
(tw_tab, Box::pin(future))
|
||||
}
|
||||
|
||||
pub fn start_overlay_pane<T, F>(
|
||||
term_window: &TermWindow,
|
||||
pane: &Rc<dyn Pane>,
|
||||
func: F,
|
||||
) -> (
|
||||
Rc<dyn Pane>,
|
||||
Pin<Box<dyn std::future::Future<Output = Option<anyhow::Result<T>>>>>,
|
||||
)
|
||||
where
|
||||
T: Send + 'static,
|
||||
F: Send + 'static + FnOnce(PaneId, TermWizTerminal) -> anyhow::Result<T>,
|
||||
{
|
||||
let pane_id = pane.pane_id();
|
||||
let dims = pane.renderer().get_dimensions();
|
||||
let (tw_term, tw_tab) = allocate(dims.cols.into(), dims.viewport_rows.into());
|
||||
|
||||
let window = term_window.window.clone().unwrap();
|
||||
|
||||
let future = promise::spawn::spawn_into_new_thread(move || {
|
||||
let res = func(pane_id, tw_term);
|
||||
TermWindow::schedule_cancel_overlay_for_pane(window, pane_id);
|
||||
res
|
||||
});
|
||||
|
||||
(tw_tab, Box::pin(future))
|
||||
}
|
||||
|
@ -9,7 +9,8 @@ use crate::font::FontConfiguration;
|
||||
use crate::frontend::activity::Activity;
|
||||
use crate::frontend::front_end;
|
||||
use crate::frontend::gui::overlay::{
|
||||
launcher, start_overlay, tab_navigator, CopyOverlay, SearchOverlay,
|
||||
confirm_close_pane, launcher, start_overlay, start_overlay_pane, tab_navigator, CopyOverlay,
|
||||
SearchOverlay,
|
||||
};
|
||||
use crate::frontend::gui::scrollbar::*;
|
||||
use crate::frontend::gui::selection::*;
|
||||
@ -1855,7 +1856,7 @@ impl TermWindow {
|
||||
}
|
||||
}
|
||||
CloseCurrentTab => self.close_current_tab(),
|
||||
CloseCurrentPane => self.close_active_pane(),
|
||||
CloseCurrentPane { confirm } => self.close_current_pane(*confirm),
|
||||
Nop | DisableDefaultAssignment => {}
|
||||
ReloadConfiguration => crate::config::reload(),
|
||||
MoveTab(n) => self.move_tab(*n)?,
|
||||
@ -2128,13 +2129,28 @@ impl TermWindow {
|
||||
self.scaling_changed(self.dimensions, 1.);
|
||||
}
|
||||
|
||||
fn close_active_pane(&mut self) {
|
||||
fn close_current_pane(&mut self, confirm: bool) {
|
||||
let mux_window_id = self.mux_window_id;
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(self.mux_window_id) {
|
||||
let tab = match mux.get_active_tab_for_window(mux_window_id) {
|
||||
Some(tab) => tab,
|
||||
None => return,
|
||||
};
|
||||
tab.kill_active_pane();
|
||||
let pane = match tab.get_active_pane() {
|
||||
Some(p) => p,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let pane_id = pane.pane_id();
|
||||
if confirm {
|
||||
let (overlay, future) = start_overlay_pane(self, &pane, move |pane_id, term| {
|
||||
confirm_close_pane(pane_id, term, mux_window_id)
|
||||
});
|
||||
self.assign_overlay_for_pane(pane_id, overlay);
|
||||
promise::spawn::spawn(future);
|
||||
} else {
|
||||
tab.kill_pane(pane_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn close_current_tab(&mut self) {
|
||||
|
@ -123,7 +123,7 @@ pub enum KeyAssignment {
|
||||
AdjustPaneSize(PaneDirection, usize),
|
||||
ActivatePaneDirection(PaneDirection),
|
||||
TogglePaneZoomState,
|
||||
CloseCurrentPane,
|
||||
CloseCurrentPane { confirm: bool },
|
||||
}
|
||||
impl_lua_conversion!(KeyAssignment);
|
||||
|
||||
|
@ -1156,11 +1156,8 @@ impl Tab {
|
||||
self.remove_pane_if(|_, pane| pane.is_dead())
|
||||
}
|
||||
|
||||
pub fn kill_active_pane(&self) -> bool {
|
||||
let active_idx = *self.active.borrow();
|
||||
let killed = self.remove_pane_if(|idx, _| idx == active_idx);
|
||||
log::debug!("kill_active_pane: killed={}", killed);
|
||||
killed
|
||||
pub fn kill_pane(&self, pane_id: PaneId) -> bool {
|
||||
self.remove_pane_if(|_, pane| pane.pane_id() == pane_id)
|
||||
}
|
||||
|
||||
pub fn kill_panes_in_domain(&self, domain: DomainId) -> bool {
|
||||
|
Loading…
Reference in New Issue
Block a user