atuin_dotfiles/shell/
powershell.rs1use crate::shell::{Alias, Var};
2use crate::store::{AliasStore, var::VarStore};
3use std::path::PathBuf;
4
5async fn cached_aliases(path: PathBuf, store: &AliasStore) -> String {
6 match tokio::fs::read_to_string(path).await {
7 Ok(aliases) => aliases,
8 Err(r) => {
9 store.powershell().await.unwrap_or_else(|e| {
13 format!("echo 'Atuin: failed to read and generate aliases: \n{r}\n{e}'",)
14 })
15 }
16 }
17}
18
19async fn cached_vars(path: PathBuf, store: &VarStore) -> String {
20 match tokio::fs::read_to_string(path).await {
21 Ok(vars) => vars,
22 Err(r) => {
23 store.powershell().await.unwrap_or_else(|e| {
27 format!("echo 'Atuin: failed to read and generate vars: \n{r}\n{e}'",)
28 })
29 }
30 }
31}
32
33pub async fn alias_config(store: &AliasStore) -> String {
41 let aliases = atuin_common::utils::dotfiles_cache_dir().join("aliases.ps1");
43
44 if aliases.exists() {
45 return cached_aliases(aliases, store).await;
46 }
47
48 if let Err(e) = store.build().await {
49 return format!("echo 'Atuin: failed to generate aliases: {e}'");
50 }
51
52 cached_aliases(aliases, store).await
53}
54
55pub async fn var_config(store: &VarStore) -> String {
56 let vars = atuin_common::utils::dotfiles_cache_dir().join("vars.ps1");
58
59 if vars.exists() {
60 return cached_vars(vars, store).await;
61 }
62
63 if let Err(e) = store.build().await {
64 return format!("echo 'Atuin: failed to generate vars: {e}'");
65 }
66
67 cached_vars(vars, store).await
68}
69
70pub fn format_alias(alias: &Alias) -> String {
71 let mut result = secure_command(&format!(
75 "function {} {{\n {}{} @args\n}}",
76 alias.name,
77 if alias.value.starts_with(['"', '\'']) {
78 "& "
79 } else {
80 ""
81 },
82 alias.value
83 ));
84
85 result.insert(0, '\n');
87 result
88}
89
90pub fn format_var(var: &Var) -> String {
91 secure_command(&format!(
92 "${}{} = '{}'",
93 if var.export { "env:" } else { "" },
94 var.name,
95 var.value.replace("'", "''")
96 ))
97}
98
99fn secure_command(command: &str) -> String {
102 format!(
103 "Invoke-Expression -ErrorAction Continue -Command '{}'\n",
104 command.replace("'", "''")
105 )
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn aliases() {
114 assert_eq!(
115 format_alias(&Alias {
116 name: "gp".to_string(),
117 value: "git push".to_string(),
118 }),
119 "\n".to_string()
120 + &secure_command(
121 "function gp {
122 git push @args
123}"
124 )
125 );
126
127 assert_eq!(
128 format_alias(&Alias {
129 name: "spc".to_string(),
130 value: "\"path with spaces\" arg".to_string(),
131 }),
132 "\n".to_string()
133 + &secure_command(
134 "function spc {
135 & \"path with spaces\" arg @args
136}"
137 )
138 );
139 }
140
141 #[test]
142 fn vars() {
143 assert_eq!(
144 format_var(&Var {
145 name: "FOO".to_owned(),
146 value: "bar 'baz'".to_owned(),
147 export: true,
148 }),
149 secure_command("$env:FOO = 'bar ''baz'''")
150 );
151
152 assert_eq!(
153 format_var(&Var {
154 name: "TEST".to_owned(),
155 value: "1".to_owned(),
156 export: false,
157 }),
158 secure_command("$TEST = '1'")
159 );
160 }
161
162 #[test]
163 fn invoke_expression() {
164 assert_eq!(
165 secure_command("echo 'foo'"),
166 "Invoke-Expression -ErrorAction Continue -Command 'echo ''foo'''\n"
167 )
168 }
169}