From 6d1e42289b98a0a1e696c0372ec7612ada5f161e Mon Sep 17 00:00:00 2001
From: Michael Aaron Murphy <mmstickman@gmail.com>
Date: Fri, 3 Nov 2017 22:42:01 -0400
Subject: [PATCH] Further Public API Improvements

---
 src/builtins/mod.rs           |  6 +++---
 src/lib.rs                    |  2 +-
 src/parser/arguments.rs       |  4 ++--
 src/parser/mod.rs             | 10 +++++-----
 src/parser/quotes.rs          | 33 +++++++++++++++++++++------------
 src/shell/binary/terminate.rs | 14 +++++++-------
 src/shell/library.rs          |  8 ++++----
 src/shell/mod.rs              | 20 ++++++++++----------
 8 files changed, 53 insertions(+), 44 deletions(-)

diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs
index 58640e20..7750f8b9 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 576a420f..876457ac 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 20a84ca1..9b9706ca 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 acc4c66f..0e96d9a4 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 d9fc8ded..10efcefa 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 2da08941..2cb932d9 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 b0cbffb2..eae65d54 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 471bf861..1fe5d1c6 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>,
-- 
GitLab