diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index 58640e20850981d67656f3747ef6c47354af6157..7750f8b95e98152ae7f49088f72ccf714d78ddd3 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -25,7 +25,7 @@ use std::error::Error; use std::io::{self, Write}; use std::path::Path; -use parser::QuoteTerminator; +use parser::Terminator; use shell::{self, FlowLogic, Shell, ShellHistory}; use shell::job_control::{JobControl, ProcessState}; use shell::status::*; @@ -193,8 +193,8 @@ fn builtin_not(args: &[&str], shell: &mut Shell) -> i32 { fn builtin_set(args: &[&str], shell: &mut Shell) -> i32 { set::set(args, shell) } fn builtin_eval(args: &[&str], shell: &mut Shell) -> i32 { let evaluated_command = args[1..].join(" "); - let mut buffer = QuoteTerminator::new(evaluated_command); - if buffer.check_termination() { + let mut buffer = Terminator::new(evaluated_command); + if buffer.is_terminated() { shell.on_command(&buffer.consume()); shell.previous_status } else { diff --git a/src/lib.rs b/src/lib.rs index 576a420f49a6e802b701618b446c9aa37dc63bbd..876457ac118b9eecd5244e2517ac577a932d42ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,7 @@ mod sys; #[macro_use] mod types; #[macro_use] -mod parser; +pub mod parser; mod builtins; pub mod shell; mod ascii_helpers; diff --git a/src/parser/arguments.rs b/src/parser/arguments.rs index 20a84ca104e501e85a928ec9a7f3611f3874a94a..9b9706ca896a0cbaf1ce5b6a8def82e527477830 100644 --- a/src/parser/arguments.rs +++ b/src/parser/arguments.rs @@ -6,14 +6,14 @@ const ARRAY: u8 = 16; const METHOD: u8 = 32; /// An efficient `Iterator` structure for splitting arguments -pub(crate) struct ArgumentSplitter<'a> { +pub struct ArgumentSplitter<'a> { data: &'a str, read: usize, flags: u8, } impl<'a> ArgumentSplitter<'a> { - pub(crate) fn new(data: &'a str) -> ArgumentSplitter<'a> { + pub fn new(data: &'a str) -> ArgumentSplitter<'a> { ArgumentSplitter { data: data, read: 0, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index acc4c66fdc681cea154a09d3bf4b97301b2dc3c4..0e96d9a4c0942af8da137524a273ee36fcbaf275 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,13 +1,13 @@ mod arguments; -pub mod assignments; +pub(crate) mod assignments; mod loops; -pub mod pipelines; -pub mod shell_expand; +pub(crate) mod pipelines; +pub(crate) mod shell_expand; mod statement; mod quotes; -pub(crate) use self::arguments::ArgumentSplitter; +pub use self::arguments::ArgumentSplitter; pub(crate) use self::loops::for_grammar::ForExpression; -pub(crate) use self::quotes::QuoteTerminator; +pub use self::quotes::Terminator; pub(crate) use self::shell_expand::{expand_string, Expander, Select}; pub(crate) use self::statement::{parse_and_validate, StatementSplitter}; diff --git a/src/parser/quotes.rs b/src/parser/quotes.rs index d9fc8ded9100a087d373dcf78d30b67e6a3d1f2f..10efcefa02dc0ee3ffd4909a4f4a6f5acfffb880 100644 --- a/src/parser/quotes.rs +++ b/src/parser/quotes.rs @@ -11,7 +11,13 @@ bitflags! { } } -pub struct QuoteTerminator { +/// Serves as a buffer for storing a string until that string can be terminated. +/// +/// # Examples +/// +/// This example comes from the shell's REPL, which ensures that the user's input +/// will only be submitted for execution once a terminated command is supplied. +pub struct Terminator { buffer: String, eof: Option<String>, eof_buffer: String, @@ -20,17 +26,17 @@ pub struct QuoteTerminator { flags: Flags, } -impl<'a> From<&'a str> for QuoteTerminator { - fn from(string: &'a str) -> QuoteTerminator { QuoteTerminator::new(string.to_owned()) } +impl<'a> From<&'a str> for Terminator { + fn from(string: &'a str) -> Terminator { Terminator::new(string.to_owned()) } } -impl From<String> for QuoteTerminator { - fn from(string: String) -> QuoteTerminator { QuoteTerminator::new(string) } +impl From<String> for Terminator { + fn from(string: String) -> Terminator { Terminator::new(string) } } -impl QuoteTerminator { - pub fn new(input: String) -> QuoteTerminator { - QuoteTerminator { +impl Terminator { + pub fn new(input: String) -> Terminator { + Terminator { buffer: input, eof: None, eof_buffer: String::new(), @@ -40,16 +46,18 @@ impl QuoteTerminator { } } - pub fn append(&mut self, input: String) { + /// Appends a string to the internal buffer. + pub fn append(&mut self, input: &str) { if self.eof.is_none() { self.buffer - .push_str(if self.flags.contains(Flags::TRIM) { input.trim() } else { &input }); + .push_str(if self.flags.contains(Flags::TRIM) { input.trim() } else { input }); } else { - self.eof_buffer.push_str(&input); + self.eof_buffer.push_str(input); } } - pub fn check_termination(&mut self) -> bool { + + pub fn is_terminated(&mut self) -> bool { let mut eof_line = None; let eof = self.eof.clone(); let status = if let Some(ref eof) = eof { @@ -164,5 +172,6 @@ impl QuoteTerminator { status } + /// Consumes the `Terminator`, and returns the underlying `String`. pub fn consume(self) -> String { self.buffer } } diff --git a/src/shell/binary/terminate.rs b/src/shell/binary/terminate.rs index 2da0894122d5690c0f4c604564d28794ccca19f4..2cb932d9b34e907f10806b579b1e02873992a8da 100644 --- a/src/shell/binary/terminate.rs +++ b/src/shell/binary/terminate.rs @@ -1,17 +1,17 @@ use super::super::{Binary, FlowLogic, Shell}; use super::super::status::*; -use parser::QuoteTerminator; +use parser::Terminator; pub(crate) fn terminate_script_quotes<I: Iterator<Item = String>>( shell: &mut Shell, mut lines: I, ) -> i32 { while let Some(command) = lines.next() { - let mut buffer = QuoteTerminator::new(command); - while !buffer.check_termination() { + let mut buffer = Terminator::new(command); + while !buffer.is_terminated() { loop { if let Some(command) = lines.next() { - buffer.append(command); + buffer.append(&command); break; } else { eprintln!("ion: unterminated quote in script"); @@ -36,11 +36,11 @@ pub(crate) fn terminate_script_quotes<I: Iterator<Item = String>>( } pub(crate) fn terminate_quotes(shell: &mut Shell, command: String) -> Result<String, ()> { - let mut buffer = QuoteTerminator::new(command); + let mut buffer = Terminator::new(command); shell.flow_control.level += 1; - while !buffer.check_termination() { + while !buffer.is_terminated() { if let Some(command) = shell.readln() { - buffer.append(command); + buffer.append(&command); } else { return Err(()); } diff --git a/src/shell/library.rs b/src/shell/library.rs index b0cbffb242c529293987d68f1d17bd0e62c30bd2..eae65d54ade9cff1006df1d3913e96f53ac1ebd9 100644 --- a/src/shell/library.rs +++ b/src/shell/library.rs @@ -1,6 +1,6 @@ use super::{Binary, FlowLogic, Shell}; use super::status::*; -use parser::QuoteTerminator; +use parser::Terminator; use std::fmt::{self, Display, Formatter}; use std::fs::File; use std::io::{self, Read}; @@ -28,7 +28,7 @@ pub trait IonLibrary { /// not /// terminated, an error will be returned. fn execute_command<CMD>(&mut self, command: CMD) -> Result<i32, &'static str> - where CMD: Into<QuoteTerminator>; + where CMD: Into<Terminator>; /// Executes all of the statements contained within a given script, /// returning the final exit status. @@ -43,10 +43,10 @@ pub trait IonLibrary { impl IonLibrary for Shell { fn execute_command<CMD>(&mut self, command: CMD) -> Result<i32, &'static str> - where CMD: Into<QuoteTerminator> + where CMD: Into<Terminator> { let mut terminator = command.into(); - if terminator.check_termination() { + if terminator.is_terminated() { self.on_command(&terminator.consume()); Ok(self.previous_status) } else { diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 471bf861a30827b03e51d316b884c0a0dcc195b1..1fe5d1c6cdb9efa206419563fa02e14ed7b58ef4 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -55,35 +55,35 @@ use types::*; /// program. pub struct Shell { /// Contains a list of built-in commands that were created when the program started. - pub builtins: &'static BuiltinMap, + pub(crate) builtins: &'static BuiltinMap, /// Contains the history, completions, and manages writes to the history file. /// Note that the context is only available in an interactive session. - pub context: Option<Context>, + pub(crate) context: Option<Context>, /// Contains the aliases, strings, and array variable maps. - pub variables: Variables, + pub(crate) variables: Variables, /// Contains the current state of flow control parameters. flow_control: FlowControl, /// Contains the directory stack parameters. - pub directory_stack: DirectoryStack, + pub(crate) directory_stack: DirectoryStack, /// Contains all of the user-defined functions that have been created. - pub functions: FnvHashMap<Identifier, Function>, + pub(crate) functions: FnvHashMap<Identifier, Function>, /// When a command is executed, the final result of that command is stored here. pub previous_status: i32, /// The job ID of the previous command sent to the background. - pub previous_job: u32, + pub(crate) previous_job: u32, /// Contains all the boolean flags that control shell behavior. pub flags: u8, /// A temporary field for storing foreground PIDs used by the pipeline execution. foreground: Vec<u32>, /// Contains information on all of the active background processes that are being managed /// by the shell. - pub background: Arc<Mutex<Vec<BackgroundProcess>>>, + pub(crate) background: Arc<Mutex<Vec<BackgroundProcess>>>, /// If set, denotes that this shell is running as a background job. - pub is_background_shell: bool, + pub(crate) is_background_shell: bool, /// Set when a signal is received, this will tell the flow control logic to abort. - pub break_flow: bool, + pub(crate) break_flow: bool, // Useful for disabling the execution of the `tcsetpgrp` call. - pub is_library: bool, + pub(crate) is_library: bool, /// When the `fg` command is run, this will be used to communicate with the specified /// background process. foreground_signals: Arc<ForegroundSignals>,