aboutsummaryrefslogtreecommitdiffstats
path: root/crates/atuin-dotfiles/src/shell
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-06-10 22:01:45 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-06-10 22:01:45 +0200
commit5e31a81cd2207f053b8cd8ad84ebe2a2f691b29d (patch)
tree5d76811ab0d693c01fa472d41aa2ceaf3bd0b415 /crates/atuin-dotfiles/src/shell
parentchore: Remove unneeded files (diff)
downloadatuin-5e31a81cd2207f053b8cd8ad84ebe2a2f691b29d.zip
chore: Remove some unused rust code
Diffstat (limited to '')
-rw-r--r--crates/atuin-dotfiles/src/shell.rs241
-rw-r--r--crates/atuin-dotfiles/src/shell/bash.rs68
-rw-r--r--crates/atuin-dotfiles/src/shell/fish.rs69
-rw-r--r--crates/atuin-dotfiles/src/shell/powershell.rs169
-rw-r--r--crates/atuin-dotfiles/src/shell/xonsh.rs68
-rw-r--r--crates/atuin-dotfiles/src/shell/zsh.rs68
6 files changed, 0 insertions, 683 deletions
diff --git a/crates/atuin-dotfiles/src/shell.rs b/crates/atuin-dotfiles/src/shell.rs
deleted file mode 100644
index 73a9ce8c..00000000
--- a/crates/atuin-dotfiles/src/shell.rs
+++ /dev/null
@@ -1,241 +0,0 @@
-use eyre::{Result, ensure, eyre};
-use rmp::{decode, encode};
-use serde::Serialize;
-
-use atuin_common::shell::{Shell, ShellError};
-
-use crate::store::AliasStore;
-
-pub mod bash;
-pub mod fish;
-pub mod powershell;
-pub mod xonsh;
-pub mod zsh;
-
-#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
-pub struct Alias {
- pub name: String,
- pub value: String,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
-pub struct Var {
- pub name: String,
- pub value: String,
-
- // False? This is a _shell var_
- // True? This is an _env var_
- pub export: bool,
-}
-
-impl Var {
- /// Serialize into the given vec
- /// This is intended to be called by the store
- pub fn serialize(&self, output: &mut Vec<u8>) -> Result<()> {
- encode::write_array_len(output, 3)?; // 3 fields
-
- encode::write_str(output, self.name.as_str())?;
- encode::write_str(output, self.value.as_str())?;
- encode::write_bool(output, self.export)?;
-
- Ok(())
- }
-
- pub fn deserialize(bytes: &mut decode::Bytes) -> Result<Self> {
- fn error_report<E: std::fmt::Debug>(err: E) -> eyre::Report {
- eyre!("{err:?}")
- }
-
- let nfields = decode::read_array_len(bytes).map_err(error_report)?;
-
- ensure!(
- nfields == 3,
- "too many entries in v0 dotfiles env create record, got {}, expected {}",
- nfields,
- 3
- );
-
- let bytes = bytes.remaining_slice();
-
- let (key, bytes) = decode::read_str_from_slice(bytes).map_err(error_report)?;
- let (value, bytes) = decode::read_str_from_slice(bytes).map_err(error_report)?;
-
- let mut bytes = decode::Bytes::new(bytes);
- let export = decode::read_bool(&mut bytes).map_err(error_report)?;
-
- ensure!(
- bytes.remaining_slice().is_empty(),
- "trailing bytes in encoded dotfiles env record, malformed"
- );
-
- Ok(Var {
- name: key.to_owned(),
- value: value.to_owned(),
- export,
- })
- }
-}
-
-pub fn parse_alias(line: &str) -> Option<Alias> {
- // consider the fact we might be importing a fish alias
- // 'alias' output
- // fish: alias foo bar
- // posix: foo=bar
-
- let is_fish = line.split(' ').next().unwrap_or("") == "alias";
-
- let parts: Vec<&str> = if is_fish {
- line.split(' ')
- .enumerate()
- .filter_map(|(n, i)| if n == 0 { None } else { Some(i) })
- .collect()
- } else {
- line.split('=').collect()
- };
-
- if parts.len() <= 1 {
- return None;
- }
-
- let mut parts = parts.iter().map(|s| s.to_string());
-
- let name = parts.next().unwrap();
-
- let remaining = if is_fish {
- parts.collect::<Vec<String>>().join(" ")
- } else {
- parts.collect::<Vec<String>>().join("=")
- };
-
- Some(Alias {
- name,
- value: remaining.trim().to_string(),
- })
-}
-
-pub fn existing_aliases(shell: Option<Shell>) -> Result<Vec<Alias>, ShellError> {
- let shell = if let Some(shell) = shell {
- shell
- } else {
- Shell::current()
- };
-
- // this only supports posix-y shells atm
- if !shell.is_posixish() {
- return Err(ShellError::NotSupported);
- }
-
- // This will return a list of aliases, each on its own line
- // They will be in the form foo=bar
- let aliases = shell.run_interactive(["alias"])?;
-
- let aliases: Vec<Alias> = aliases.lines().filter_map(parse_alias).collect();
-
- Ok(aliases)
-}
-
-/// Import aliases from the current shell
-/// This will not import aliases already in the store
-/// Returns aliases that were set
-pub async fn import_aliases(store: &AliasStore) -> Result<Vec<Alias>> {
- let shell_aliases = existing_aliases(None)?;
- let store_aliases = store.aliases().await?;
-
- let mut res = Vec::new();
-
- for alias in shell_aliases {
- // O(n), but n is small, and imports infrequent
- // can always make a map
- if store_aliases.contains(&alias) {
- continue;
- }
-
- res.push(alias.clone());
- store.set(&alias.name, &alias.value).await?;
- }
-
- Ok(res)
-}
-
-#[cfg(test)]
-mod tests {
- use crate::shell::{Alias, parse_alias};
-
- #[test]
- fn test_parse_simple_alias() {
- let alias = super::parse_alias("foo=bar").expect("failed to parse alias");
- assert_eq!(alias.name, "foo");
- assert_eq!(alias.value, "bar");
- }
-
- #[test]
- fn test_parse_quoted_alias() {
- let alias = super::parse_alias("emacs='TERM=xterm-24bits emacs -nw'")
- .expect("failed to parse alias");
-
- assert_eq!(alias.name, "emacs");
- assert_eq!(alias.value, "'TERM=xterm-24bits emacs -nw'");
-
- let git_alias = super::parse_alias("gwip='git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message \"--wip-- [skip ci]\"'").expect("failed to parse alias");
- assert_eq!(git_alias.name, "gwip");
- assert_eq!(
- git_alias.value,
- "'git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message \"--wip-- [skip ci]\"'"
- );
- }
-
- #[test]
- fn test_parse_quoted_alias_equals() {
- let alias = super::parse_alias("emacs='TERM=xterm-24bits emacs -nw --foo=bar'")
- .expect("failed to parse alias");
- assert_eq!(alias.name, "emacs");
- assert_eq!(alias.value, "'TERM=xterm-24bits emacs -nw --foo=bar'");
- }
-
- #[test]
- fn test_parse_fish() {
- let alias = super::parse_alias("alias foo bar").expect("failed to parse alias");
- assert_eq!(alias.name, "foo");
- assert_eq!(alias.value, "bar");
-
- let alias =
- super::parse_alias("alias x 'exa --icons --git --classify --group-directories-first'")
- .expect("failed to parse alias");
-
- assert_eq!(alias.name, "x");
- assert_eq!(
- alias.value,
- "'exa --icons --git --classify --group-directories-first'"
- );
- }
-
- #[test]
- fn test_parse_with_fortune() {
- // Because we run the alias command in an interactive subshell
- // there may be other output.
- // Ensure that the parser can handle it
- // Annoyingly not all aliases are picked up all the time if we use
- // a non-interactive subshell. Boo.
- let shell = "
-/ In a consumer society there are \\
-| inevitably two kinds of slaves: the |
-| prisoners of addiction and the |
-\\ prisoners of envy. /
- -------------------------------------
- \\ ^__^
- \\ (oo)\\_______
- (__)\\ )\\/\\
- ||----w |
- || ||
-emacs='TERM=xterm-24bits emacs -nw --foo=bar'
-k=kubectl
-";
-
- let aliases: Vec<Alias> = shell.lines().filter_map(parse_alias).collect();
- assert_eq!(aliases[0].name, "emacs");
- assert_eq!(aliases[0].value, "'TERM=xterm-24bits emacs -nw --foo=bar'");
-
- assert_eq!(aliases[1].name, "k");
- assert_eq!(aliases[1].value, "kubectl");
- }
-}
diff --git a/crates/atuin-dotfiles/src/shell/bash.rs b/crates/atuin-dotfiles/src/shell/bash.rs
deleted file mode 100644
index 2b9b4c88..00000000
--- a/crates/atuin-dotfiles/src/shell/bash.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-use std::path::PathBuf;
-
-use crate::store::{AliasStore, var::VarStore};
-
-async fn cached_aliases(path: PathBuf, store: &AliasStore) -> String {
- match tokio::fs::read_to_string(path).await {
- Ok(aliases) => aliases,
- Err(r) => {
- // we failed to read the file for some reason, but the file does exist
- // fallback to generating new aliases on the fly
-
- store.posix().await.unwrap_or_else(|e| {
- format!("echo 'Atuin: failed to read and generate aliases: \n{r}\n{e}'",)
- })
- }
- }
-}
-
-async fn cached_vars(path: PathBuf, store: &VarStore) -> String {
- match tokio::fs::read_to_string(path).await {
- Ok(vars) => vars,
- Err(r) => {
- // we failed to read the file for some reason, but the file does exist
- // fallback to generating new vars on the fly
-
- store.posix().await.unwrap_or_else(|e| {
- format!("echo 'Atuin: failed to read and generate vars: \n{r}\n{e}'",)
- })
- }
- }
-}
-
-/// Return bash dotfile config
-///
-/// Do not return an error. We should not prevent the shell from starting.
-///
-/// In the worst case, Atuin should not function but the shell should start correctly.
-///
-/// While currently this only returns aliases, it will be extended to also return other synced dotfiles
-pub async fn alias_config(store: &AliasStore) -> String {
- // First try to read the cached config
- let aliases = atuin_common::utils::dotfiles_cache_dir().join("aliases.bash");
-
- if aliases.exists() {
- return cached_aliases(aliases, store).await;
- }
-
- if let Err(e) = store.build().await {
- return format!("echo 'Atuin: failed to generate aliases: {e}'");
- }
-
- cached_aliases(aliases, store).await
-}
-
-pub async fn var_config(store: &VarStore) -> String {
- // First try to read the cached config
- let vars = atuin_common::utils::dotfiles_cache_dir().join("vars.bash");
-
- if vars.exists() {
- return cached_vars(vars, store).await;
- }
-
- if let Err(e) = store.build().await {
- return format!("echo 'Atuin: failed to generate vars: {e}'");
- }
-
- cached_vars(vars, store).await
-}
diff --git a/crates/atuin-dotfiles/src/shell/fish.rs b/crates/atuin-dotfiles/src/shell/fish.rs
deleted file mode 100644
index 6d472f67..00000000
--- a/crates/atuin-dotfiles/src/shell/fish.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-// Configuration for fish
-use std::path::PathBuf;
-
-use crate::store::{AliasStore, var::VarStore};
-
-async fn cached_aliases(path: PathBuf, store: &AliasStore) -> String {
- match tokio::fs::read_to_string(path).await {
- Ok(aliases) => aliases,
- Err(r) => {
- // we failed to read the file for some reason, but the file does exist
- // fallback to generating new aliases on the fly
-
- store.posix().await.unwrap_or_else(|e| {
- format!("echo 'Atuin: failed to read and generate aliases: \n{r}\n{e}'",)
- })
- }
- }
-}
-
-async fn cached_vars(path: PathBuf, store: &VarStore) -> String {
- match tokio::fs::read_to_string(path).await {
- Ok(vars) => vars,
- Err(r) => {
- // we failed to read the file for some reason, but the file does exist
- // fallback to generating new vars on the fly
-
- store.posix().await.unwrap_or_else(|e| {
- format!("echo 'Atuin: failed to read and generate vars: \n{r}\n{e}'",)
- })
- }
- }
-}
-
-/// Return fish dotfile config
-///
-/// Do not return an error. We should not prevent the shell from starting.
-///
-/// In the worst case, Atuin should not function but the shell should start correctly.
-///
-/// While currently this only returns aliases, it will be extended to also return other synced dotfiles
-pub async fn alias_config(store: &AliasStore) -> String {
- // First try to read the cached config
- let aliases = atuin_common::utils::dotfiles_cache_dir().join("aliases.fish");
-
- if aliases.exists() {
- return cached_aliases(aliases, store).await;
- }
-
- if let Err(e) = store.build().await {
- return format!("echo 'Atuin: failed to generate aliases: {e}'");
- }
-
- cached_aliases(aliases, store).await
-}
-
-pub async fn var_config(store: &VarStore) -> String {
- // First try to read the cached config
- let vars = atuin_common::utils::dotfiles_cache_dir().join("vars.fish");
-
- if vars.exists() {
- return cached_vars(vars, store).await;
- }
-
- if let Err(e) = store.build().await {
- return format!("echo 'Atuin: failed to generate vars: {e}'");
- }
-
- cached_vars(vars, store).await
-}
diff --git a/crates/atuin-dotfiles/src/shell/powershell.rs b/crates/atuin-dotfiles/src/shell/powershell.rs
deleted file mode 100644
index 1daee28b..00000000
--- a/crates/atuin-dotfiles/src/shell/powershell.rs
+++ /dev/null
@@ -1,169 +0,0 @@
-use crate::shell::{Alias, Var};
-use crate::store::{AliasStore, var::VarStore};
-use std::path::PathBuf;
-
-async fn cached_aliases(path: PathBuf, store: &AliasStore) -> String {
- match tokio::fs::read_to_string(path).await {
- Ok(aliases) => aliases,
- Err(r) => {
- // we failed to read the file for some reason, but the file does exist
- // fallback to generating new aliases on the fly
-
- store.powershell().await.unwrap_or_else(|e| {
- format!("echo 'Atuin: failed to read and generate aliases: \n{r}\n{e}'",)
- })
- }
- }
-}
-
-async fn cached_vars(path: PathBuf, store: &VarStore) -> String {
- match tokio::fs::read_to_string(path).await {
- Ok(vars) => vars,
- Err(r) => {
- // we failed to read the file for some reason, but the file does exist
- // fallback to generating new vars on the fly
-
- store.powershell().await.unwrap_or_else(|e| {
- format!("echo 'Atuin: failed to read and generate vars: \n{r}\n{e}'",)
- })
- }
- }
-}
-
-/// Return powershell dotfile config
-///
-/// Do not return an error. We should not prevent the shell from starting.
-///
-/// In the worst case, Atuin should not function but the shell should start correctly.
-///
-/// While currently this only returns aliases, it will be extended to also return other synced dotfiles
-pub async fn alias_config(store: &AliasStore) -> String {
- // First try to read the cached config
- let aliases = atuin_common::utils::dotfiles_cache_dir().join("aliases.ps1");
-
- if aliases.exists() {
- return cached_aliases(aliases, store).await;
- }
-
- if let Err(e) = store.build().await {
- return format!("echo 'Atuin: failed to generate aliases: {e}'");
- }
-
- cached_aliases(aliases, store).await
-}
-
-pub async fn var_config(store: &VarStore) -> String {
- // First try to read the cached config
- let vars = atuin_common::utils::dotfiles_cache_dir().join("vars.ps1");
-
- if vars.exists() {
- return cached_vars(vars, store).await;
- }
-
- if let Err(e) = store.build().await {
- return format!("echo 'Atuin: failed to generate vars: {e}'");
- }
-
- cached_vars(vars, store).await
-}
-
-pub fn format_alias(alias: &Alias) -> String {
- // Set-Alias doesn't support adding implicit arguments, so use a function.
- // See https://github.com/PowerShell/PowerShell/issues/12962
-
- let mut result = secure_command(&format!(
- "function {} {{\n {}{} @args\n}}",
- alias.name,
- if alias.value.starts_with(['"', '\'']) {
- "& "
- } else {
- ""
- },
- alias.value
- ));
-
- // This makes the file layout prettier
- result.insert(0, '\n');
- result
-}
-
-pub fn format_var(var: &Var) -> String {
- secure_command(&format!(
- "${}{} = '{}'",
- if var.export { "env:" } else { "" },
- var.name,
- var.value.replace("'", "''")
- ))
-}
-
-/// Wraps the given command in an Invoke-Expression to ensure the outer script is not halted
-/// if the inner command contains a syntax error.
-fn secure_command(command: &str) -> String {
- format!(
- "Invoke-Expression -ErrorAction Continue -Command '{}'\n",
- command.replace("'", "''")
- )
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn aliases() {
- assert_eq!(
- format_alias(&Alias {
- name: "gp".to_string(),
- value: "git push".to_string(),
- }),
- "\n".to_string()
- + &secure_command(
- "function gp {
- git push @args
-}"
- )
- );
-
- assert_eq!(
- format_alias(&Alias {
- name: "spc".to_string(),
- value: "\"path with spaces\" arg".to_string(),
- }),
- "\n".to_string()
- + &secure_command(
- "function spc {
- & \"path with spaces\" arg @args
-}"
- )
- );
- }
-
- #[test]
- fn vars() {
- assert_eq!(
- format_var(&Var {
- name: "FOO".to_owned(),
- value: "bar 'baz'".to_owned(),
- export: true,
- }),
- secure_command("$env:FOO = 'bar ''baz'''")
- );
-
- assert_eq!(
- format_var(&Var {
- name: "TEST".to_owned(),
- value: "1".to_owned(),
- export: false,
- }),
- secure_command("$TEST = '1'")
- );
- }
-
- #[test]
- fn invoke_expression() {
- assert_eq!(
- secure_command("echo 'foo'"),
- "Invoke-Expression -ErrorAction Continue -Command 'echo ''foo'''\n"
- )
- }
-}
diff --git a/crates/atuin-dotfiles/src/shell/xonsh.rs b/crates/atuin-dotfiles/src/shell/xonsh.rs
deleted file mode 100644
index 1e56fc1d..00000000
--- a/crates/atuin-dotfiles/src/shell/xonsh.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-use std::path::PathBuf;
-
-use crate::store::{AliasStore, var::VarStore};
-
-async fn cached_aliases(path: PathBuf, store: &AliasStore) -> String {
- match tokio::fs::read_to_string(path).await {
- Ok(aliases) => aliases,
- Err(r) => {
- // we failed to read the file for some reason, but the file does exist
- // fallback to generating new aliases on the fly
-
- store.xonsh().await.unwrap_or_else(|e| {
- format!("echo 'Atuin: failed to read and generate aliases: \n{r}\n{e}'",)
- })
- }
- }
-}
-
-async fn cached_vars(path: PathBuf, store: &VarStore) -> String {
- match tokio::fs::read_to_string(path).await {
- Ok(vars) => vars,
- Err(r) => {
- // we failed to read the file for some reason, but the file does exist
- // fallback to generating new vars on the fly
-
- store.xonsh().await.unwrap_or_else(|e| {
- format!("echo 'Atuin: failed to read and generate vars: \n{r}\n{e}'",)
- })
- }
- }
-}
-
-/// Return xonsh dotfile config
-///
-/// Do not return an error. We should not prevent the shell from starting.
-///
-/// In the worst case, Atuin should not function but the shell should start correctly.
-///
-/// While currently this only returns aliases, it will be extended to also return other synced dotfiles
-pub async fn alias_config(store: &AliasStore) -> String {
- // First try to read the cached config
- let aliases = atuin_common::utils::dotfiles_cache_dir().join("aliases.xsh");
-
- if aliases.exists() {
- return cached_aliases(aliases, store).await;
- }
-
- if let Err(e) = store.build().await {
- return format!("echo 'Atuin: failed to generate aliases: {e}'");
- }
-
- cached_aliases(aliases, store).await
-}
-
-pub async fn var_config(store: &VarStore) -> String {
- // First try to read the cached config
- let vars = atuin_common::utils::dotfiles_cache_dir().join("vars.xsh");
-
- if vars.exists() {
- return cached_vars(vars, store).await;
- }
-
- if let Err(e) = store.build().await {
- return format!("echo 'Atuin: failed to generate vars: {e}'");
- }
-
- cached_vars(vars, store).await
-}
diff --git a/crates/atuin-dotfiles/src/shell/zsh.rs b/crates/atuin-dotfiles/src/shell/zsh.rs
deleted file mode 100644
index 117e9403..00000000
--- a/crates/atuin-dotfiles/src/shell/zsh.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-use std::path::PathBuf;
-
-use crate::store::{AliasStore, var::VarStore};
-
-async fn cached_aliases(path: PathBuf, store: &AliasStore) -> String {
- match tokio::fs::read_to_string(path).await {
- Ok(aliases) => aliases,
- Err(r) => {
- // we failed to read the file for some reason, but the file does exist
- // fallback to generating new aliases on the fly
-
- store.posix().await.unwrap_or_else(|e| {
- format!("echo 'Atuin: failed to read and generate aliases: \n{r}\n{e}'",)
- })
- }
- }
-}
-
-async fn cached_vars(path: PathBuf, store: &VarStore) -> String {
- match tokio::fs::read_to_string(path).await {
- Ok(aliases) => aliases,
- Err(r) => {
- // we failed to read the file for some reason, but the file does exist
- // fallback to generating new vars on the fly
-
- store.posix().await.unwrap_or_else(|e| {
- format!("echo 'Atuin: failed to read and generate aliases: \n{r}\n{e}'",)
- })
- }
- }
-}
-
-/// Return zsh dotfile config
-///
-/// Do not return an error. We should not prevent the shell from starting.
-///
-/// In the worst case, Atuin should not function but the shell should start correctly.
-///
-/// While currently this only returns aliases, it will be extended to also return other synced dotfiles
-pub async fn alias_config(store: &AliasStore) -> String {
- // First try to read the cached config
- let aliases = atuin_common::utils::dotfiles_cache_dir().join("aliases.zsh");
-
- if aliases.exists() {
- return cached_aliases(aliases, store).await;
- }
-
- if let Err(e) = store.build().await {
- return format!("echo 'Atuin: failed to generate aliases: {e}'");
- }
-
- cached_aliases(aliases, store).await
-}
-
-pub async fn var_config(store: &VarStore) -> String {
- // First try to read the cached config
- let vars = atuin_common::utils::dotfiles_cache_dir().join("vars.zsh");
-
- if vars.exists() {
- return cached_vars(vars, store).await;
- }
-
- if let Err(e) = store.build().await {
- return format!("echo 'Atuin: failed to generate aliases: {e}'");
- }
-
- cached_vars(vars, store).await
-}