commit 8cc83a4f10e3891654005c72460b344dc9042946 Author: spiders Date: Fri Apr 22 11:56:23 2022 -0700 added project files diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..aac6c9a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "kijetesantakaluotokieni" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +voca_rs = " 1.14.0" + diff --git a/src/bubbles.rs b/src/bubbles.rs new file mode 100644 index 0000000..7b96a28 --- /dev/null +++ b/src/bubbles.rs @@ -0,0 +1,123 @@ +use voca_rs::*; + +pub fn bubble_from_text(text: &str, bubble_anchor: usize, max_length: usize) -> String { + bubble_from_lines(wrap_block(text, max_length), bubble_anchor) +} + +fn bubble_from_lines(lines: Vec, min_length: usize) -> String { + let longest_length: usize; + let lengths: Vec<(&String, usize)> = lines + .iter() + .zip(lines.iter().map(|s| count::count_graphemes(s))) + .collect(); + match lines.iter().map(|s| count::count_graphemes(s)).max() { + None => return "".to_string(), + Some(l) => longest_length = l, + }; + + // let line_length = cmp::max(longest_length, min_length); + let line_length = longest_length; + let pad_length = if longest_length < min_length { + min_length + (longest_length / 2) + 2 + } else { + 0 + }; + let bubble_top = manipulate::pad_left( + &format!(" _{}_ \n", "_".repeat(line_length)), + pad_length, + " ", + ); + let bubble_bottom = manipulate::pad_left( + &format!(" -{}- ", "-".repeat(line_length)), + pad_length, + " ", + ); + let mut bubble_body = String::new(); + + match lines.len() { + 1 => { + return format!( + "{}{}{}", + bubble_top, + manipulate::pad_left(&format!("< {} >\n", lines[0]), pad_length, " "), + bubble_bottom + ) + } + n => { + bubble_body.push_str(&format!("/ {: 2 { + for i in 1..n - 1 { + bubble_body.push_str(&format!("| {: (String, Option) { + let whitespace_not_newline = |c: char| c.is_whitespace() && c != '\n'; + let mut length: usize = 0; + let mut last_space: Option = None; + + for s in split::graphemes(text) { + length = length + 1; + if s == "\n" { + // chop::substring treats 0 as 'till the end of the string' so if we want to cut off initial + // newlines into empty strings we need special handling + let broken_line = if length == 1 { + "".to_string() + } else { + chop::substring(text, 0, length - 1) + }; + let rest = chop::substring(text, length, count::count_graphemes(text)) + .trim_start_matches(whitespace_not_newline) + .to_string(); + return (broken_line, Some(rest)); + } + if query::is_blank(s) { + // minus one because last_space is an index + last_space = Some(length - 1); + } + if length == max_length { + match last_space { + None => { + // breaks in middle of word as in cowsay + let broken_line = chop::substring(text, 0, length); + let rest = chop::substring(text, length, count::count_graphemes(text)) + .trim_start_matches(whitespace_not_newline) + .to_string(); + return (broken_line, Some(rest)); + } + Some(last_space) => { + // break at last whitespace, discarding it + let broken_line = chop::substring(text, 0, last_space); + let rest = chop::substring(text, last_space + 1, count::count_graphemes(text)) + .trim_start_matches(whitespace_not_newline) + .to_string(); + return (broken_line, Some(rest)); + } + }; + }; + } + // if we get here it means the string wasn't long enough to be broken + return (text.to_string(), None); +} + +/* +splits a bunch of text into wrapped lines +*/ +fn wrap_block(text: &str, max_length: usize) -> Vec { + let mut lines: Vec = vec![]; + let mut remaining = text.trim_end().to_string(); + loop { + let (line, rest) = wrap_once(&remaining, max_length); + lines.push(line); + match rest { + None => break, + Some(rest) => remaining = rest, + }; + } + return lines; +} diff --git a/src/critters.rs b/src/critters.rs new file mode 100644 index 0000000..3c06131 --- /dev/null +++ b/src/critters.rs @@ -0,0 +1,125 @@ +use voca_rs::*; + +pub struct Critter<'a> { + pub anchor: usize, + pub critter: &'a str, +} + +pub struct CritterConfig { + pub left_eye: String, + pub right_eye: String, + + pub left_tongue: String, + pub right_tongue: String, + + pub right_line: String, + pub up_line: String, + pub left_line: String, +} + +pub const KIJETESANTAKALU: Critter = Critter { + anchor: 14, + critter: r" + $6 + /__ $6 + / $1$2\ $7 + | |$3$4 + | | + (III|\||", +}; + +pub const KIJETESANTAKALU_LITTLE: Critter = Critter { + anchor: 13, + critter: r" + $6 + /__ $6 + / $1$2\ $5 + | |$3$4 + (I|\||", +}; + +pub fn config_from_string(eyes: &str, tongue: &str, line: &str) -> CritterConfig { + let default_config = CritterConfig { + left_eye: String::from("."), + right_eye: String::from("."), + + left_tongue: String::from(" "), + right_tongue: String::from(" "), + + right_line: String::from("/"), + up_line: String::from("|"), + left_line: String::from("\\"), + }; + + let (left_eye, right_eye); + let (left_tongue, right_tongue); + let (left_line, up_line, right_line); + + match count::count_graphemes(eyes) { + 0 => (left_eye, right_eye) = (default_config.left_eye, default_config.right_eye), + 1 => (left_eye, right_eye) = (chop::grapheme_at(eyes, 0), chop::grapheme_at(eyes, 0)), + _ => (left_eye, right_eye) = (chop::grapheme_at(eyes, 0), chop::grapheme_at(eyes, 1)), + } + match count::count_graphemes(tongue) { + 0 => { + (left_tongue, right_tongue) = (default_config.left_tongue, default_config.right_tongue) + } + 1 => (left_tongue, right_tongue) = (chop::grapheme_at(tongue, 0), " ".to_string()), + _ => { + (left_tongue, right_tongue) = + (chop::grapheme_at(tongue, 0), chop::grapheme_at(tongue, 1)) + } + } + match count::count_graphemes(line) { + 0 => { + (left_line, up_line, right_line) = ( + default_config.left_line, + default_config.up_line, + default_config.right_line, + ) + } + 1 => { + (left_line, up_line, right_line) = ( + chop::grapheme_at(line, 0), + default_config.up_line, + default_config.right_line, + ) + } + 2 => { + (left_line, up_line, right_line) = ( + chop::grapheme_at(line, 0), + chop::grapheme_at(line, 1), + default_config.right_line, + ) + } + _ => { + (left_line, up_line, right_line) = ( + chop::grapheme_at(line, 0), + chop::grapheme_at(line, 1), + chop::grapheme_at(line, 2), + ) + } + } + CritterConfig { + left_eye, + right_eye, + + left_tongue, + right_tongue, + + right_line, + up_line, + left_line, + } +} + +pub fn format_critter(critter: &str, critter_config: CritterConfig) -> String { + return critter + .replace("$1", &critter_config.left_eye) + .replace("$2", &critter_config.right_eye) + .replace("$3", &critter_config.left_tongue) + .replace("$4", &critter_config.right_tongue) + .replace("$5", &critter_config.right_line) + .replace("$6", &critter_config.up_line) + .replace("$7", &critter_config.left_line); +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b8653ea --- /dev/null +++ b/src/main.rs @@ -0,0 +1,40 @@ +/* +TO DO +- options +- kijefiles +- other aminals +*/ + +mod bubbles; +mod critters; + +use std::cmp; +use std::io; +use std::io::Read; +use voca_rs::*; + +fn main() { + let mut text = String::new(); + let default_config = critters::config_from_string("", "", ""); + + io::stdin() + .read_to_string(&mut text) + .expect("failed to read input"); + + print!( + "{}", + bubbles::bubble_from_text( + &text, + critters::KIJETESANTAKALU.anchor, + DEFAULT_MAXIMUM_LINE_LENGTH + ) + ); + println!( + "{}", + critters::format_critter(critters::KIJETESANTAKALU_LITTLE.critter, default_config) + ); +} + +// functions for producing formatted text + +const DEFAULT_MAXIMUM_LINE_LENGTH: usize = 40; diff --git a/test b/test new file mode 100755 index 0000000..54bd882 --- /dev/null +++ b/test @@ -0,0 +1,28 @@ +#!/usr/bin/fish + +echo 1234567890123456789012345678901234567890123456789012345678901234567890 | ./target/debug/kijetesantakaluotokieni + +echo -e "“Oh, you wicked little thing!” cried Alice, catching up the kitten, and giving it a little kiss to make it understand that it was in disgrace. “Really, Dinah ought to have taught you better manners!”\n\n“You ought, Dinah, you know you ought!” she added, looking reproachfully at the old cat, and speaking in as cross a voice as she could manage—and then she scrambled back into the arm-chair, taking the kitten and the worsted with her, and began winding up the ball again." | ./target/debug/kijetesantakaluotokieni + + +#echo -e "'Oh, you wicked little thing!' cried Alice, catching up the kitten, and giving it a little kiss to make it understand that it was in disgrace. 'Really, Dinah ought to have taught you better manners!'\n\n'You ought, Dinah, you know you ought!' she added, looking reproachfully at the old cat, and speaking in as cross a voice as she could manage—and then she scrambled back into the arm-chair, taking the kitten and the worsted with her, and began winding up the ball again." | ./target/debug/kijetesantakaluotokieni + +echo "Белеет парус одинокий +В тумане моря голубом!.. +Что ищет он в стране далекой? +Что кинул он в краю родном?.. + +A lonely sail is flashing white +Amdist the blue mist of the sea!... +What does it seek in foreign lands? +What did it leave behind at home?.." | ./target/debug/kijetesantakaluotokieni + +echo | ./target/debug/kijetesantakaluotokieni + +echo mu | ./target/debug/kijetesantakaluotokieni + +echo 1234567890123 | ./target/debug/kijetesantakaluotokieni + +echo Pingo pi n\'t go li sitelen | ./target/debug/kijetesantakaluotokieni + +echo 420 lol | ./target/debug/kijetesantakaluotokieni \ No newline at end of file