Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1977,6 +1977,7 @@ mod tests {
"wezterm",
"tmux",
"alacritty",
"ptyxis",
"terminal.app",
"iterm",
] {
Expand Down
2 changes: 2 additions & 0 deletions src/instance_binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ fn capture_context() -> serde_json::Map<String, serde_json::Value> {
"KITTY_LISTEN_ON",
"ALACRITTY_WINDOW_ID",
"WEZTERM_PANE",
"PTYXIS_PROFILE",
"PTYXIS_VERSION",
"GNOME_TERMINAL_SCREEN",
"KONSOLE_DBUS_WINDOW",
"TERMINATOR_UUID",
Expand Down
26 changes: 25 additions & 1 deletion src/shared/terminal_presets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,17 @@ pub static TERMINAL_PRESETS: LazyLock<Vec<(&'static str, TerminalPreset)>> = Laz
&["Linux"],
),
),
(
"ptyxis",
p(
Some("ptyxis"),
None,
argv(&["ptyxis", "--new-window", "--", "bash", "{script}"]),
NONE_ARGV,
None,
&["Linux"],
),
),
(
"konsole",
p(
Expand Down Expand Up @@ -617,6 +628,7 @@ pub const TERMINAL_ENV_MAP: &[(&str, &str)] = &[
("GHOSTTY_RESOURCES_DIR", "ghostty"),
("ITERM_SESSION_ID", "iterm"),
("ALACRITTY_WINDOW_ID", "alacritty"),
("PTYXIS_VERSION", "ptyxis"),
("GNOME_TERMINAL_SCREEN", "gnome-terminal"),
("KONSOLE_DBUS_WINDOW", "konsole"),
("TERMINATOR_UUID", "terminator"),
Expand All @@ -630,7 +642,7 @@ mod tests {

#[test]
fn test_terminal_presets_count() {
assert_eq!(TERMINAL_PRESETS.len(), 28);
assert_eq!(TERMINAL_PRESETS.len(), 29);
}

#[test]
Expand Down Expand Up @@ -683,4 +695,16 @@ mod tests {
assert!(win.contains(&"powershell"));
assert_eq!(win.first(), Some(&"mintty"));
}

#[test]
fn test_ptyxis_opens_a_new_window() {
let preset = get_terminal_preset("ptyxis").unwrap();
assert_eq!(preset.binary, Some("ptyxis"));
assert_eq!(
preset.open.select(false),
Some(&["ptyxis", "--new-window", "--", "bash", "{script}"] as ArgvTemplate)
);
assert!(preset.close.select(false).is_none());
assert!(preset.platforms.contains(&"Linux"));
}
}
64 changes: 64 additions & 0 deletions src/terminal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ pub(crate) const TERMINAL_CONTEXT_VARS: &[&str] = &[
"GHOSTTY_RESOURCES_DIR",
"ITERM_SESSION_ID",
"ALACRITTY_WINDOW_ID",
"PTYXIS_PROFILE",
"PTYXIS_VERSION",
"GNOME_TERMINAL_SCREEN",
"KONSOLE_DBUS_WINDOW",
"TERMINATOR_UUID",
Expand Down Expand Up @@ -368,6 +370,16 @@ fn normalize_terminal_mode_for_launch(
if opens_new_window {
if terminal_mode == "default"
&& let Some(detected) = detect_terminal_from_env()
// Ptyxis is commonly installed as a Flatpak. Such shells export
// PTYXIS_VERSION even when no host-side `ptyxis` launcher exists,
// so environment detection alone is not enough to launch a new
// window. Keep `default` in that case and use the normal Linux
// fallback selection below. A configured `ptyxis.binary` override
// (for example, a wrapper around `flatpak run`) is honored.
&& (detected != "ptyxis"
|| crate::config::get_merged_preset("ptyxis")
.and_then(|preset| preset.binary)
.is_some_and(|binary| which_bin(&binary).is_some()))
{
terminal_mode = detected;
}
Expand Down Expand Up @@ -1511,6 +1523,8 @@ pub fn get_default_fallback_terminal_name() -> &'static str {
}
} else if which_bin("gnome-terminal").is_some() {
"gnome-terminal"
} else if which_bin("ptyxis").is_some() {
"ptyxis"
} else if which_bin("konsole").is_some() {
"konsole"
} else if which_bin("xterm").is_some() {
Expand All @@ -1531,6 +1545,10 @@ fn get_linux_terminal_argv() -> Option<Vec<String>> {
"gnome-terminal",
&["gnome-terminal", "--", "bash", "{script}"] as &[&str],
),
(
"ptyxis",
&["ptyxis", "--new-window", "--", "bash", "{script}"],
),
("konsole", &["konsole", "-e", "bash", "{script}"]),
("xterm", &["xterm", "-e", "bash", "{script}"]),
];
Expand Down Expand Up @@ -1624,6 +1642,7 @@ fn is_external_terminal_launcher(argv: &[String]) -> bool {
| "ttab"
| "wttab"
| "gnome-terminal"
| "ptyxis"
| "konsole"
| "xterm"
| "tilix"
Expand Down Expand Up @@ -3181,6 +3200,49 @@ mod tests {
assert!(auto);
}

#[test]
#[serial]
fn test_detect_terminal_from_ptyxis_version() {
let _env = EnvGuard::clear(TERMINAL_CONTEXT_VARS);
let _detect = EnvGuard::clear(DETECT_ONLY_VARS);
unsafe {
std::env::set_var("PTYXIS_VERSION", "50.1");
}

assert_eq!(detect_terminal_from_env().as_deref(), Some("ptyxis"));
}

#[test]
#[serial]
fn test_auto_detected_ptyxis_requires_host_launcher_for_new_window() {
let _env = EnvGuard::clear(TERMINAL_CONTEXT_VARS);
let _detect = EnvGuard::clear(DETECT_ONLY_VARS);
let _path = EnvGuard::clear(&["PATH"]);
let empty_path = tempfile::tempdir().unwrap();
unsafe {
std::env::set_var("PTYXIS_VERSION", "50.1");
std::env::set_var("PATH", empty_path.path());
}

let (mode, socket) = normalize_terminal_mode_for_launch("default".to_string(), true, false);

assert_eq!(mode, "default");
assert!(socket.is_empty());
}

#[test]
fn test_launcher_env_strips_ptyxis_identity() {
let env = get_launcher_env_from(vec![
("PTYXIS_PROFILE".into(), "profile-id".into()),
("PTYXIS_VERSION".into(), "50.1".into()),
("PATH".into(), "/bin".into()),
]);

assert!(!env.contains_key("PTYXIS_PROFILE"));
assert!(!env.contains_key("PTYXIS_VERSION"));
assert_eq!(env.get("PATH").map(String::as_str), Some("/bin"));
}

#[test]
fn test_splice_kitten_to_socket_matches_absolute_app_bundle_path() {
// Regression: when `kitten` isn't on PATH, resolve_terminal_open_argv
Expand Down Expand Up @@ -3984,6 +4046,8 @@ mod tests {
assert!(terminal_preset_supported_on("wttab", "Windows"));
assert!(!terminal_preset_supported_on("wttab", "Darwin"));
assert!(terminal_preset_supported_on("wezterm", "Windows"));
assert!(terminal_preset_supported_on("ptyxis", "Linux"));
assert!(!terminal_preset_supported_on("ptyxis", "Darwin"));
assert!(!terminal_preset_supported_on("nope", "Darwin"));
}
}
6 changes: 6 additions & 0 deletions src/tui/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1295,6 +1295,12 @@ const BUILTIN_PRESETS: &[PresetDef] = &[
app_name: "",
platforms: &["Linux"],
},
PresetDef {
name: "ptyxis",
binary: Some("ptyxis"),
app_name: "",
platforms: &["Linux"],
},
PresetDef {
name: "konsole",
binary: Some("konsole"),
Expand Down
2 changes: 2 additions & 0 deletions tests/test_relay_roundtrip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ fn hcom_with_dir(cmd: &str, hcom_dir: &str) -> Output {
"GHOSTTY_RESOURCES_DIR",
"ITERM_SESSION_ID",
"ALACRITTY_WINDOW_ID",
"PTYXIS_PROFILE",
"PTYXIS_VERSION",
"GNOME_TERMINAL_SCREEN",
"KONSOLE_DBUS_WINDOW",
"TERMINATOR_UUID",
Expand Down