diff options
author | Rory Dudley | 2024-05-19 18:50:06 -0600 |
---|---|---|
committer | Rory Dudley | 2024-05-19 18:50:06 -0600 |
commit | 4b1b8061e79b42128df4f06fd1e439549bf9696b (patch) | |
tree | 80db43cf7295937751d61435fb4e60118b8a3ea9 /src/poem/read | |
parent | 8756d3e7512c1416cc15a688c62b8f51f030b192 (diff) | |
download | dwarvish-4b1b8061e79b42128df4f06fd1e439549bf9696b.tar.gz |
Handle STDERR, in addition to STDOUT
This patch overhauls the reading and reciting of verses, such that the
redirection of STDERR (in addition to STDOUT, which was already a
feature), is now possible.
Removed the 'stdout' argument from recite(), since it is no longer
needed with how incantations function.
A verse's couplet indicator is now a u8, instead of a bool, with certain
values corresponding to types of couplets, for instance:
ls | grep Ca | lolcat
^ ^ ^
| | 2: right side of a couplet
| 3: both sides of a couplet
1: left side of a couplet
Incantions are no longer hanlded in rune.rs, and the task macros have
been removed. Now, a verse incants itself, matching on its own meter to
determine how to handle the next verse.
The following runes were added to help with handling STDERR:
Write2 -> 2>
WriteAll -> &>
Addendum2 -> 2>>
AddendumAll -> &>>
The 'io' field in verse was changed from an Option<Rune>, to an array of
Runes, since a single verse might have multiple IO operations.
The following fields were added to Verse, to assist with handling
STDERR:
ip -> List of filenames to read into STDIN
op -> List of filenames to send STDOUT to
ep -> List of filenames to send STDERR to
Keep track of channels when reading a poem. Channels are relating to IO
operations. If channel is None, words get pushed to the verse's primary
stanza (i.e. the verb or the clause). If a channel is selected, words
are pushed to one of the aforementioned new fields in Verse.
Read -> ip
Write/Addedum -> op
Write2/Addedum2 -> ep
WriteAll/AddendumAll -> op and ep
Notes
Notes:
This commit also added tests for the new Runes.
Diffstat (limited to 'src/poem/read')
-rw-r--r-- | src/poem/read/parse.rs | 52 |
1 files changed, 34 insertions, 18 deletions
diff --git a/src/poem/read/parse.rs b/src/poem/read/parse.rs index 27c4728..fc1979f 100644 --- a/src/poem/read/parse.rs +++ b/src/poem/read/parse.rs @@ -15,29 +15,45 @@ use std::str::Chars; /// /// # Examples: /// ``` -/// next(&mut chars, &mut i, Rune::Write, vec![('>', Rune::Addendum)]) -/// next(&mut chars, &mut i, Rune::Quiet, vec![('&', Rune::And)]) +/// next(&mut chars, &mut i, Rune::Write, vec![(">", Rune::Addendum)]) +/// next(&mut chars, &mut i, Rune::Quiet, vec![("&", Rune::And)]) /// ``` -pub fn next(chars: &mut Chars, i: &mut usize, otherwise: Rune, ahead: Vec<(char, Rune)>) -> Rune { - // Try to get the next character in the poem - let next = match chars.peekable().peek() { - Some(c) => *c, - None => { - return otherwise; - } - }; +pub fn next(chars: &mut Chars, i: &mut usize, otherwise: Rune, ahead: Vec<(&str, Rune)>) -> Rune { + // Initialize rune (the return value) with the default + let mut rune = otherwise; + + // We need to peek the iterator + let mut peekable = chars.clone().peekable(); + + // Help keep track of matched characters + let mut j = 0; - // Check if that next character matches any characters in ahead - for (c, rune) in ahead.iter() { - if next == *c { - chars.next(); - *i += 1; - return *rune; + // For each tuple pair (string, rune)... + for (s, r) in ahead.iter() { + // For each character in in the string, starting at length j... + for c in s[j..].chars().into_iter() { + // If the next char matches... + match peekable.peek() { + Some(next) if next == &c => { + // Increment counters + chars.next(); + peekable.next(); + *i += 1; + j += 1; + + // Only update the rune if j equals the length of the string + if j == s.len() { + rune = *r; + } + } + Some(_) => {} + None => {} + } } } - // If it doesn't match, return the default - otherwise + // Return whatever the rune was determined to be + rune } /// Keep pushing to the [Word][super::super::elements::word::Word] stack |