aboutsummaryrefslogtreecommitdiff
path: root/src/app/input
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/input')
-rw-r--r--src/app/input/mod.rs12
-rw-r--r--src/app/input/navigate.rs91
2 files changed, 101 insertions, 2 deletions
diff --git a/src/app/input/mod.rs b/src/app/input/mod.rs
index 1b5dfefe..339f7293 100644
--- a/src/app/input/mod.rs
+++ b/src/app/input/mod.rs
@@ -341,6 +341,13 @@ impl App {
};
self.last_pane_click = None;
+ match self.invoke_plugin_link_handler_for_url(&url, info.id) {
+ Ok(true) => return true,
+ Ok(false) => {}
+ Err(err) => {
+ tracing::warn!(err = %err, url = %url, "failed to invoke plugin link handler");
+ }
+ }
if let Err(err) = crate::platform::open_url(&url) {
tracing::warn!(err = %err, url = %url, "failed to open pane URL");
}
@@ -514,6 +521,7 @@ impl AppState {
self.pane_scrollback_limit_bytes,
self.host_terminal_theme,
crate::pane::PaneShellConfig::new(&self.default_shell, self.shell_mode),
+ Vec::new(),
) {
let new_id = new_pane.pane_id;
terminal_runtimes.insert(new_pane.terminal.id.clone(), new_pane.runtime);
@@ -622,7 +630,9 @@ fn wait_for_file(path: &std::path::Path) -> String {
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(2);
while std::time::Instant::now() < deadline {
if let Ok(content) = std::fs::read_to_string(path) {
- return content;
+ if !content.is_empty() {
+ return content;
+ }
}
std::thread::sleep(std::time::Duration::from_millis(20));
}
diff --git a/src/app/input/navigate.rs b/src/app/input/navigate.rs
index b27b5cb9..7072f659 100644
--- a/src/app/input/navigate.rs
+++ b/src/app/input/navigate.rs
@@ -140,6 +140,9 @@ impl App {
crate::config::CustomCommandAction::Pane => {
self.spawn_pane_command(&binding.command, Vec::new())
}
+ crate::config::CustomCommandAction::PluginAction => self
+ .invoke_plugin_action_from_keybind(binding.command.clone())
+ .map_err(std::io::Error::other),
};
match result {
Ok(()) => finish_custom_command_context(&mut self.state, context, previous_mode),
@@ -317,7 +320,7 @@ impl App {
new_cols,
cwd,
command,
- &env,
+ env,
self.state.pane_scrollback_limit_bytes,
self.state.host_terminal_theme,
)?;
@@ -355,6 +358,92 @@ impl App {
self.state.mode = Mode::Terminal;
Ok(())
}
+
+ pub(crate) fn spawn_overlay_argv_command(
+ &mut self,
+ argv: &[String],
+ cwd: Option<std::path::PathBuf>,
+ extra_env: Vec<(String, String)>,
+ temp_files: Vec<std::path::PathBuf>,
+ ) -> std::io::Result<(usize, crate::workspace::NewPane)> {
+ let Some(ws_idx) = self.state.active else {
+ return Err(std::io::Error::other("no active workspace"));
+ };
+ let previous_focus_target = self.state.current_pane_focus_target();
+ let (rows, cols) = self.state.estimate_pane_size();
+ let new_rows = rows.max(4);
+ let new_cols = cols.max(10);
+
+ let ws = self
+ .state
+ .workspaces
+ .get(ws_idx)
+ .ok_or_else(|| std::io::Error::other("active workspace disappeared"))?;
+ let previous_focus = ws
+ .focused_pane_id()
+ .ok_or_else(|| std::io::Error::other("no focused pane"))?;
+ let cwd = cwd.or_else(|| {
+ ws.active_tab().and_then(|tab| {
+ tab.cwd_for_pane(
+ previous_focus,
+ &self.state.terminals,
+ &self.terminal_runtimes,
+ )
+ })
+ });
+
+ let (tab_idx, new_pane, workspace_id) = {
+ let ws = self
+ .state
+ .workspaces
+ .get_mut(ws_idx)
+ .ok_or_else(|| std::io::Error::other("active workspace disappeared"))?;
+ let previous_zoomed = ws.active_tab().map(|tab| tab.zoomed).unwrap_or(false);
+ let result = ws.split_pane_argv_command(
+ previous_focus,
+ Direction::Horizontal,
+ new_rows,
+ new_cols,
+ cwd,
+ argv,
+ extra_env,
+ self.state.pane_scrollback_limit_bytes,
+ self.state.host_terminal_theme,
+ true,
+ );
+ let (tab_idx, new_pane) = match result {
+ Some(Ok(result)) => result,
+ Some(Err(err)) => return Err(err),
+ None => return Err(std::io::Error::other("focused pane disappeared")),
+ };
+ ws.tabs
+ .get_mut(tab_idx)
+ .ok_or_else(|| std::io::Error::other("plugin overlay tab disappeared"))?
+ .zoomed = true;
+ self.overlay_panes.insert(
+ new_pane.pane_id,
+ super::super::OverlayPaneState {
+ ws_idx,
+ tab_idx,
+ previous_focus,
+ previous_zoomed,
+ temp_files,
+ },
+ );
+ (tab_idx, new_pane, ws.id.clone())
+ };
+
+ let new_focus_target = crate::app::state::PaneFocusTarget {
+ workspace_id,
+ pane_id: new_pane.pane_id,
+ };
+ if previous_focus_target.as_ref() != Some(&new_focus_target) {
+ self.state.previous_pane_focus = previous_focus_target;
+ }
+ self.state.switch_workspace_tab(ws_idx, tab_idx);
+ self.state.mode = Mode::Terminal;
+ Ok((ws_idx, new_pane))
+ }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]