From b8338719e2cc2138bc67c10ad56fb707f5e3b546 Mon Sep 17 00:00:00 2001
From: Rory Dudley
Date: Sun, 30 Jun 2024 20:09:26 -0600
Subject: Add/update doc comments

This patch update a ton of the documentation comments throughout the
codebase, refactoring some areas, and adding new comments to others.
---
 src/compose.rs                   |  15 ++++
 src/compose/environment.rs       |  33 +++++---
 src/poem.rs                      |   4 +-
 src/poem/anthology.rs            |  57 ++++++++++++-
 src/poem/anthology/alias.rs      |   4 +-
 src/poem/anthology/cd.rs         |   9 +-
 src/poem/anthology/export.rs     |   4 +-
 src/poem/anthology/source.rs     |   4 +-
 src/poem/anthology/which.rs      |  12 +++
 src/poem/elements/rune.rs        | 116 +++++++++++++++-----------
 src/poem/elements/stanza.rs      |  12 +--
 src/poem/elements/verse.rs       | 174 ++++++++++++++++++++++++---------------
 src/poem/elements/verse/logic.rs |  14 ++++
 src/poem/elements/word.rs        |   3 +-
 src/poem/read.rs                 |  39 +++++++--
 src/poem/recite.rs               |  11 +--
 16 files changed, 351 insertions(+), 160 deletions(-)

(limited to 'src')

diff --git a/src/compose.rs b/src/compose.rs
index dfbbaef..b12d1a4 100644
--- a/src/compose.rs
+++ b/src/compose.rs
@@ -5,6 +5,14 @@ use std::env;
 use std::fs;
 use std::path::PathBuf;
 
+/// Setup the global shell environment
+///
+/// Sets up the shell's environment via configuration files. In order:
+/// * `/etc/dwvshrc`
+/// * `~/.dwvshrc`
+///
+/// For debug builds, all files will instead be sourced from
+/// `./dist/...` with the exception of `~/.dwvshrc`.
 pub fn env() -> Environment {
     // Create a new Environment object, to store some extra shell info
     let mut env = Environment::new();
@@ -39,6 +47,13 @@ pub fn env() -> Environment {
     env
 }
 
+/// Read, read, and recite
+///
+/// Small, reusable function used to do the heavy lifting in regards to
+/// sourcing configuration files. [Read][fs::read_to_string]s a file
+/// from disk, then [read][crate::poem::read]s (parses) a [Poem],
+/// then [recite][crate::poem::recite]s that [Poem].
+/// Configuration files are just shell scripts.
 fn rrr(path: PathBuf, env: &mut Environment) {
     let poetry = match fs::read_to_string(&path) {
         Ok(poetry) => poetry,
diff --git a/src/compose/environment.rs b/src/compose/environment.rs
index 151c7a5..540401b 100644
--- a/src/compose/environment.rs
+++ b/src/compose/environment.rs
@@ -2,19 +2,13 @@ use std::collections::HashMap;
 
 /// Record the shell state
 ///
-/// The [Environment] struct keeps track of various fields, all relating to the
-/// shell state. The environment is the first thing setup at the beginning of
-/// the shell, and is maintained throughout the lifetime of the process.
+/// The [Environment] struct keeps track of various fields, all relating
+/// to the shell state. The environment is the first thing setup at the
+/// beginning of the shell, and is maintained throughout the lifetime of
+/// the process.
 ///
-/// Both [crate::Poem]::read() and [crate::Poem]::recite() rely on this struct
-/// for various functions and features.
-///
-/// # Fields
-/// aliases - A table of aliases, set by the user using the built-in 'alias'
-/// bins - A lookup table for +x files, constructed from the $PATH
-/// cs - Indication of callstack level, helpful for recursively dealing with
-///      aliases
-/// fc - Force the capture of stdout (for internal poems)
+/// Both [read()][crate::poem::read] and [recite()][crate::poem::recite]
+/// rely on this struct for various functions and features.
 ///
 /// # Examples
 /// ```
@@ -22,14 +16,27 @@ use std::collections::HashMap;
 ///     let mut env = compose::env();
 ///     let poem = Poem::read("alias", &mut env)?;
 ///     poem.recite(&mut env)?;
-///     ()
+///     Ok(())
 /// }
 /// ```
 #[derive(Debug, PartialEq, Eq, Clone)]
 pub struct Environment {
+    /// A table of aliases, set by the user using the built-in 'alias'
+    /// command
     pub aliases: HashMap<String, String>,
+
+    /// A lookup table for +x files, constructed from the $PATH (see
+    /// [spellcheck()][crate::poem::elements::verse::Verse::spellcheck]
+    /// for more details)
     pub bins: Vec<String>,
+
+    /// Indication of callstack level, helpful for recursively dealing
+    /// with aliases (see
+    /// [add()][crate::poem::elements::verse::Verse::add] for more
+    /// details)
     pub cs: u8,
+
+    /// Force the capture of STDOUT (for internal poems)
     pub fc: bool,
 }
 
diff --git a/src/poem.rs b/src/poem.rs
index 362eaaa..e330679 100644
--- a/src/poem.rs
+++ b/src/poem.rs
@@ -1,8 +1,8 @@
 mod anthology;
-mod elements;
-use elements::verse::Verse;
+pub mod elements;
 pub mod read;
 pub mod recite;
+use elements::verse::Verse;
 
 /// Parse and run shell commands or `dwvsh` files
 ///
diff --git a/src/poem/anthology.rs b/src/poem/anthology.rs
index 086864c..0026b8d 100644
--- a/src/poem/anthology.rs
+++ b/src/poem/anthology.rs
@@ -15,7 +15,8 @@ static INDEX: [&str; 8] = [
 
 /// Lookup the index of a built-in command
 ///
-/// Looks up the index of a built-in command in [INDEX], accounting for aliases.
+/// Looks up the index of a built-in command in [INDEX], accounting for
+/// aliases.
 ///
 /// # Aliases
 /// * quit -> exit
@@ -29,34 +30,67 @@ pub fn lookup(verb: &str) -> Option<usize> {
     INDEX.iter().position(|v| v.to_string() == verb)
 }
 
+/// Dummy interface for STDIN
+///
+/// A helper struct for dealing with STDIN in built-in commands.
+/// Currently, there are no built-in commands that actually use this,
+/// but it needs to exist for the `incant!()` macro to function
+/// properly. See [Anthology] for more details.
 #[derive(Debug, PartialEq, Eq, Clone)]
 pub struct AnthologyStdin {
+    /// Bytes
     data: Vec<u8>,
 }
 
 impl AnthologyStdin {
+    /// Create a new instance of AnthologyStdin
     pub fn new() -> Self {
         AnthologyStdin { data: Vec::new() }
     }
 
+    /// Return a mutable version of self
     pub fn as_mut(&mut self) -> Option<&mut Self> {
         Some(self)
     }
 
+    /// Write bytes specified by data into STDIN
     pub fn write_all(&mut self, data: &[u8]) -> Result<(), io::Error> {
         self.data.append(&mut data.to_vec());
         Ok(())
     }
 }
 
+/// Interface for built-in commands
+///
+/// The implementation of [Anthology] is designed to mimic
+/// [std::process::Command], in order to avoid code redundancy. The
+/// internal structure of [Anthology] is fairly irrelevant to this
+/// `impl`, with the exception of the `stdin`, and `output` fields. In
+/// addition to the documentation below, it may also be helpful to read
+/// through the `incant!()` macro, so see how processes are actually
+/// forked.
 #[derive(Debug, Clone)]
 pub struct Anthology {
+    /// Name of the built-in command (see [lookup()] and/or [INDEX])
     verb: String,
+
+    /// Arguments to pass to the built-in command
     clause: Option<Vec<String>>,
+
+    /// Indicates STDIN should be read in (but no built-ins use STDIN)
     uin: bool,
+
+    /// Indicates STDOUT should be captured
     uout: bool,
+
+    /// Indicates STDERR should be captured
     uerr: bool,
+
+    /// Compatability with [std::process::Command]
     pub stdin: AnthologyStdin,
+
+    /// Stores the built-in output (return code, STDOUT, STDERR), also
+    /// needed for compatability with [std::process::Command]
     output: Option<Output>,
 }
 
@@ -110,11 +144,28 @@ impl Anthology {
         self.uerr = true;
     }
 
+    /// Set the process group
+    ///
+    /// This is only needed if a process is forked into the background.
+    /// Technically this is possible with the built-ins, but not really
+    /// useful, so this function simply does nothing. As a result,
+    /// built-ins that get forked into the background always return
+    /// immediately.
     pub fn process_group(&mut self, _id: usize) {}
+
+    /// Get the process id
+    ///
+    /// This is only needed if a process is forked into the background.
+    /// Will always return `0` for built-in commands. Also see
+    /// [process_group()][Anthology::process_group].
     pub fn id(&mut self) -> i32 {
         0
     }
 
+    /// Run a built-in command
+    ///
+    /// Runs a built-in command based on the `verb`, appropriately
+    /// passing arguments and [Environment] fields as necessary.
     pub fn spawn(&mut self, env: &mut Environment) -> Result<Self, io::Error> {
         // Incant the built-in and set the output
         self.output = Some(match self.verb.as_str() {
@@ -132,6 +183,10 @@ impl Anthology {
         Ok(self.clone())
     }
 
+    /// Get the output of a built-in
+    ///
+    /// Return the [Output] of a built-in command. This function needed
+    /// for compatibility with [std::process::Command].
     pub fn wait_with_output(&self) -> Result<Output, io::Error> {
         match &self.output {
             Some(output) => Ok(output.clone()),
diff --git a/src/poem/anthology/alias.rs b/src/poem/anthology/alias.rs
index 0746b59..fdd1224 100644
--- a/src/poem/anthology/alias.rs
+++ b/src/poem/anthology/alias.rs
@@ -5,8 +5,8 @@ use std::process::{ExitStatus, Output};
 
 /// alias
 ///
-/// The builtin `alias` command. Used to monikers for other verbs, or entire
-/// verses.
+/// The builtin `alias` command. Used to monikers for other verbs, or
+/// entire verses.
 ///
 /// # Shell Example
 /// ```sh
diff --git a/src/poem/anthology/cd.rs b/src/poem/anthology/cd.rs
index bdf04f6..4427536 100644
--- a/src/poem/anthology/cd.rs
+++ b/src/poem/anthology/cd.rs
@@ -5,13 +5,16 @@ use std::process::{ExitStatus, Output};
 /// cd
 ///
 /// The builtin `cd` command. Used to change directories. This must be
-/// implemented by the shell, since the `pwd` is context sensitive within a
-/// process. If no arguments are given, `cd` will take the user back to their
-/// home directory (i.e. `~`).
+/// implemented by the shell, since the present working directory
+/// (`pwd`) is context sensitive within a process. If no arguments are
+/// given, `cd` will take the user back to their home directory (i.e.
+/// `~` / `$HOME`).
 ///
 /// # Shell Example
 /// ```sh
 /// cd ~/.config # Change into /home/<user>/.config
+/// cd / # Change into the root directory
+/// cd # Change into the home directory
 /// ```
 pub fn incant(clause: &Option<Vec<String>>, uerr: bool) -> Output {
     let status;
diff --git a/src/poem/anthology/export.rs b/src/poem/anthology/export.rs
index 35a24ae..4c8e46d 100644
--- a/src/poem/anthology/export.rs
+++ b/src/poem/anthology/export.rs
@@ -5,8 +5,8 @@ use std::process::{ExitStatus, Output};
 
 /// export
 ///
-/// The builtin `export` command. Used to set global environment variables for
-/// the current instance of the shell.
+/// The builtin `export` command. Used to set global environment
+/// variables for the current instance of the shell.
 ///
 /// # Aliases
 /// * export
diff --git a/src/poem/anthology/source.rs b/src/poem/anthology/source.rs
index 0ed759c..fc27caf 100644
--- a/src/poem/anthology/source.rs
+++ b/src/poem/anthology/source.rs
@@ -6,8 +6,8 @@ use std::process::{ExitStatus, Output};
 
 /// source
 ///
-/// The builtin `source` command. Used to change the shell's global environment
-/// state via a `.sh` or `.dwvsh` file.
+/// The built-in `source` command. Used to change the shell's global
+/// environment state via a `.sh` or `.dwvsh` file.
 ///
 /// # Shell Examples
 /// ```sh
diff --git a/src/poem/anthology/which.rs b/src/poem/anthology/which.rs
index 0872dda..9a1708a 100644
--- a/src/poem/anthology/which.rs
+++ b/src/poem/anthology/which.rs
@@ -4,6 +4,18 @@ use crate::poem::Verse;
 use std::os::unix::process::ExitStatusExt;
 use std::process::{ExitStatus, Output};
 
+/// which
+///
+/// The built-in `which` command. Used to check what program would be
+/// called when not providing a full path. On Linux, it seems most
+/// distros ship with a standalone `which` program. BSD systems, on the
+/// other hand, tend to just use the shell built-in.
+///
+/// # Shell Examples
+/// ```sh
+/// which ls # -> /bin/ls
+/// which exit # -> shell built-in command
+/// ```
 pub fn incant(clause: &Option<Vec<String>>, uout: bool, uerr: bool, env: &Environment) -> Output {
     let mut status = 0;
     let mut out: Vec<u8> = Vec::new();
diff --git a/src/poem/elements/rune.rs b/src/poem/elements/rune.rs
index 688043d..64e3326 100644
--- a/src/poem/elements/rune.rs
+++ b/src/poem/elements/rune.rs
@@ -2,57 +2,75 @@ use core::fmt;
 
 /// Describes one or two characters from the input
 ///
-/// [Rune]s are a way to mark special characters from the input string (i.e.
-/// poetry). Some [Rune]s are special--as they denote the end of a [Verse]--
-/// and are refered to as a Meter. For instance, `Addendum`, `Couplet`,
-/// `Quiet`, and `And`, are all meters. Meters also determine how the
-/// [Stanza][super::stanza::Stanza] should be interpreted. For instance, a
-/// [Stanza][super::stanza::Stanza] that is piped needs to have
-/// its `STDOUT` captured (rather than printing out to the terminal), and
-/// subsequently sent to the next [Verse] in the [Poem][super::super::Poem].
-///
-/// # Values
-/// * `None` - A shell command with no additional actions (the end of a poem)
-/// * `Pause` - The space character, to dilineate words (` `)
-/// * `Path` - The forward slash character, to dilineate paths (`/`)
-/// * `Remark` - Indicates a single line comment (`#`)
-/// * `String` - Interpret all character as one large
-///              [Word][super::word::Word] (`'` or `"`)
-/// * `Poem` - A subcommand to run first (`\``)
-/// * `Read` - Read files into STDIN (`<`)
-/// * `Write` - Write STDOUT to a file (`>`)
-/// * `Write2` - Write STDERR to a file (`2>`)
-/// * `WriteAll` - Write both STDOUT and STDERR to a file (`&>`)
-/// * `Addendum` - Append STDOUT to a file (`>>`)
-/// * `Addendum2` - Append STDERR to a file (`2>>`)
-/// * `AddendumAll` - Append both STDOUT and STDERR to a file (`&>>`)
-/// * `Couplet` - Pipe the output of this command into the next (`|`)
-/// * `Quiet` - Fork the called process into the background (`&`)
-/// * `And` - Run the next command only if this one succeeds (`&&`)
-/// * `Continue` - String commands together on a single line (`;`)
-/// * `Home` - Interpret `~` as `$HOME`
-/// * `Else` - Any other character
+/// [Rune]s are a way to mark special characters from the input string
+/// (i.e. poetry). Some [Rune]s are special--as they denote the end of a
+/// [Verse][crate::poem::Verse]--and are refered to as a Meter. For
+/// instance, `Addendum`, `Couplet`, `Quiet`, and `And`, are all meters.
+/// Meters also determine how the [Stanza][super::stanza::Stanza] should
+/// be interpreted. For instance, a [Stanza][super::stanza::Stanza] that
+/// is piped needs to have its `STDOUT` captured (rather than printing
+/// out to the terminal), and subsequently sent to the next
+/// [Verse][crate::poem::Verse] in the [Poem][super::super::Poem].
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
 pub enum Rune {
-    None,        // No meter (the end of a poem)
-    Pause,       // A space
-    Path,        // A forward slash
-    Remark,      // A comment
-    String,      // Interpret the following as one large [Word]
-    Poem,        // Run a sub-poem before the main one
-    Read,        // Read files into STDIN
-    Write,       // Send STDOUT to a file
-    Write2,      // Send STDERR to a file
-    WriteAll,    // Send STDOUT and STDERR to a file
-    Addendum,    // Append STDOUT to a file
-    Addendum2,   // Append STDERR to a file
-    AddendumAll, // Append STDOUT and STDERR to a file
-    Couplet,     // Pipe the output of this command into the next
-    Quiet,       // Fork the command into the background
-    And,         // Run the next command only if this succeeds
-    Continue,    // Run the next command, even if this doesn't succeed
-    Home,        // Interpret '~' as $HOME
-    Else,        // Any other character
+    /// A shell command with no additional actions (the end of a poem)
+    None,
+
+    /// The space character, to dilineate words (`' '`)
+    Pause,
+
+    /// The forward slash character, to dilineate paths (`/`)
+    Path,
+
+    /// Indicates a single line comment (`#`)
+    Remark,
+
+    /// Interpret all characters as one large [Word][super::word::Word]
+    /// (`'` or `"`)
+    String,
+
+    /// A subcommand to run first (`\``)
+    Poem,
+
+    /// Read files into STDIN (`<`)
+    Read,
+
+    /// Write STDOUT to a file (`>`)
+    Write,
+
+    /// Write STDERR to a file (`2>`)
+    Write2,
+
+    /// Write both STDOUT and STDERR to a file (`&>`)
+    WriteAll,
+
+    /// Append STDOUT to a file (`>>`)
+    Addendum,
+
+    /// Append STDERR to a file (`2>>`)
+    Addendum2,
+
+    /// Append both STDOUT and STDERR to a file (`&>>`)
+    AddendumAll,
+
+    /// Pipe the output of this command into the next (`|`)
+    Couplet,
+
+    /// Fork the called process into the background (`&`)
+    Quiet,
+
+    /// Run the next command, only if this one succeeds (`&&`)
+    And,
+
+    /// Run the next command, regardless of whether or not this command
+    /// succeeds (`;` or a newline in a file)
+    Continue,
+
+    /// Interpret `~` as `$HOME`
+    Home,
+
+    /// Any other character
+    Else,
 }
 
 impl fmt::Display for Rune {
diff --git a/src/poem/elements/stanza.rs b/src/poem/elements/stanza.rs
index d58d080..b5acf32 100644
--- a/src/poem/elements/stanza.rs
+++ b/src/poem/elements/stanza.rs
@@ -1,10 +1,10 @@
 /// The actionable part of a [Verse][super::verse::Verse]
 ///
-/// Each [Stanza] has two parts, a `verb()` and a `clause()`. The `verb()` is
-/// the program, or path to the program to call, while the `clause()` contains
-/// arguments to pass to that program.
+/// Each [Stanza] has two parts, a `verb()` and a `clause()`. The
+/// `verb()` is the program, or path to the program to call, while the
+/// `clause()` contains arguments to pass to that program.
 ///
-/// The [Stanza] is just stored as a [Vec] of [String]s, where the verb is the
-/// first entry in the vector (i.e. `stanza[0]`) and the clause the the
-/// remainder of the vector (i.e. `stanza[1..]`).
+/// The [Stanza] is just stored as a [Vec] of [String]s, where the verb
+/// is the first entry in the vector (i.e. `stanza[0]`) and the clause
+/// the the remainder of the vector (i.e. `stanza[1..]`).
 pub type Stanza = Vec<String>;
diff --git a/src/poem/elements/verse.rs b/src/poem/elements/verse.rs
index b4f41ba..1c5bcc1 100644
--- a/src/poem/elements/verse.rs
+++ b/src/poem/elements/verse.rs
@@ -16,27 +16,83 @@ use std::path::Path;
 use std::process::{Child, Command, Output, Stdio};
 use std::sync::{Arc, Mutex};
 
-/// A [Stanza] and it's [meter](Rune)
+/// A [Stanza] and its [meter](Rune)
 ///
-/// In addition to a [Stanza] and a [meter](Rune), this also holds a [bool]
-/// value called `couplet`, indicating that it needs to accept input on `STDIN`
-/// from the previous [Verse].
+/// In addition to a [Stanza] and a [meter](Rune), this also holds a
+/// [bool] value called `couplet`, indicating that it needs to accept
+/// input on `STDIN` from the previous [Verse].
 #[derive(Debug, Clone)]
 pub struct Verse {
+    /// A command and its arguments (also see [Stanza])
     pub stanza: Stanza,
+
+    /// Denote the couplet status (for piping text in/out)
+    ///
+    /// * `0`: Not a couplet
+    /// * `1`: Left side of a couplet
+    /// * `2`: Right side of a couplet
+    /// * `3`: Both sides of a couplet
+    ///
+    /// ```
+    /// ls | grep Ca | lolcat
+    /// ^    ^         ^
+    /// |    |         2: right side of a couplet
+    /// |    3: both sides of a couplet
+    /// 1: left side of a couplet
+    /// ```
     pub couplet: u8,
+
+    /// A list of IO operations to be performed
+    ///
+    /// For instance, read into STDIN, write STDOUT to a file, etc. May
+    /// be empty. Also see [Rune] for more details.
     pub io: Vec<Rune>,
+
+    /// Input paths
+    ///
+    /// A list of files to read into STDIN, may be empty.
     pub ip: Stanza,
+
+    /// Output paths
+    ///
+    /// A list of files to send STDOUT to, may be empty.
     pub op: Stanza,
+
+    /// Error paths
+    ///
+    /// A list of files to send STDERR to, may be empty.
     pub ep: Stanza,
+
+    /// Internal poems (i.e. 'ls \`ls\`')
+    ///
+    /// A list of poems to evaluate before evaluating this one.
     pub poems: Vec<Poem>,
+
+    /// Interpret how to handle a poem after forking to its command
+    ///
+    /// * `None`: Indicates the end of a poem
+    /// * `Couplet`: Pipe the output of this command into the next (`|`)
+    /// * `Quiet`: Fork the called process into the background (`&`)
+    /// * `And`: Run the next command, only if this one succeeds (`&&`)
+    /// * `Continue`: Run the next command, regardless of whether or not
+    ///               this command succeeds (`;` or a newline in a file)
+    ///
+    /// Also see [Rune] for more details.
     pub meter: Rune,
 }
 
+/// Granularity for [spellcheck()][Verse::spellcheck]
+///
+/// Indicates if a given [verb][Verse::verb] exists, and where.
 #[derive(Debug, Clone)]
 pub enum Spelling {
+    /// The [verb][Verse::verb] is a full path, and that path exists
     FullPath,
+
+    /// The [verb][Verse::verb] is on the `$PATH`
     OnPath(usize),
+
+    /// The [verb][Verse::verb] is a built-in shell command
     BuiltIn(usize),
 }
 
@@ -59,42 +115,8 @@ impl Forkable<Anthology> for Anthology {
 impl Verse {
     /// Create a new [Verse]
     ///
-    /// Returns a new [Verse], with an empty [Stanza], a meter of [Rune::None],
-    /// and `couplet` set to 0.
-    ///
-    /// # Fields
-    /// stanza - The command (a `verb()` and a `clause()`)
-    /// couplet - Indicates couplet status
-    ///           0: Not a couplet (`cat Cargo.toml`)
-    ///           1: Left side of a couplet (`cat Cargo.toml | ...`)
-    ///           2: Right side of a couplet (`... | lolcat`)
-    ///           3: Sandwiched between couplets (`... | grep Ca | ...`)
-    /// io - A list of IO operations ([Rune::Read], [Rune::Write], etc.)
-    /// ip - A list of filenames for reading into STDIN when:
-    ///      [Rune::Read]
-    ///      is specified
-    /// op - A list of filenames for redirecting STDOUT to when:
-    ///      [Rune::Write],
-    ///      [Rune::WriteAll],
-    ///      [Rune::Addendum],
-    ///      and/or [Rune::AddendumAll]
-    ///      is specified
-    /// ep - A list of filenames for redirecting STDERR to when:
-    ///      [Rune::Write2],
-    ///      [Rune::WriteAll],
-    ///      [Rune::Addendum2],
-    ///      and/or [Rune::AddendumAll]
-    ///      is specified
-    /// poems - Internal commands to run before the [Verse] is recited
-    ///         ([Rune::Poem]).
-    /// meter - Determines how the verse is recited in relation to the other
-    ///         verses in the [Poem].
-    ///         [Rune::None] -> Run the command and print the output
-    ///         [Rune::Couplet] -> Pipe the output of this verse into the next
-    ///         [Rune::Quiet] -> Run in the background
-    ///         [Rune::And] -> Run the next verse only if this verse succeeds
-    ///         [Rune::Continue] -> Run the next verse, regardless of whether
-    ///                             or not this verse succeeds
+    /// Returns a new [Verse], with an empty [Stanza], a meter of
+    /// [Rune::None], and `couplet` set to 0.
     pub fn new() -> Self {
         Verse {
             stanza: Stanza::new(),
@@ -153,11 +175,11 @@ impl Verse {
 
     /// Push a word to the [Verse]'s [Stanza]
     ///
-    /// Push a word to the [Verse]'s [Stanza], or one of its IO channels. If
-    /// `word` is empty, this function will simply return without performing
-    /// any operations. A channel of [None] will push to the [Verse]'s
-    /// [Stanza], while IO [Rune]s will determine which IO channel a word will
-    /// get pushed onto.
+    /// Push a word to the [Verse]'s [Stanza], or one of its IO
+    /// channels. If `word` is empty, this function will simply return
+    /// without performing any operations. A channel of [None] will push
+    /// to the [Verse]'s [Stanza], while IO [Rune]s will determine which
+    /// IO channel a word will get pushed onto.
     ///
     /// # Arguments
     /// word - The word to push onto the [Stanza]/channel
@@ -194,35 +216,50 @@ impl Verse {
         word.clear();
     }
 
-    /// Check if the `verb()` exists in the `$PATH`
+    /// Check if the [verb][Verse::verb] exists
     ///
-    /// First checks if the `verb()` is a relative or full path. If it is,
-    /// check whether or not it exists. If it does exist, return true,
-    /// otherwise seeif the `verb()` is cached in our list of binaries. Search is
-    /// done in $PATH order.
+    /// First checks if the [verb][Verse::verb] is a built-in shell
+    /// command. Then checks if the [verb][Verse::verb] is on the
+    /// `$PATH`. If not, then the [verb][Verse::verb] is a either a full
+    /// path, or it does not exist on the system.
     ///
     /// # Examples
     /// ```
-    /// let bins = vec!["cargo", "ruby", "cat"]
-    ///            .into_iter()
-    ///            .map(String::from)
-    ///            .collect<Vec<String>>();
+    /// let command_full_path = vec!["/bin/ls"]
+    ///                         .into_iter()
+    ///                         .map(String::from)
+    ///                         .collect<Vec<String>>();
     ///
-    /// let command_success = vec!["cargo", "build", "--release"]
+    /// let command_on_path = vec!["cargo", "build", "--release"]
     ///                       .into_iter()
     ///                       .map(String::from)
     ///                       .collect<Vec<String>>();
     ///
-    /// let command_fail = vec!["make", "-j8"]
-    ///                    .into_iter()
-    ///                    .map(String::from)
-    ///                    .collect<Vec<String>>();
+    /// let command_built_in = vec!["alias", "g=git"]
+    ///                        .into_iter()
+    ///                        .map(String::from)
+    ///                        .collect<Vec<String>>();
+    ///
+    /// let command_no_exist = vec!["thisdoesntexist"]
+    ///                        .into_iter()
+    ///                        .map(String::from)
+    ///                        .collect<Vec<String>>();
+    ///
+    /// let verse = Verse::new();
+    /// verse.stanza = Stanza::new(command_full_path);
+    /// verse.spellcheck(&env.bins); // -> Some(Spelling::FullPath)
+    ///
+    /// let verse = Verse::new();
+    /// verse.stanza = Stanza::new(command_on_path);
+    /// verse.spellcheck(&env.bins); // -> Some(Spelling::OnPath)
     ///
-    /// let stanza_success = Stanza::new(command_success);
-    /// let stanza_fail = Stanza::new(command_fail);
+    /// let verse = Verse::new();
+    /// verse.stanza = Stanza::new(command_built_in);
+    /// verse.spellcheck(&env.bins); // -> Some(Spelling::BuiltIn)
     ///
-    /// stanza_success.spellcheck(bins) // -> Some(i)
-    /// stanza_fail.spellcheck(bins) // -> None
+    /// let verse = Verse::new();
+    /// verse.stanza = Stanza::new(command_no_exist);
+    /// verse.spellcheck(&env.bins); // -> None
     /// ```
     pub fn spellcheck(&self, bins: &Vec<String>) -> Option<Spelling> {
         // An empty verb (i.e. the empty string) cannot be a program, so
@@ -261,11 +298,12 @@ impl Verse {
 
     /// Run a command
     ///
-    /// The [Poem]::recite() function calls this [Verse::incant] function for
-    /// each verse it contains. This function handles the actual setup and
-    /// spawning (forking) of a new process specified in the [Verse]. It will
-    /// also run IO operations for the verse, and setup appropriate coupling,
-    /// as per the [Verse]'s own details, contained throughout its fields.
+    /// The [recite()][crate::poem::recite] function calls this
+    /// [incant()][Verse::incant] function for each verse it contains.
+    /// This function handles the actual setup and spawning (forking) of
+    /// a new process specified in the [Verse]. It will also run IO
+    /// operations for the verse, and setup appropriate coupling, as per
+    /// the [Verse]'s own details, contained throughout its fields.
     pub fn incant(
         &mut self,
         out: &mut Vec<u8>,
diff --git a/src/poem/elements/verse/logic.rs b/src/poem/elements/verse/logic.rs
index f5efdee..e7ed4df 100644
--- a/src/poem/elements/verse/logic.rs
+++ b/src/poem/elements/verse/logic.rs
@@ -1,3 +1,17 @@
+/// Spawn a program
+///
+/// This macro provides a common interface for running system programs,
+/// as well as built-in shell commands. This is possible, since the
+/// shell's homebrew facilities for running built-ins mimic the
+/// interface of [std::process::Command]. See
+/// [crate::poem::anthology::Anthology] for the implementation details.
+///
+/// First, the macro sets the arguments for the command. Next, it
+/// determines the whether or not text should be piped in/out of the
+/// command. The process is spawned, then it determines what to do based
+/// on the [crate::poem::elements::verse::Verse]'s meter (wait, fork to
+/// background, or capture STDOUT). Finally, the macro performs any IO
+/// functions (i.e. writing/appending STDOUT or STDERR to a file).
 #[macro_export]
 macro_rules! incant {
     ($verb:expr, $command:expr, $out:expr, $pids:expr, $env:expr, $self:expr) => {{
diff --git a/src/poem/elements/word.rs b/src/poem/elements/word.rs
index dd088e0..f51dc7d 100644
--- a/src/poem/elements/word.rs
+++ b/src/poem/elements/word.rs
@@ -1,2 +1,3 @@
-/// A (typically) space dilineated piece of a [Stanza][super::stanza::Stanza]
+/// A (typically) space dilineated piece of a
+/// [Stanza][super::stanza::Stanza]
 pub type Word = Vec<char>;
diff --git a/src/poem/read.rs b/src/poem/read.rs
index 0418738..6d7550b 100644
--- a/src/poem/read.rs
+++ b/src/poem/read.rs
@@ -8,10 +8,35 @@ use crate::compose::Environment;
 use crate::{poem, remark, string};
 use parse::next;
 
+/// Custom errors for the parser ([read()][crate::poem::read])
 #[derive(Debug, PartialEq, Eq)]
 pub enum Mishap {
+    /// Generic parser error
     ParseMishap(usize, usize, char),
+
+    /// IO operation parse errors
+    ///
+    /// Raised when an IO operation is specified, but a filepath was not
+    /// given.
+    ///
+    /// # Examples
+    /// ```sh
+    /// cat < # No file specified for Rune::Read
+    /// cat file.txt >> # No file specified for Rune::Addendum
+    /// ```
     IOMishap(usize, usize, char),
+
+    /// Missing end character
+    ///
+    /// Some [Rune]s consists of two characters, that may contain other
+    /// characters between them (i.e. [String][Rune::String]). This is
+    /// raised when the ending character was left out.
+    ///
+    /// # Examples
+    /// ```sh
+    /// echo 'Hello # Ending ' character is missing
+    /// mv file.txt hello.txt" # Beginning " character is missing
+    /// ```
     PartialMishap(usize, usize, char),
 }
 
@@ -55,13 +80,14 @@ impl Appendable for Poem {
 
     /// Push a [Verse] to the [Poem]
     ///
-    /// Push a [Verse] to the [Poem] after checking that the [Verse] is not
-    /// empty. It also:
+    /// Push a [Verse] to the [Poem] after checking that the [Verse] is
+    /// not empty. It also:
     ///  - sets the meter of the [Verse],
     ///  - determines the couplet status of the [Verse],
     ///  - and checks for aliases associated the the [Verse]'s verb.
     ///
-    /// Once the [Verse] is pushed to the [Poem], the verse stack is cleared.
+    /// Once the [Verse] is pushed to the [Poem], the verse stack is
+    /// cleared.
     ///
     /// # Examples
     /// ```
@@ -157,9 +183,10 @@ impl Readable for Poem {
     /// Parse a [Poem] from a raw [String] input
     ///
     /// Takes a shell command/program or file and converts it to a
-    /// machine-runnable [Poem]. If there is a parse error, [Poem::read] may
-    /// return a [Mishap]. See [Poem::recite][super::recite] or [Verse::incant]
-    /// for how each [Verse] in a [Poem] is called.
+    /// machine-runnable [Poem]. If there is a parse error,
+    /// [read()][Poem::read] may return a [Mishap]. See
+    /// [recite()][crate::poem::recite] or [incant()][Verse::incant] for
+    /// how each [Verse] in a [Poem] is called.
     fn read(poetry: String, env: &mut Environment) -> Result<Poem, Mishap> {
         // Get all the characters in the input string as an iterator
         let mut chars = poetry.chars().into_iter();
diff --git a/src/poem/recite.rs b/src/poem/recite.rs
index 7ceecca..89f71c8 100644
--- a/src/poem/recite.rs
+++ b/src/poem/recite.rs
@@ -17,11 +17,12 @@ pub trait Reciteable {
 impl Reciteable for Poem {
     /// Recite a [Poem]
     ///
-    /// Runs the commands specified in all verses for a given [Poem]. See
-    /// [crate::poem::Verse::incant] for more details on how processes are
-    /// forked. In addition to running each [crate::poem::Verse],
-    /// [Poem::recite] also checks for the presence of environment variables,
-    /// as well as sub-poems, before running the [crate::poem::Verse]'s
+    /// Runs the commands specified in all verses for a given [Poem].
+    /// See [incant()][crate::poem::Verse::incant] for more details on
+    /// how processes are forked. In addition to running each
+    /// [Verse][crate::poem::Verse], [recite()][Poem::recite] also
+    /// checks for the presence of environment variables, as well as
+    /// internal poems, before running the [Verse][crate::poem::Verse]'s
     /// [Stanza].
     fn recite(&self, env: &mut Environment) -> Result<Vec<u8>, io::Error> {
         // Variable for storing the output of a piped verse
-- 
cgit v1.2.3