diff --git a/.gitignore b/.gitignore index e1c6c05..bcb0d50 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.vscode/launch.json + # Cargo build dir /target diff --git a/Cargo.lock b/Cargo.lock index 53c384d..e4d819e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -391,9 +391,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "linux-raw-sys" diff --git a/src/config.rs b/src/config.rs index e4ddeba..a4d2fd2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -294,6 +294,7 @@ enum Shell { #[default] Bash, Python, + Zsh, #[value(skip)] Custom { program: String, @@ -315,6 +316,7 @@ impl Display for Shell { match self { Self::Bash => f.write_str("bash"), Self::Python => f.write_str("python"), + Self::Zsh => f.write_str("zsh"), Self::Custom { program, args, .. } => f.write_str( &iter::once(program) .chain(args) @@ -342,7 +344,7 @@ impl Merge for Shell { impl Shell { fn line_split(&self) -> &str { match self { - Self::Bash | Self::Python => " \\", + Self::Bash | Self::Python | Self::Zsh => " \\", Self::Custom { line_split, .. } => line_split, } } @@ -351,6 +353,7 @@ impl Shell { match self { Self::Bash => "bash", Self::Python => "python", + Self::Zsh => "zsh", Self::Custom { program, .. } => program, } } @@ -370,6 +373,7 @@ impl Shell { match self { Self::Bash => spawn::bash(timeout, environment, width, height), Self::Python => spawn::python(timeout, environment, width, height), + Self::Zsh => spawn::zsh(timeout, environment, width, height), Self::Custom { program, args, diff --git a/src/config/de/shell.rs b/src/config/de/shell.rs index a1b5434..be1be4e 100644 --- a/src/config/de/shell.rs +++ b/src/config/de/shell.rs @@ -12,6 +12,7 @@ use crate::config::Shell; enum Variant { Bash, Python, + Zsh, Custom, } @@ -41,6 +42,7 @@ impl<'de> de::Visitor<'de> for Visitor { match v { "bash" | "Bash" => Ok(Shell::Bash), "python" | "Python" => Ok(Shell::Python), + "zsh" | "Zsh" => Ok(Shell::Zsh), _ => Err(E::invalid_value( de::Unexpected::Str(v), &"supported shell (e.g. bash or python) or a custom shell", @@ -57,6 +59,7 @@ impl<'de> de::Visitor<'de> for Visitor { match tag { Variant::Bash => variant.unit_variant().map(|_| Shell::Bash), Variant::Python => variant.unit_variant().map(|_| Shell::Python), + Variant::Zsh => variant.unit_variant().map(|_| Shell::Zsh), Variant::Custom => variant.struct_variant(CUSTOM_FIELDS, CustomVisitor), } } @@ -109,6 +112,7 @@ mod tests { fn visit_str() -> serde_yaml::Result<()> { assert_eq!(serde_yaml::from_str::("bash")?, Shell::Bash); assert_eq!(serde_yaml::from_str::("python")?, Shell::Python); + assert_eq!(serde_yaml::from_str::("zsh")?, Shell::Zsh); assert!(serde_yaml::from_str::("custom").is_err()); Ok(()) } diff --git a/src/config/spawn.rs b/src/config/spawn.rs index 3b625d2..4f968c2 100644 --- a/src/config/spawn.rs +++ b/src/config/spawn.rs @@ -1,7 +1,7 @@ use std::{ ffi::OsStr, io::{self, BufRead, BufReader, Read, Write}, - ops::{Deref, DerefMut}, + ops::DerefMut, process::Command, time::{Duration, Instant}, }; @@ -19,6 +19,38 @@ use os_str_bytes::OsStrBytes; use crate::asciicast::Event; +pub(super) fn zsh( + timeout: Duration, + environment: I, + width: u16, + height: u16, +) -> color_eyre::Result +where + I: IntoIterator, + K: AsRef, + V: AsRef, +{ + const PROMPT: &str = "AUTOCAST_PROMPT"; + const PROMPT_COMMAND: &str = + "PS1=AUTOCAST_PROMPT; unset PROMPT_COMMAND; unset zle_bracketed_paste"; + + let mut command = Command::new("zsh"); + command.arg("--no-rcs"); + command + .envs(environment) + .env("PS1", PROMPT) + .env("PROMPT_COMMAND", PROMPT_COMMAND); + + ShellSession::spawn( + command, + width, + height, + String::from(PROMPT), + Some(String::from("exit")), + timeout, + ) +} + pub(super) fn bash( timeout: Duration, environment: I, @@ -256,7 +288,15 @@ pub trait Wait: Process { #[cfg(unix)] impl Wait for UnixProcess { fn wait(&self, _: Duration) -> color_eyre::Result<()> { - self.deref().wait().map(|_| ()).map_err(Into::into) + #[cfg(target_os = "macos")] + { + Ok(()) + } + + #[cfg(target_os = "linux")] + { + self.deref().wait().map(|_| ()).map_err(Into::into) + } } }