Permalink
Browse files

Further Public API Improveents

The IonLibrary interface has been removed, and integrated directly
within the shell's main module.
  • Loading branch information...
mmstick committed Nov 4, 2017
1 parent 6d1e422 commit fffdddcd64b15f6edb2c92b2a4638044ac51544a
View
@@ -153,7 +153,7 @@ fn binary_is_in_path(binaryname: &str, shell: &Shell) -> bool {
// TODO: Right now they use an entirely different logic which means that it *might* be possible
// TODO: that `exists` reports a binary to be in the path, while the shell cannot find it or
// TODO: vice-versa
if let Some(path) = shell.variables.get_var("PATH") {
if let Some(path) = shell.get_var("PATH") {
for dir in path.split(":") {
let fname = format!("{}/{}", dir, binaryname);
if let Ok(metadata) = fs::metadata(&fname) {
@@ -197,7 +197,7 @@ fn array_var_is_not_empty(arrayvar: &str, shell: &Shell) -> bool {
/// Returns true if the variable is a string and the string is not empty
fn string_var_is_not_empty(stringvar: &str, shell: &Shell) -> bool {
match shell.variables.get_var(stringvar) {
match shell.get_var(stringvar) {
Some(string) => !string.is_empty(),
None => false,
}
@@ -250,16 +250,16 @@ fn test_evaluate_arguments() {
// TODO: see test_binary_is_in_path()
// no argument means we treat it as a string
assert_eq!(evaluate_arguments(&["-b"], &mut sink, &shell), Ok(true));
let oldpath = shell.variables.get_var("PATH").unwrap_or("/usr/bin".to_owned());
shell.variables.set_var("PATH", "testing/");
let oldpath = shell.get_var("PATH").unwrap_or("/usr/bin".to_owned());
shell.set_var("PATH", "testing/");
assert_eq!(evaluate_arguments(&["-b", "executable_file"], &mut sink, &shell), Ok(true));
assert_eq!(evaluate_arguments(&["-b", "empty_file"], &mut sink, &shell), Ok(false));
assert_eq!(evaluate_arguments(&["-b", "file_does_not_exist"], &mut sink, &shell), Ok(false));
// restore original PATH. Not necessary for the currently defined test cases but this might
// change in the future? Better safe than sorry!
shell.variables.set_var("PATH", &oldpath);
shell.set_var("PATH", &oldpath);
// check `exists -d`
// no argument means we treat it as a string
@@ -278,9 +278,9 @@ fn test_evaluate_arguments() {
// check `exists -s`
// no argument means we treat it as a string
assert_eq!(evaluate_arguments(&["-s"], &mut sink, &shell), Ok(true));
shell.variables.set_var("emptyvar", "");
shell.set_var("emptyvar", "");
assert_eq!(evaluate_arguments(&["-s", "emptyvar"], &mut sink, &shell), Ok(false));
shell.variables.set_var("testvar", "foobar");
shell.set_var("testvar", "foobar");
assert_eq!(evaluate_arguments(&["-s", "testvar"], &mut sink, &shell), Ok(true));
shell.variables.unset_var("testvar");
assert_eq!(evaluate_arguments(&["-s", "testvar"], &mut sink, &shell), Ok(false));
@@ -362,7 +362,7 @@ fn test_binary_is_in_path() {
// TODO: PATH containing directories without read permission (for user)
// TODO: PATH containing directories without execute ("enter") permission (for user)
// TODO: empty PATH?
shell.variables.set_var("PATH", "testing/");
shell.set_var("PATH", "testing/");
assert_eq!(binary_is_in_path("executable_file", &shell), true);
assert_eq!(binary_is_in_path("empty_file", &shell), false);
@@ -400,18 +400,18 @@ fn test_array_var_is_not_empty() {
assert_eq!(array_var_is_not_empty("NOT_EMPTY_ARRAY", &shell), false);
// array_var_is_not_empty should NOT match for non-array variables with the same name
shell.variables.set_var("VARIABLE", "notempty-variable");
shell.set_var("VARIABLE", "notempty-variable");
assert_eq!(array_var_is_not_empty("VARIABLE", &shell), false);
}
#[test]
fn test_string_var_is_not_empty() {
let mut shell = Shell::new();
shell.variables.set_var("EMPTY", "");
shell.set_var("EMPTY", "");
assert_eq!(string_var_is_not_empty("EMPTY", &shell), false);
shell.variables.set_var("NOT_EMPTY", "notempty");
shell.set_var("NOT_EMPTY", "notempty");
assert_eq!(string_var_is_not_empty("NOT_EMPTY", &shell), true);
// string_var_is_not_empty should NOT match for arrays with the same name
View
@@ -12,7 +12,7 @@ pub(crate) fn ion_docs(_: &[&str], shell: &mut Shell) -> i32 {
return FAILURE;
}
if let Some(cmd) = shell.variables.get_var("BROWSER".into()) {
if let Some(cmd) = shell.get_var("BROWSER".into()) {
if let Ok(_) = Command::new(&cmd).arg(DOCPATH).spawn() {
return SUCCESS;
}
View
@@ -96,9 +96,9 @@ impl VariableStore for Shell {
match value_check(self, &expression, key.kind) {
Ok(ReturnValue::Str(value)) => {
let lhs = self.variables.get_var_or_empty(&key.name);
let lhs = self.get_var_or_empty(&key.name);
match math(&lhs, key.kind, operator, &value) {
Ok(value) => self.variables.set_var(&key.name, &value),
Ok(value) => self.set_var(&key.name, &value),
Err(why) => {
eprintln!("ion: assignment error: {}", why);
return FAILURE;
@@ -125,7 +125,7 @@ impl VariableStore for Shell {
fn export(&mut self, action: ExportAction) -> i32 {
let actions = match action {
ExportAction::Assign(ref keys, op, ref vals) => AssignmentActions::new(keys, op, vals),
ExportAction::LocalExport(ref key) => match self.variables.get_var(key) {
ExportAction::LocalExport(ref key) => match self.get_var(key) {
Some(var) => {
env::set_var(key, &var);
return SUCCESS;
@@ -166,7 +166,7 @@ impl VariableStore for Shell {
Ok(Action::UpdateString(key, operator, expression)) => {
match value_check(self, &expression, key.kind) {
Ok(ReturnValue::Str(value)) => {
let lhs = self.variables.get_var_or_empty(&key.name);
let lhs = self.get_var_or_empty(&key.name);
match math(&lhs, key.kind, operator, &value) {
Ok(value) => {
let value = OsStr::from_bytes(&value.as_bytes());
View
@@ -10,7 +10,6 @@ use self::terminate::{terminate_quotes, terminate_script_quotes};
use super::{FlowLogic, JobControl, Shell, ShellHistory};
use super::flags::*;
use super::flow_control::Statement;
use super::library::IonLibrary;
use super::status::*;
use liner::{Buffer, Context};
use smallvec::SmallVec;
@@ -90,8 +89,8 @@ impl Binary for Shell {
self.context = Some({
let mut context = Context::new();
context.word_divider_fn = Box::new(word_divide);
if "1" == self.variables.get_var_or_empty("HISTFILE_ENABLED") {
let path = self.variables.get_var("HISTFILE").expect("shell didn't set HISTFILE");
if "1" == self.get_var_or_empty("HISTFILE_ENABLED") {
let path = self.get_var("HISTFILE").expect("shell didn't set HISTFILE");
context.history.set_file_name(Some(path.clone()));
if !Path::new(path.as_str()).exists() {
eprintln!("ion: creating history file at \"{}\"", path);
@@ -104,7 +103,7 @@ impl Binary for Shell {
// pass
}
Err(ref err) if err.kind() == ErrorKind::NotFound => {
let history_filename = self.variables.get_var_or_empty("HISTFILE");
let history_filename = self.get_var_or_empty("HISTFILE");
eprintln!("ion: failed to find history file {}: {}", history_filename, err);
}
Err(err) => {
View
@@ -1,11 +1,13 @@
use super::super::{Function, Shell};
use parser::shell_expand::expand_string;
use std::io::Read;
use sys;
pub(crate) fn prompt(shell: &mut Shell) -> String {
if shell.flow_control.level == 0 {
let rprompt = match prompt_fn(shell) {
Some(prompt) => prompt,
None => shell.variables.get_var_or_empty("PROMPT"),
None => shell.get_var_or_empty("PROMPT"),
};
expand_string(&rprompt, shell, false).join(" ")
} else {
@@ -19,7 +21,26 @@ pub(crate) fn prompt_fn(shell: &mut Shell) -> Option<String> {
None => return None,
};
shell.fork_and_output(|child| unsafe {
let mut output = None;
match shell.fork(|child| unsafe {
let _ = function.read().execute(child, &["ion"]);
})
}) {
Ok(mut result) => {
let mut string = String::new();
match result.stdout.read_to_string(&mut string) {
Ok(_) => output = Some(string),
Err(why) => {
eprintln!("ion: error reading stdout of child: {}", why);
}
}
}
Err(why) => {
eprintln!("ion: fork error: {}", why);
}
}
// Ensure that the parent retains ownership of the terminal before exiting.
let _ = sys::tcsetpgrp(sys::STDIN_FILENO, sys::getpid().unwrap());
output
}
View
@@ -290,9 +290,8 @@ impl FlowLogic for Shell {
.map(|x| ReturnValue::Vector(x.clone()));
self.variables.set_array(&bind, value.clone());
} else {
previous_bind =
self.variables.get_var(bind).map(|x| ReturnValue::Str(x));
self.variables.set_var(&bind, &value.join(" "));
previous_bind = self.get_var(bind).map(|x| ReturnValue::Str(x));
self.set_var(&bind, &value.join(" "));
}
}
@@ -308,7 +307,7 @@ impl FlowLogic for Shell {
if let Some(ref bind) = case.binding {
if let Some(value) = previous_bind {
match value {
ReturnValue::Str(value) => self.variables.set_var(bind, &value),
ReturnValue::Str(value) => self.set_var(bind, &value),
ReturnValue::Vector(values) => {
self.variables.set_array(bind, values)
}
@@ -327,9 +326,8 @@ impl FlowLogic for Shell {
.map(|x| ReturnValue::Vector(x.clone()));
self.variables.set_array(&bind, value.clone());
} else {
previous_bind =
self.variables.get_var(bind).map(|x| ReturnValue::Str(x));
self.variables.set_var(&bind, &value.join(" "));
previous_bind = self.get_var(bind).map(|x| ReturnValue::Str(x));
self.set_var(&bind, &value.join(" "));
}
}
@@ -345,7 +343,7 @@ impl FlowLogic for Shell {
if let Some(ref bind) = case.binding {
if let Some(value) = previous_bind {
match value {
ReturnValue::Str(value) => self.variables.set_var(bind, &value),
ReturnValue::Str(value) => self.set_var(bind, &value),
ReturnValue::Vector(values) => {
self.variables.set_array(bind, values)
}
@@ -549,7 +547,7 @@ impl FlowLogic for Shell {
}
},
ForExpression::Multiple(values) => for value in values.iter() {
self.variables.set_var(variable, &value);
self.set_var(variable, &value);
match self.execute_statements(statements.clone()) {
Condition::Break => break,
Condition::SigInt => return Condition::SigInt,
@@ -564,7 +562,7 @@ impl FlowLogic for Shell {
}
},
ForExpression::Normal(values) => for value in values.lines() {
self.variables.set_var(variable, &value);
self.set_var(variable, &value);
match self.execute_statements(statements.clone()) {
Condition::Break => break,
Condition::SigInt => return Condition::SigInt,
@@ -579,7 +577,7 @@ impl FlowLogic for Shell {
}
},
ForExpression::Range(start, end) => for value in (start..end).map(|x| x.to_string()) {
self.variables.set_var(variable, &value);
self.set_var(variable, &value);
match self.execute_statements(statements.clone()) {
Condition::Break => break,
Condition::SigInt => return Condition::SigInt,
@@ -191,8 +191,8 @@ impl Function {
shell.variables.set_array(&type_.name, vector);
}
ReturnValue::Str(string) => {
variables_backup.insert(&type_.name, shell.variables.get_var(&type_.name));
shell.variables.set_var(&type_.name, &string);
variables_backup.insert(&type_.name, shell.get_var(&type_.name));
shell.set_var(&type_.name, &string);
}
}
}
@@ -201,7 +201,7 @@ impl Function {
for (name, value_option) in &variables_backup {
match *value_option {
Some(ref value) => shell.variables.set_var(name, value),
Some(ref value) => shell.set_var(name, value),
None => {
shell.variables.unset_var(name);
}
View
@@ -85,17 +85,17 @@ impl ShellHistory for Shell {
fn set_context_history_from_vars(&mut self) {
let context = self.context.as_mut().unwrap();
let max_history_size =
self.variables.get_var_or_empty("HISTORY_SIZE").parse().unwrap_or(1000);
let variables = &self.variables;
let max_history_size = variables.get_var_or_empty("HISTORY_SIZE").parse().unwrap_or(1000);
context.history.set_max_size(max_history_size);
if &*self.variables.get_var_or_empty("HISTFILE_ENABLED") == "1" {
let file_name = self.variables.get_var("HISTFILE");
if &*variables.get_var_or_empty("HISTFILE_ENABLED") == "1" {
let file_name = variables.get_var("HISTFILE");
context.history.set_file_name(file_name.map(|f| f.into()));
let max_histfile_size =
self.variables.get_var_or_empty("HISTFILE_SIZE").parse().unwrap_or(1000);
variables.get_var_or_empty("HISTFILE_SIZE").parse().unwrap_or(1000);
context.history.set_max_file_size(max_histfile_size);
} else {
context.history.set_file_name(None);
Oops, something went wrong.

0 comments on commit fffdddc

Please sign in to comment.