aboutsummaryrefslogtreecommitdiffstats
path: root/atuin-common/src/shell.rs
diff options
context:
space:
mode:
authorEllie Huxtable <ellie@elliehuxtable.com>2024-04-18 16:41:28 +0100
committerGitHub <noreply@github.com>2024-04-18 16:41:28 +0100
commit95cc472037fcb3207b510e67f1a44af4e2a2cae9 (patch)
treefc1d3e71d8e0bdb806370e4144fd6f373bcc9c5e /atuin-common/src/shell.rs
parentfeat: show preview auto (#1804) (diff)
downloadatuin-95cc472037fcb3207b510e67f1a44af4e2a2cae9.zip
chore: move crates into crates/ dir (#1958)
I'd like to tidy up the root a little, and it's nice to have all the rust crates in one place
Diffstat (limited to 'atuin-common/src/shell.rs')
-rw-r--r--atuin-common/src/shell.rs147
1 files changed, 0 insertions, 147 deletions
diff --git a/atuin-common/src/shell.rs b/atuin-common/src/shell.rs
deleted file mode 100644
index 42e32f72..00000000
--- a/atuin-common/src/shell.rs
+++ /dev/null
@@ -1,147 +0,0 @@
-use std::{ffi::OsStr, path::Path, process::Command};
-
-use serde::Serialize;
-use sysinfo::{get_current_pid, Process, System};
-use thiserror::Error;
-
-pub enum Shell {
- Sh,
- Bash,
- Fish,
- Zsh,
- Xonsh,
- Nu,
-
- Unknown,
-}
-
-impl std::fmt::Display for Shell {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- let shell = match self {
- Shell::Bash => "bash",
- Shell::Fish => "fish",
- Shell::Zsh => "zsh",
- Shell::Nu => "nu",
- Shell::Xonsh => "xonsh",
- Shell::Sh => "sh",
-
- Shell::Unknown => "unknown",
- };
-
- write!(f, "{}", shell)
- }
-}
-
-#[derive(Debug, Error, Serialize)]
-pub enum ShellError {
- #[error("shell not supported")]
- NotSupported,
-
- #[error("failed to execute shell command: {0}")]
- ExecError(String),
-}
-
-impl Shell {
- pub fn current() -> Shell {
- let sys = System::new_all();
-
- let process = sys
- .process(get_current_pid().expect("Failed to get current PID"))
- .expect("Process with current pid does not exist");
-
- let parent = sys
- .process(process.parent().expect("Atuin running with no parent!"))
- .expect("Process with parent pid does not exist");
-
- let shell = parent.name().trim().to_lowercase();
- let shell = shell.strip_prefix('-').unwrap_or(&shell);
-
- Shell::from_string(shell.to_string())
- }
-
- /// Best-effort attempt to determine the default shell
- /// This implementation will be different across different platforms
- /// Caller should ensure to handle Shell::Unknown correctly
- pub fn default_shell() -> Result<Shell, ShellError> {
- let sys = System::name().unwrap_or("".to_string()).to_lowercase();
-
- // TODO: Support Linux
- // I'm pretty sure we can use /etc/passwd there, though there will probably be some issues
- if sys.contains("darwin") {
- // This works in my testing so far
- let path = Shell::Sh.run_interactive([
- "dscl localhost -read \"/Local/Default/Users/$USER\" shell | awk '{print $2}'",
- ])?;
-
- let path = Path::new(path.trim());
-
- let shell = path.file_name();
-
- if shell.is_none() {
- return Err(ShellError::NotSupported);
- }
-
- Ok(Shell::from_string(
- shell.unwrap().to_string_lossy().to_string(),
- ))
- } else {
- Err(ShellError::NotSupported)
- }
- }
-
- pub fn from_string(name: String) -> Shell {
- match name.as_str() {
- "bash" => Shell::Bash,
- "fish" => Shell::Fish,
- "zsh" => Shell::Zsh,
- "xonsh" => Shell::Xonsh,
- "nu" => Shell::Nu,
- "sh" => Shell::Sh,
-
- _ => Shell::Unknown,
- }
- }
-
- /// Returns true if the shell is posix-like
- /// Note that while fish is not posix compliant, it behaves well enough for our current
- /// featureset that this does not matter.
- pub fn is_posixish(&self) -> bool {
- matches!(self, Shell::Bash | Shell::Fish | Shell::Zsh)
- }
-
- pub fn run_interactive<I, S>(&self, args: I) -> Result<String, ShellError>
- where
- I: IntoIterator<Item = S>,
- S: AsRef<OsStr>,
- {
- let shell = self.to_string();
-
- let output = Command::new(shell)
- .arg("-ic")
- .args(args)
- .output()
- .map_err(|e| ShellError::ExecError(e.to_string()))?;
-
- Ok(String::from_utf8(output.stdout).unwrap())
- }
-}
-
-pub fn shell_name(parent: Option<&Process>) -> String {
- let sys = System::new_all();
-
- let parent = if let Some(parent) = parent {
- parent
- } else {
- let process = sys
- .process(get_current_pid().expect("Failed to get current PID"))
- .expect("Process with current pid does not exist");
-
- sys.process(process.parent().expect("Atuin running with no parent!"))
- .expect("Process with parent pid does not exist")
- };
-
- let shell = parent.name().trim().to_lowercase();
- let shell = shell.strip_prefix('-').unwrap_or(&shell);
-
- shell.to_string()
-}