aboutsummaryrefslogtreecommitdiff
path: root/src/app/runtime_commands.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/runtime_commands.rs')
-rw-r--r--src/app/runtime_commands.rs177
1 files changed, 0 insertions, 177 deletions
diff --git a/src/app/runtime_commands.rs b/src/app/runtime_commands.rs
deleted file mode 100644
index ad9b85bc..00000000
--- a/src/app/runtime_commands.rs
+++ /dev/null
@@ -1,177 +0,0 @@
-//! Runtime command launching and overlay pane lifecycle helpers for [`App`].
-
-use std::process::{Command, Stdio};
-
-use ratatui::layout::Direction;
-
-use super::{App, Mode};
-
-#[derive(Debug, Clone, Copy)]
-pub(super) struct OverlayPaneState {
- ws_idx: usize,
- tab_idx: usize,
- previous_focus: crate::layout::PaneId,
- previous_zoomed: bool,
-}
-
-impl App {
- pub(super) fn launch_custom_command(&mut self, binding: crate::config::CustomCommandKeybind) {
- let previous_toast = self.state.toast.clone();
- let result = match binding.action {
- crate::config::CustomCommandAction::Shell => self.spawn_custom_command(&binding),
- crate::config::CustomCommandAction::Pane => self.spawn_pane_command(&binding.command),
- };
- match result {
- Ok(()) => {
- if self.state.active.is_some() {
- self.state.mode = Mode::Terminal;
- }
- }
- Err(err) => {
- self.state.toast = Some(crate::app::state::ToastNotification {
- kind: crate::app::state::ToastKind::NeedsAttention,
- title: "custom command failed".to_string(),
- context: err.to_string(),
- });
- self.sync_toast_deadline(previous_toast);
- }
- }
- }
-
- fn custom_command_env(&self) -> (Vec<(String, String)>, Option<std::path::PathBuf>) {
- let mut env = vec![(
- crate::api::SOCKET_PATH_ENV_VAR.to_string(),
- crate::api::socket_path().display().to_string(),
- )];
- if let Ok(current_exe) = std::env::current_exe() {
- env.push((
- "HERDR_BIN_PATH".to_string(),
- current_exe.display().to_string(),
- ));
- }
-
- let mut cwd = None;
- if let Some(ws_idx) = self.state.active {
- env.push((
- "HERDR_ACTIVE_WORKSPACE_ID".to_string(),
- self.public_workspace_id(ws_idx),
- ));
- if let Some(workspace) = self.state.workspaces.get(ws_idx) {
- let tab_idx = workspace.active_tab_index();
- if let Some(tab_id) = self.public_tab_id(ws_idx, tab_idx) {
- env.push(("HERDR_ACTIVE_TAB_ID".to_string(), tab_id));
- }
- if let Some(pane_id) = workspace.focused_pane_id() {
- if let Some(public_pane_id) = self.public_pane_id(ws_idx, pane_id) {
- env.push(("HERDR_ACTIVE_PANE_ID".to_string(), public_pane_id));
- }
- if let Some(pane_cwd) = workspace
- .active_tab()
- .and_then(|tab| tab.cwd_for_pane(pane_id))
- {
- env.push((
- "HERDR_ACTIVE_PANE_CWD".to_string(),
- pane_cwd.display().to_string(),
- ));
- if pane_cwd.is_dir() {
- cwd = Some(pane_cwd);
- }
- }
- }
- }
- }
- (env, cwd)
- }
-
- fn spawn_custom_command(
- &self,
- binding: &crate::config::CustomCommandKeybind,
- ) -> std::io::Result<()> {
- let mut command = Command::new("/bin/sh");
- command
- .arg("-lc")
- .arg(&binding.command)
- .stdin(Stdio::null())
- .stdout(Stdio::null())
- .stderr(Stdio::null());
- let (env, cwd) = self.custom_command_env();
- command.envs(env);
- if let Some(cwd) = cwd {
- command.current_dir(cwd);
- }
- command.spawn()?;
- Ok(())
- }
-
- fn spawn_pane_command(&mut self, command: &str) -> std::io::Result<()> {
- let Some(ws_idx) = self.state.active else {
- return Err(std::io::Error::other("no active workspace"));
- };
- let (rows, cols) = self.state.estimate_pane_size();
- let new_rows = rows.max(4);
- let new_cols = cols.max(10);
- let (env, _) = self.custom_command_env();
-
- let ws = self
- .state
- .workspaces
- .get_mut(ws_idx)
- .ok_or_else(|| std::io::Error::other("active workspace disappeared"))?;
- let tab_idx = ws.active_tab_index();
- let previous_focus = ws
- .focused_pane_id()
- .ok_or_else(|| std::io::Error::other("no focused pane"))?;
- let previous_zoomed = ws.active_tab().map(|tab| tab.zoomed).unwrap_or(false);
- let cwd = ws
- .active_tab()
- .and_then(|tab| tab.cwd_for_pane(previous_focus));
- let new_pane_id = ws.split_focused_command(
- Direction::Horizontal,
- new_rows,
- new_cols,
- cwd,
- command,
- &env,
- self.state.pane_scrollback_limit_bytes,
- self.state.host_terminal_theme,
- )?;
- ws.active_tab_mut()
- .expect("workspace must have an active tab")
- .layout
- .focus_pane(new_pane_id);
- ws.active_tab_mut()
- .expect("workspace must have an active tab")
- .zoomed = true;
- self.overlay_panes.insert(
- new_pane_id,
- OverlayPaneState {
- ws_idx,
- tab_idx,
- previous_focus,
- previous_zoomed,
- },
- );
- self.state.mode = Mode::Terminal;
- Ok(())
- }
-
- pub(super) fn restore_overlay_after_exit(&mut self, overlay: OverlayPaneState) {
- let Some(ws) = self.state.workspaces.get_mut(overlay.ws_idx) else {
- return;
- };
- if overlay.tab_idx >= ws.tabs.len() {
- return;
- }
-
- ws.active_tab = overlay.tab_idx;
- let tab = &mut ws.tabs[overlay.tab_idx];
- if tab.panes.contains_key(&overlay.previous_focus) {
- tab.layout.focus_pane(overlay.previous_focus);
- }
- tab.zoomed = overlay.previous_zoomed;
-
- if self.state.active == Some(overlay.ws_idx) {
- self.state.mode = Mode::Terminal;
- }
- }
-}