use std::path::{Path, PathBuf};
use crate::config::Position;
use crate::context::SystemContext;
use crate::shell::{Shell, ShellKind};
pub struct Tcsh;
impl Shell for Tcsh {
fn kind(&self) -> ShellKind {
ShellKind::Tcsh
}
fn env_extension(&self) -> &'static str {
".tcsh"
}
fn env_script(&self, dir: &Path, position: Position) -> String {
let dir = dir.display();
let setenv = match position {
Position::Prepend => format!("setenv PATH \"{dir}:${{PATH}}\""),
Position::Append => format!("setenv PATH \"${{PATH}}:{dir}\""),
};
format!(
r#"#!/bin/tcsh
# Generated by onpath. Do not edit.
switch (":${{PATH}}:")
case *\:"{dir}"\:*:
breaksw
default:
{setenv}
breaksw
endsw
"#
)
}
fn source_line(&self, env_script_path: &Path) -> String {
format!("source \"{}\"", env_script_path.display())
}
fn rc_candidates(&self, ctx: &SystemContext) -> Vec<PathBuf> {
vec![
ctx.home_dir().join(".tcshrc"),
ctx.home_dir().join(".cshrc"),
]
}
fn primary_rc(&self, ctx: &SystemContext) -> PathBuf {
ctx.home_dir().join(".tcshrc")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn env_script_uses_switch_pattern() {
let script = Tcsh.env_script(Path::new("/app/bin"), Position::Prepend);
assert!(script.contains("switch"));
assert!(script.contains("setenv PATH"));
assert!(script.contains("endsw"));
}
#[test]
fn env_script_append() {
let script = Tcsh.env_script(Path::new("/app/bin"), Position::Append);
assert!(script.contains("\"${PATH}:/app/bin\""));
}
#[test]
fn rc_candidates_includes_tcshrc_and_cshrc() {
let ctx = SystemContext::with_home(PathBuf::from("/home/user"));
let candidates = Tcsh.rc_candidates(&ctx);
assert!(candidates.contains(&PathBuf::from("/home/user/.tcshrc")));
assert!(candidates.contains(&PathBuf::from("/home/user/.cshrc")));
}
}