1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-23 15:04:36 +03:00

wezterm: add confirm parameter to CloseCurrentTab

When confirmation is enabled, a really basic overlay is
rendered over the top of the tab to request confirmation.

The default key assignment for CloseCurrentTab now
has confirmation enabled.

```lua
action=wezterm.action{CloseCurrentTab={confirm=true}}

action=wezterm.action{CloseCurrentTab={confirm=false}}
```

refs: https://github.com/wez/wezterm/issues/157
refs: https://github.com/wez/wezterm/issues/280
This commit is contained in:
Wez Furlong 2020-10-01 22:19:42 -07:00
parent 1b9d561e56
commit b2911ccc41
5 changed files with 86 additions and 19 deletions

View File

@ -1,4 +1,4 @@
use crate::mux::tab::PaneId;
use crate::mux::tab::{PaneId, TabId};
use crate::mux::window::WindowId;
use crate::mux::Mux;
use crate::termwiztermtab::TermWizTerminal;
@ -58,3 +58,51 @@ pub fn confirm_close_pane(
Ok(())
}
pub fn confirm_close_tab(
tab_id: TabId,
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 tab and all contained panes? [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();
mux.remove_tab(tab_id);
});
break;
}
InputEvent::Key(KeyEvent {
key: KeyCode::Char('n'),
..
})
| InputEvent::Key(KeyEvent {
key: KeyCode::Escape,
..
}) => {
break;
}
_ => {}
}
}
Ok(())
}

View File

@ -11,6 +11,7 @@ mod search;
mod tabnavigator;
pub use confirm_close_pane::confirm_close_pane;
pub use confirm_close_pane::confirm_close_tab;
pub use copy::CopyOverlay;
pub use launcher::launcher;
pub use search::SearchOverlay;

View File

@ -9,8 +9,8 @@ use crate::font::FontConfiguration;
use crate::frontend::activity::Activity;
use crate::frontend::front_end;
use crate::frontend::gui::overlay::{
confirm_close_pane, launcher, start_overlay, start_overlay_pane, tab_navigator, CopyOverlay,
SearchOverlay,
confirm_close_pane, confirm_close_tab, launcher, start_overlay, start_overlay_pane,
tab_navigator, CopyOverlay, SearchOverlay,
};
use crate::frontend::gui::scrollbar::*;
use crate::frontend::gui::selection::*;
@ -1855,7 +1855,7 @@ impl TermWindow {
w.show();
}
}
CloseCurrentTab => self.close_current_tab(),
CloseCurrentTab { confirm } => self.close_current_tab(*confirm),
CloseCurrentPane { confirm } => self.close_current_pane(*confirm),
Nop | DisableDefaultAssignment => {}
ReloadConfiguration => crate::config::reload(),
@ -2153,17 +2153,23 @@ impl TermWindow {
}
}
fn close_current_tab(&mut self) {
fn close_current_tab(&mut self, confirm: bool) {
let mux = Mux::get().unwrap();
let tab = match mux.get_active_tab_for_window(self.mux_window_id) {
Some(tab) => tab,
None => return,
};
mux.remove_tab(tab.tab_id());
if let Some(mut win) = mux.get_window_mut(self.mux_window_id) {
win.remove_by_id(tab.tab_id());
let tab_id = tab.tab_id();
let mux_window_id = self.mux_window_id;
if confirm {
let (overlay, future) = start_overlay(self, &tab, move |tab_id, term| {
confirm_close_tab(tab_id, term, mux_window_id)
});
self.assign_overlay(tab_id, overlay);
promise::spawn::spawn(future);
} else {
mux.remove_tab(tab_id);
}
self.activate_tab_relative(0).ok();
}
fn close_tab_idx(&mut self, idx: usize) -> anyhow::Result<()> {

View File

@ -97,7 +97,7 @@ pub enum KeyAssignment {
DisableDefaultAssignment,
Hide,
Show,
CloseCurrentTab,
CloseCurrentTab { confirm: bool },
ReloadConfiguration,
MoveTabRelative(isize),
MoveTab(usize),
@ -227,7 +227,11 @@ impl InputMap {
[KeyModifiers::SUPER, KeyCode::Char('7'), ActivateTab(6)],
[KeyModifiers::SUPER, KeyCode::Char('8'), ActivateTab(7)],
[KeyModifiers::SUPER, KeyCode::Char('9'), ActivateTab(-1)],
[KeyModifiers::SUPER, KeyCode::Char('w'), CloseCurrentTab],
[
KeyModifiers::SUPER,
KeyCode::Char('w'),
CloseCurrentTab { confirm: true }
],
[ctrl_shift, KeyCode::Char('1'), ActivateTab(0)],
[ctrl_shift, KeyCode::Char('2'), ActivateTab(1)],
[ctrl_shift, KeyCode::Char('3'), ActivateTab(2)],
@ -237,7 +241,11 @@ impl InputMap {
[ctrl_shift, KeyCode::Char('7'), ActivateTab(6)],
[ctrl_shift, KeyCode::Char('8'), ActivateTab(7)],
[ctrl_shift, KeyCode::Char('9'), ActivateTab(-1)],
[KeyModifiers::CTRL, KeyCode::Char('W'), CloseCurrentTab],
[
KeyModifiers::CTRL,
KeyCode::Char('W'),
CloseCurrentTab { confirm: true }
],
[
KeyModifiers::SUPER | KeyModifiers::SHIFT,
KeyCode::Char('['),

View File

@ -231,17 +231,20 @@ impl Mux {
}
}
fn remove_tab_internal(&self, tab_id: TabId) {
fn remove_tab_internal(&self, tab_id: TabId) -> Option<Rc<Tab>> {
log::debug!("remove_tab_internal tab {}", tab_id);
let tab = self.tabs.borrow_mut().remove(&tab_id)?;
let mut pane_ids = vec![];
if let Some(tab) = self.tabs.borrow_mut().remove(&tab_id) {
for pos in tab.iter_panes() {
pane_ids.push(pos.pane.pane_id());
}
for pos in tab.iter_panes() {
pane_ids.push(pos.pane.pane_id());
}
for pane_id in pane_ids {
self.remove_pane_internal(pane_id);
}
Some(tab)
}
fn remove_window_internal(&self, window_id: WindowId) {
@ -259,9 +262,10 @@ impl Mux {
self.prune_dead_windows();
}
pub fn remove_tab(&self, tab_id: TabId) {
self.remove_tab_internal(tab_id);
pub fn remove_tab(&self, tab_id: TabId) -> Option<Rc<Tab>> {
let tab = self.remove_tab_internal(tab_id);
self.prune_dead_windows();
tab
}
pub fn prune_dead_windows(&self) {