zsh_module/
zsh.rs

1//! A collection of functions used to interact directly with Zsh
2use std::{io::Read, path::Path};
3
4use crate::{to_cstr, MaybeError, ToCString};
5
6use zsh_sys as zsys;
7
8#[derive(Debug)]
9pub struct InternalError;
10
11impl std::fmt::Display for InternalError {
12    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13        write!(f, "Something went wrong while sourcing the file")
14    }
15}
16impl std::error::Error for InternalError {}
17
18/// Evaluates a zsh script string
19/// # Examples
20/// ```no_run
21/// zsh_module::zsh::eval_simple("set -x").unwrap();
22/// zsh_module::zsh::eval_simple("function func() { echo 'Hello from func' }").unwrap();
23/// ```
24///
25pub fn eval_simple(cmd: &str) -> MaybeError<InternalError> {
26    static ZSH_CONTEXT_STRING: &[u8] = b"zsh-module-rs-eval\0";
27    unsafe {
28        let cmd = to_cstr(cmd);
29        zsys::execstring(
30            cmd.as_ptr() as *mut _,
31            1,
32            0,
33            ZSH_CONTEXT_STRING.as_ptr() as *mut _,
34        );
35        if zsys::errflag != 0 {
36            Err(InternalError)
37        } else {
38            Ok(())
39        }
40    }
41}
42
43// for some shell globals, take a look at Src/init.c:source
44
45// !TODO: implement zsh's stdin
46/* pub fn stdin() -> impl Read {
47    std::os::unix::io::FromRawFd::from_raw_fd(zsys::SHIN)
48} */
49
50#[derive(Debug)]
51#[repr(u32)]
52pub enum SourceError {
53    NotFound,
54    InternalError(InternalError),
55}
56
57impl std::fmt::Display for SourceError {
58    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59        match self {
60            Self::NotFound => write!(f, "File not found"),
61            Self::InternalError(e) => e.fmt(f),
62        }
63    }
64}
65impl std::error::Error for SourceError {}
66
67pub fn source_file(path: impl ToCString) -> MaybeError<SourceError> {
68    let path = path.into_cstr();
69    let result = unsafe { zsys::source(path.as_ptr() as *mut _) };
70    if result == zsys::source_return_SOURCE_OK {
71        Ok(())
72    } else {
73        Err(match result {
74            zsys::source_return_SOURCE_NOT_FOUND => SourceError::NotFound,
75            zsys::source_return_SOURCE_ERROR => SourceError::InternalError(InternalError),
76            _ => unreachable!(),
77        })
78    }
79}