From 38b9f33979ae2a736d2f75fbd3f95dbf7552b441 Mon Sep 17 00:00:00 2001 From: T Date: Sun, 22 Mar 2026 02:18:07 +0700 Subject: [PATCH 1/2] fix(tmux): make tmux work as editor regardless of post:open hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add `open_editor_or_terminal` which uses terminal-specific spawn logic (tmux new-session/new-window) when cmd is a known terminal, falling back to `open_in_editor` for IDEs — fixes the `(Some(cmd), None)` path - Wire `(Some(cmd), None)` in `cmd_open` to `open_editor_or_terminal` instead of `open_in_editor` so tmux users without a post:open hook no longer get the invalid `tmux /path/to/worktree` invocation - Add tmux check in `open_hook_in_auto_terminal` so hook-only users (IDE + post:open hook) also prefer tmux over GUI terminals Closes #52 Co-Authored-By: Claude Sonnet 4.6 --- src/commands/open/mod.rs | 2 +- src/opener/mod.rs | 20 +++++++++++++++----- src/opener/opener_tests.rs | 5 +++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/commands/open/mod.rs b/src/commands/open/mod.rs index d368104..021462e 100644 --- a/src/commands/open/mod.rs +++ b/src/commands/open/mod.rs @@ -83,7 +83,7 @@ pub fn cmd_open(issue_ref: Option<&str>, force_editor: bool, no_hooks: bool) -> } } (Some(cmd), None) => { - opener::open_in_editor(&workspace.path, cmd, config.editor.background)?; + opener::open_editor_or_terminal(&workspace.path, cmd, config.editor.background)?; } (None, Some(script)) => { eprintln!("Running post:open hook…"); diff --git a/src/opener/mod.rs b/src/opener/mod.rs index a686981..08c1eb1 100644 --- a/src/opener/mod.rs +++ b/src/opener/mod.rs @@ -28,7 +28,10 @@ fn open_hook_in_auto_terminal(path: &Path, init_script: &str) -> Result { if which::which("wt").is_ok() && terminal::try_terminal_with_init(path, "wt", init_script)? { return Ok(true); } - + if which::which("tmux").is_ok() && terminal::try_terminal_with_init(path, "tmux", init_script)? + { + return Ok(true); + } #[cfg(target_os = "macos")] { let candidates: &[(&str, &str)] = &[ @@ -45,7 +48,6 @@ fn open_hook_in_auto_terminal(path: &Path, init_script: &str) -> Result { // LLVM_COV_EXCL_STOP } } - Ok(false) } @@ -56,9 +58,7 @@ fn open_hook_in_auto_terminal(path: &Path, init_script: &str) -> Result { /// Returns an error if the editor or terminal command fails to spawn. pub fn open_with_hook(path: &Path, cmd: &str, init: &str, background: bool) -> Result { if terminal::try_terminal_with_init(path, cmd, init)? { - // LLVM_COV_EXCL_START return Ok(true); - // LLVM_COV_EXCL_STOP } open_in_editor(path, cmd, background)?; open_hook_in_auto_terminal(path, init) @@ -74,7 +74,6 @@ pub fn open_in_editor(path: &Path, command: &str, background: bool) -> Result<() let path_str = path .to_str() .context("Workspace path contains non-UTF-8 characters")?; - let cmd_str = if command.contains(" . ") || command.ends_with(" .") || command == "." { command.replacen(" .", &format!(" {path_str}"), 1) } else { @@ -85,6 +84,17 @@ pub fn open_in_editor(path: &Path, command: &str, background: bool) -> Result<() .with_context(|| format!("Failed to open editor with command: {cmd_str}")) } +/// Open `path` with `cmd`; uses terminal-specific logic if `cmd` is a known terminal, +/// otherwise opens as an editor. +/// # Errors +/// Returns an error if the spawn or editor command fails. +pub fn open_editor_or_terminal(path: &Path, cmd: &str, background: bool) -> Result<()> { + if !terminal::try_terminal_with_init(path, cmd, "")? { + open_in_editor(path, cmd, background)?; + } + Ok(()) +} + #[cfg(test)] #[path = "opener_tests.rs"] mod tests; diff --git a/src/opener/opener_tests.rs b/src/opener/opener_tests.rs index 5082dfe..c2b6d95 100644 --- a/src/opener/opener_tests.rs +++ b/src/opener/opener_tests.rs @@ -25,3 +25,8 @@ fn test_open_in_editor_background() { let p = std::path::Path::new("/tmp/myproject"); open_in_editor(p, "echo", true).unwrap(); } +#[test] +fn test_open_editor_or_terminal_ide() { + let p = std::path::Path::new("/tmp/myproject"); + open_editor_or_terminal(p, "echo .", false).unwrap(); +} From 69ea252f40aa3f67d28dcd52599e32fb8069e98f Mon Sep 17 00:00:00 2001 From: T Date: Sun, 22 Mar 2026 02:18:48 +0700 Subject: [PATCH 2/2] chore(centy): close issue #52 Co-Authored-By: Claude Sonnet 4.6 --- .centy/issues/5702708c-716d-4edc-ad72-c83bde1e514d.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.centy/issues/5702708c-716d-4edc-ad72-c83bde1e514d.md b/.centy/issues/5702708c-716d-4edc-ad72-c83bde1e514d.md index 401aa0e..1e426b5 100644 --- a/.centy/issues/5702708c-716d-4edc-ad72-c83bde1e514d.md +++ b/.centy/issues/5702708c-716d-4edc-ad72-c83bde1e514d.md @@ -1,10 +1,10 @@ --- # This file is managed by Centy. Use the Centy CLI to modify it. displayNumber: 52 -status: in-progress +status: closed priority: 2 createdAt: 2026-03-21T19:08:45.344228+00:00 -updatedAt: 2026-03-21T19:09:55.102321+00:00 +updatedAt: 2026-03-21T19:18:15.833046+00:00 --- # tmux as editor: session creation only works when a post:open hook is configured