fix: editor commands configured with flags never launched
Command::new(&cfg.editor) treated the whole configured string as one binary name, so an editor set to e.g. 'code --wait' or 'vim -R' — a common config style — failed to spawn at all every single time. Added a shared launch_editor() that splits on whitespace (program + args) first, used by every one of the 6 call sites across detail/ and hub/.
This commit is contained in:
1 parent
edf4bd34bf
commit
b9fa29f656
3 files changed
+20
-6
No files matched your search
@@ -7,6 +7,7 @@
|
|||||||
use super::git::{build_history, checkout_branch, git_run, list_branches, push_branch};
|
use super::git::{build_history, checkout_branch, git_run, list_branches, push_branch};
|
||||||
use super::settings_io::{try_load_settings, try_make_provider};
|
use super::settings_io::{try_load_settings, try_make_provider};
|
||||||
use super::types::{RepoSettings, St};
|
use super::types::{RepoSettings, St};
|
||||||
|
use crate::util::launch_editor;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
/// Runs the action identified by `idx` (one of the numeric codes set on
|
/// Runs the action identified by `idx` (one of the numeric codes set on
|
||||||
@@ -78,19 +79,19 @@ pub async fn exec_action(st: &mut St, idx: usize) -> Result<()> {
|
|||||||
// ── 106-109: open in editor (leave_tui is handled by run_detail_loop) ─
|
// ── 106-109: open in editor (leave_tui is handled by run_detail_loop) ─
|
||||||
106 => {
|
106 => {
|
||||||
let editor = st.cfg_editor.clone();
|
let editor = st.cfg_editor.clone();
|
||||||
if let Err(e) = std::process::Command::new(&editor).arg(&path).status() {
|
if let Err(e) = launch_editor(&editor, &path) {
|
||||||
st.status_msg = Some(format!("Couldn't launch editor '{}': {}", editor, e));
|
st.status_msg = Some(format!("Couldn't launch editor '{}': {}", editor, e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
107 => {
|
107 => {
|
||||||
let editor = st.cfg_editor.clone();
|
let editor = st.cfg_editor.clone();
|
||||||
if let Err(e) = std::process::Command::new(&editor).arg(path.join(".gitignore")).status() {
|
if let Err(e) = launch_editor(&editor, &path.join(".gitignore")) {
|
||||||
st.status_msg = Some(format!("Couldn't launch editor '{}': {}", editor, e));
|
st.status_msg = Some(format!("Couldn't launch editor '{}': {}", editor, e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
108 => {
|
108 => {
|
||||||
let editor = st.cfg_editor.clone();
|
let editor = st.cfg_editor.clone();
|
||||||
if let Err(e) = std::process::Command::new(&editor).arg(path.join("LICENSE")).status() {
|
if let Err(e) = launch_editor(&editor, &path.join("LICENSE")) {
|
||||||
st.status_msg = Some(format!("Couldn't launch editor '{}': {}", editor, e));
|
st.status_msg = Some(format!("Couldn't launch editor '{}': {}", editor, e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,7 +100,7 @@ pub async fn exec_action(st: &mut St, idx: usize) -> Result<()> {
|
|||||||
let readme = ["README.md", "README.rst", "README"].iter()
|
let readme = ["README.md", "README.rst", "README"].iter()
|
||||||
.map(|f| path.join(f)).find(|p| p.exists())
|
.map(|f| path.join(f)).find(|p| p.exists())
|
||||||
.unwrap_or_else(|| path.join("README.md"));
|
.unwrap_or_else(|| path.join("README.md"));
|
||||||
if let Err(e) = std::process::Command::new(&editor).arg(&readme).status() {
|
if let Err(e) = launch_editor(&editor, &readme) {
|
||||||
st.status_msg = Some(format!("Couldn't launch editor '{}': {}", editor, e));
|
st.status_msg = Some(format!("Couldn't launch editor '{}': {}", editor, e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,7 +109,7 @@ pub async fn exec_action(st: &mut St, idx: usize) -> Result<()> {
|
|||||||
110 => {
|
110 => {
|
||||||
if let Some(file) = st.pending_file.take() {
|
if let Some(file) = st.pending_file.take() {
|
||||||
let editor = st.cfg_editor.clone();
|
let editor = st.cfg_editor.clone();
|
||||||
if let Err(e) = std::process::Command::new(&editor).arg(&file).status() {
|
if let Err(e) = launch_editor(&editor, &file) {
|
||||||
st.status_msg = Some(format!("Couldn't launch editor '{}': {}", editor, e));
|
st.status_msg = Some(format!("Couldn't launch editor '{}': {}", editor, e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -246,7 +246,7 @@ pub async fn run_overview_tui(
|
|||||||
}
|
}
|
||||||
PhaseResult::ExecOpenEditor(path) => {
|
PhaseResult::ExecOpenEditor(path) => {
|
||||||
let editor = state.editor.clone();
|
let editor = state.editor.clone();
|
||||||
let _ = std::process::Command::new(&editor).arg(&path).status();
|
let _ = crate::util::launch_editor(&editor, &path);
|
||||||
}
|
}
|
||||||
PhaseResult::None => {}
|
PhaseResult::None => {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,19 @@ pub fn walk_files<F: FnMut(&std::path::Path)>(root: &std::path::Path, cb: &mut F
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Launches the configured editor against `target`, treating `editor` as a
|
||||||
|
/// whitespace-separated command line (program + flags) rather than a single
|
||||||
|
/// binary name — common editor configs like `"code --wait"` or `"vim -R"`
|
||||||
|
/// would otherwise fail to spawn entirely, since `Command::new` looks for a
|
||||||
|
/// literal executable named `"code --wait"`.
|
||||||
|
pub fn launch_editor(editor: &str, target: &std::path::Path) -> std::io::Result<std::process::ExitStatus> {
|
||||||
|
let mut parts = editor.split_whitespace();
|
||||||
|
let Some(prog) = parts.next() else {
|
||||||
|
return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "empty editor command"));
|
||||||
|
};
|
||||||
|
std::process::Command::new(prog).args(parts).arg(target).status()
|
||||||
|
}
|
||||||
|
|
||||||
/// Open a file, directory, or URL with the system default application.
|
/// Open a file, directory, or URL with the system default application.
|
||||||
pub fn open_path(target: &str) {
|
pub fn open_path(target: &str) {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
|
|||||||
Reference in new issue
Block a user