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/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 +- 5 files changed, 195 insertions(+), 124 deletions(-) (limited to 'src/poem/elements') 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; 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, + + /// 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, + + /// 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 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>(); + /// let command_full_path = vec!["/bin/ls"] + /// .into_iter() + /// .map(String::from) + /// .collect>(); /// - /// let command_success = vec!["cargo", "build", "--release"] + /// let command_on_path = vec!["cargo", "build", "--release"] /// .into_iter() /// .map(String::from) /// .collect>(); /// - /// let command_fail = vec!["make", "-j8"] - /// .into_iter() - /// .map(String::from) - /// .collect>(); + /// let command_built_in = vec!["alias", "g=git"] + /// .into_iter() + /// .map(String::from) + /// .collect>(); + /// + /// let command_no_exist = vec!["thisdoesntexist"] + /// .into_iter() + /// .map(String::from) + /// .collect>(); + /// + /// 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) -> Option { // 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, 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; -- cgit v1.2.3