use bash_builtins::variables::{self, Variable};
use bash_builtins::{builtin_metadata, Args, Builtin, Error, Result};
use std::io::{self, BufWriter, Write};
builtin_metadata!(name = "usevars", create = UseVars::default);
#[derive(Default)]
struct UseVars;
impl Builtin for UseVars {
fn call(&mut self, args: &mut Args) -> Result<()> {
let stdout_handle = io::stdout();
let mut output = BufWriter::new(stdout_handle.lock());
for name in args.string_arguments() {
let mut name_parts = name?.splitn(2, '=');
match (name_parts.next(), name_parts.next()) {
(Some(name), None) => {
if name.contains('[') {
get_array(name)?;
} else if let Some(var) = variables::find(name) {
write_var(&mut output, name, var)?
}
}
(Some(name), Some("")) => {
if variables::unset(name) {
writeln!(&mut output, "unset: {}", name)?;
}
}
(Some(name), Some(value)) => {
if name.contains('[') {
set_array(name, value)?;
} else {
variables::set(name, value)?;
}
}
_ => (),
}
}
Ok(())
}
}
fn write_var(mut output: impl Write, name: &str, var: Variable) -> io::Result<()> {
match var {
Variable::Str(s) => writeln!(&mut output, "{} = {:?}", name, s)?,
Variable::Array(a) => {
for (idx, elem) in a.iter().enumerate() {
writeln!(&mut output, "{}[{}] = {:?}", name, idx, elem)?;
}
}
Variable::Assoc(a) => {
for (key, value) in a.iter() {
writeln!(&mut output, "{}[{:?}] = {:?}", name, key, value)?;
}
}
}
Ok(())
}
fn parse_array_ref(name: &str) -> Result<(&str, &str)> {
let (open, close) = match (name.find('['), name.find(']')) {
(Some(a), Some(b)) if b + 1 == name.len() => (a, b),
_ => Err(Error::Usage)?,
};
let var_name = &name[..open];
let key = &name[open + 1..close];
Ok((var_name, key))
}
fn get_array(name: &str) -> Result<()> {
let (var_name, key) = parse_array_ref(name)?;
let value = if let Ok(index) = key.parse() {
variables::array_get(var_name, index)
} else {
variables::assoc_get(var_name, key)
};
println!("{} = {:?}", name, value);
Ok(())
}
fn set_array(name: &str, value: &str) -> Result<()> {
let (var_name, key) = parse_array_ref(name)?;
if let Ok(index) = key.parse() {
variables::array_set(var_name, index, value)?;
} else {
variables::assoc_set(var_name, key, value)?;
}
Ok(())
}