use std::path::{Path, PathBuf};
use crate::config::Position;
use crate::context::SystemContext;
use crate::shell::{Shell, ShellKind};
pub struct PowerShell;
impl Shell for PowerShell {
fn kind(&self) -> ShellKind {
ShellKind::PowerShell
}
fn env_extension(&self) -> &'static str {
".ps1"
}
fn env_script(&self, dir: &Path, position: Position) -> String {
let dir = dir.display();
let mutation = match position {
Position::Prepend => {
format!("$env:PATH = \"{dir}\" + [IO.Path]::PathSeparator + $env:PATH")
}
Position::Append => {
format!("$env:PATH = $env:PATH + [IO.Path]::PathSeparator + \"{dir}\"")
}
};
format!(
r#"# Generated by onpath. Do not edit.
if (-not ($env:PATH -split [IO.Path]::PathSeparator | Where-Object {{ $_ -eq "{dir}" }})) {{
{mutation}
}}
"#
)
}
fn source_line(&self, env_script_path: &Path) -> String {
format!(". \"{}\"", env_script_path.display())
}
fn rc_candidates(&self, ctx: &SystemContext) -> Vec<PathBuf> {
let config = ctx.xdg_config_home();
vec![
config
.join("powershell")
.join("Microsoft.PowerShell_profile.ps1"),
ctx.home_dir()
.join(".config")
.join("powershell")
.join("Microsoft.PowerShell_profile.ps1"),
]
}
fn primary_rc(&self, ctx: &SystemContext) -> PathBuf {
ctx.xdg_config_home()
.join("powershell")
.join("Microsoft.PowerShell_profile.ps1")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn env_script_uses_powershell_syntax() {
let script = PowerShell.env_script(Path::new("/app/bin"), Position::Prepend);
assert!(script.contains("$env:PATH"));
assert!(script.contains("[IO.Path]::PathSeparator"));
}
#[test]
fn env_script_append() {
let script = PowerShell.env_script(Path::new("/app/bin"), Position::Append);
assert!(script.contains("$env:PATH + [IO.Path]::PathSeparator"));
}
#[test]
fn source_line_uses_dot_sourcing() {
let line = PowerShell.source_line(Path::new("/home/user/.myapp/env.ps1"));
assert_eq!(line, ". \"/home/user/.myapp/env.ps1\"");
}
}