From a9111cbab2a7550c7e84ec94c8b388de9a44daa3 Mon Sep 17 00:00:00 2001 From: Ogulcan Celik Date: Thu, 2 Jul 2026 01:16:21 +0300 Subject: fix: open scrollback editor on windows without sh refs #914 --- src/platform/macos.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'src/platform/macos.rs') diff --git a/src/platform/macos.rs b/src/platform/macos.rs index df957652..3770a3be 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -16,6 +16,30 @@ const PROC_PGRP_ONLY: u32 = 2; const SERVER_NOFILE_LIMIT_TARGET: libc::rlim_t = 8192; const CF_STRING_ENCODING_UTF8: u32 = 0x0800_0100; +pub(crate) fn scrollback_editor_argv(path: &Path) -> std::io::Result> { + let quoted_path = shell_quote(&path.display().to_string()); + let command = format!( + r#"scrollback_file={quoted_path}; eval "${{EDITOR:-vi}} \"\$scrollback_file\""; status=$?; rm -f "$scrollback_file"; exit $status"# + ); + Ok(vec!["/bin/sh".to_string(), "-c".to_string(), command]) +} + +fn shell_quote(value: &str) -> String { + if !value.is_empty() + && value.chars().all(|ch| { + ch.is_ascii_alphanumeric() + || matches!( + ch, + '@' | '%' | '_' | '+' | '=' | ':' | ',' | '.' | '/' | '-' + ) + }) + { + return value.to_string(); + } + + format!("'{}'", value.replace('\'', "'\\''")) +} + #[repr(C)] struct TisInputSource { _private: [u8; 0], @@ -1117,4 +1141,15 @@ printf '%s\n' "$@" > "$HERDR_NOTIFY_ARGS" "-e\non run argv\n-e\ndisplay notification (item 2 of argv) with title (item 1 of argv)\n-e\nend run\ntitle\nbody\n" ); } + + #[test] + fn scrollback_editor_argv_preserves_unix_editor_shell_semantics() { + let path = std::path::Path::new("/tmp/herdr scrollback.txt"); + let argv = scrollback_editor_argv(path).unwrap(); + + assert_eq!(argv[0], "/bin/sh"); + assert_eq!(argv[1], "-c"); + assert!(argv[2].contains("EDITOR:-vi")); + assert!(argv[2].contains("/tmp/herdr scrollback.txt")); + } } -- cgit v1.2.3