use std::ffi::OsString;
use std::path::Path;
use anyhow::{Context, Result};
pub const CD_FILE_VAR: &str = "GWX_CD_FILE";
pub fn request(path: &Path) -> Result<()> {
write_request(std::env::var_os(CD_FILE_VAR), path)
}
pub fn request_picked(path: &Path) -> Result<()> {
let file = std::env::var_os(CD_FILE_VAR);
let integrated = file.as_ref().is_some_and(|f| !f.is_empty());
write_request(file, path)?;
if !integrated {
eprintln!(
"gwx: could not change directory — the shell integration is missing or out of date."
);
eprintln!(" Start a new shell, or reload it with: eval \"$(gwx shell-init zsh)\"");
}
Ok(())
}
fn write_request(file: Option<OsString>, path: &Path) -> Result<()> {
match file {
Some(file) if !file.is_empty() => std::fs::write(&file, format!("{}\n", path.display()))
.with_context(|| {
format!(
"failed to write the target directory to {}",
Path::new(&file).display()
)
}),
_ => {
println!("{}", path.display());
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn writes_to_the_hand_off_file_when_asked() {
let dir = tempfile::tempdir().unwrap();
let file = dir.path().join("cd");
write_request(
Some(file.clone().into_os_string()),
Path::new("/home/me/worktrees/feature/auth"),
)
.unwrap();
assert_eq!(
std::fs::read_to_string(&file).unwrap(),
"/home/me/worktrees/feature/auth\n"
);
}
#[test]
fn falls_back_to_stdout_without_a_file() {
write_request(None, Path::new("/tmp")).unwrap();
write_request(Some(OsString::new()), Path::new("/tmp")).unwrap();
}
#[test]
fn reports_an_unwritable_hand_off_file() {
let err = write_request(
Some(OsString::from("/nonexistent-dir/gwx-cd")),
Path::new("/tmp"),
)
.unwrap_err();
assert!(err.to_string().contains("failed to write"), "{err}");
}
}