Skip to main content

shrub_core/shell/
expansion.rs

1//! Expansion support for shell instances.
2
3use std::borrow::Cow;
4
5use crate::interp::ExecutionParameters;
6use crate::{error, expansion, extensions};
7
8impl<SE: extensions::ShellExtensions> crate::Shell<SE> {
9    /// Returns the current value of the IFS variable, or the default value if
10    /// it is not set.
11    pub fn ifs(&self) -> Cow<'_, str> {
12        self.env_var("IFS")
13            .filter(|var| var.value().is_set())
14            .map_or_else(|| " \t\n".into(), |var| var.value().to_cow_str(self))
15    }
16
17    /// Returns the separator that joins the fields of `$*` and `${arr[*]}`: the
18    /// first character of IFS, or nothing at all when IFS is empty (an
19    /// unset IFS is a space).
20    pub(crate) fn ifs_joiner(&self) -> String {
21        self.ifs()
22            .chars()
23            .next()
24            .map_or_else(String::new, String::from)
25    }
26
27    /// Applies basic shell expansion to the provided string.
28    ///
29    /// # Arguments
30    ///
31    /// * `s` - The string to expand.
32    ///
33    /// # Errors
34    ///
35    /// - [`crate::error::ErrorKind::WordParseError`] if the text cannot be
36    ///   parsed as a word.
37    /// - [`crate::error::ErrorKind::BadSubstitution`],
38    ///   [`crate::error::ErrorKind::ExpandingUnsetVariable`] or
39    ///   [`crate::error::ErrorKind::CheckedExpansionError`] if an expansion in
40    ///   it fails, as with a bad substitution or an unset variable under `set
41    ///   -u`.
42    /// - Any error raised by a command substitution or arithmetic expansion
43    ///   inside the text.
44    pub async fn basic_expand_string<S: AsRef<str>>(
45        &mut self,
46        params: &ExecutionParameters,
47        s: S,
48    ) -> Result<String, error::Error> {
49        let result = expansion::basic_expand_word(self, params, s.as_ref()).await?;
50        Ok(result)
51    }
52
53    /// Applies full shell expansion and field splitting to the provided string;
54    /// returns a sequence of fields.
55    ///
56    /// # Arguments
57    ///
58    /// * `s` - The string to expand and split.
59    ///
60    /// # Errors
61    ///
62    /// - [`crate::error::ErrorKind::WordParseError`] if the text cannot be
63    ///   parsed as a word.
64    /// - [`crate::error::ErrorKind::BadSubstitution`],
65    ///   [`crate::error::ErrorKind::ExpandingUnsetVariable`] or
66    ///   [`crate::error::ErrorKind::CheckedExpansionError`] if an expansion in
67    ///   it fails, as with a bad substitution or an unset variable under `set
68    ///   -u`.
69    /// - Any error raised by a command substitution or arithmetic expansion
70    ///   inside the text.
71    pub async fn full_expand_and_split_string<S: AsRef<str>>(
72        &mut self,
73        params: &ExecutionParameters,
74        s: S,
75    ) -> Result<Vec<String>, error::Error> {
76        let result = expansion::full_expand_and_split_word(self, params, s.as_ref()).await?;
77        Ok(result)
78    }
79}