Skip to main content

runex_core/
init.rs

1use std::path::PathBuf;
2
3use crate::config::xdg_config_home;
4use crate::shell::Shell;
5
6/// Marker comment written into rc files to enable idempotent init.
7pub const RUNEX_INIT_MARKER: &str = "# runex-init";
8
9/// Minimal config template written by `runex init`.
10pub fn default_config_content() -> &'static str {
11    r#"version = 1
12
13# Add your abbreviations below.
14# [[abbr]]
15# key = "gcm"
16# expand = "git commit -m"
17"#
18}
19
20/// The single line appended to the shell rc file.
21pub fn integration_line(shell: Shell, bin: &str) -> String {
22    match shell {
23        Shell::Bash => format!("eval \"$({bin} export bash)\""),
24        Shell::Zsh => format!("eval \"$({bin} export zsh)\""),
25        Shell::Pwsh => format!("Invoke-Expression (& {bin} export pwsh | Out-String)"),
26        Shell::Nu => {
27            let cfg_dir = xdg_config_home()
28                .map(|p| p.display().to_string())
29                .unwrap_or_else(|| "~/.config".to_string());
30            format!(
31                "{bin} export nu | save --force {cfg_dir}/runex/runex.nu\nsource {cfg_dir}/runex/runex.nu"
32            )
33        }
34        Shell::Clink => format!("-- add '{bin} export clink' output to your clink scripts directory"),
35    }
36}
37
38/// The rc file path for a given shell (best-effort; may not exist yet).
39pub fn rc_file_for(shell: Shell) -> Option<PathBuf> {
40    let home = dirs::home_dir()?;
41    match shell {
42        Shell::Bash => Some(home.join(".bashrc")),
43        Shell::Zsh => Some(home.join(".zshrc")),
44        Shell::Pwsh => {
45            // $PROFILE is a runtime variable; use the conventional Windows path.
46            let base = if cfg!(windows) {
47                home.join("Documents").join("PowerShell")
48            } else {
49                home.join(".config").join("powershell")
50            };
51            Some(base.join("Microsoft.PowerShell_profile.ps1"))
52        }
53        Shell::Nu => {
54            let cfg = xdg_config_home().unwrap_or_else(|| home.join(".config"));
55            Some(cfg.join("nushell").join("env.nu"))
56        }
57        Shell::Clink => None,
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn default_config_content_has_version() {
67        assert!(default_config_content().contains("version = 1"));
68    }
69
70    #[test]
71    fn integration_line_bash() {
72        assert_eq!(
73            integration_line(Shell::Bash, "runex"),
74            r#"eval "$(runex export bash)""#
75        );
76    }
77
78    #[test]
79    fn integration_line_pwsh() {
80        let line = integration_line(Shell::Pwsh, "runex");
81        assert!(line.contains("Invoke-Expression"));
82        assert!(line.contains("runex export pwsh"));
83    }
84
85    #[test]
86    fn rc_file_for_bash_ends_with_bashrc() {
87        if let Some(path) = rc_file_for(Shell::Bash) {
88            assert!(path.to_str().unwrap().ends_with(".bashrc"));
89        }
90    }
91}