Add docs, new define directive and ASCII table output as an option

This commit is contained in:
mrkmntal 2026-09-24 22:59:45 -04:00
commit 62c941b4e8
12 changed files with 1215 additions and 106 deletions

View file

@ -192,7 +192,7 @@ fn pad_line(content: &str, inner_width: usize) -> String {
format!("{}{}", content, " ".repeat(inner_width.saturating_sub(len)))
}
fn print_table(m: &Match) {
fn print_table_chars(m: &Match, horiz: char, vert: char, tl: char, tr: char, bl: char, br: char, cross: char) {
let home = &m.home.name;
let away = &m.away.name;
let score_line = format!("{home} {}-{} {away}", m.home.score, m.away.score);
@ -230,15 +230,24 @@ fn print_table(m: &Match) {
);
let inner_width = max_content + 2;
println!("╔{}╗", "═".repeat(inner_width));
println!("║{}║", pad_line(&format!("{:^w$}", title, w = inner_width), inner_width));
println!("╠{}╣", "═".repeat(inner_width));
println!("║{}║", pad_line(&format!("{:^w$}", score_line, w = inner_width), inner_width));
println!("╠{}╣", "═".repeat(inner_width));
let h = horiz.to_string().repeat(inner_width);
println!("{}{}{}", tl, h, tr);
println!("{}{}{}", vert, pad_line(&format!("{:^w$}", title, w = inner_width), inner_width), vert);
println!("{}{}{}", cross, h, cross);
println!("{}{}{}", vert, pad_line(&format!("{:^w$}", score_line, w = inner_width), inner_width), vert);
println!("{}{}{}", cross, h, cross);
for line in &lines {
println!("║{}║", pad_line(line, inner_width));
println!("{}{}{}", vert, pad_line(line, inner_width), vert);
}
println!("╚{}╝", "═".repeat(inner_width));
println!("{}{}{}", bl, h, br);
}
fn print_table(m: &Match) {
print_table_chars(m, '═', '║', '╔', '╗', '╚', '╝', '╠');
}
fn print_ascii_table(m: &Match) {
print_table_chars(m, '-', '+', '+', '+', '+', '+', '+');
}
fn print_json(m: &Match) {
@ -337,6 +346,10 @@ fn main() {
print_json(&m);
}
else {
print_table(&m);
match script.as_ref().map(|s| &s.output_mode) {
Some(tsrc::OutputMode::Json) => print_json(&m),
Some(tsrc::OutputMode::AsciiTable) => print_ascii_table(&m),
_ => print_table(&m),
}
}
}

View file

@ -8,6 +8,13 @@ pub struct ScriptedGoal {
pub player: String,
}
#[derive(Debug, PartialEq)]
pub enum OutputMode {
UnicodeTable,
AsciiTable,
Json,
}
#[derive(Debug)]
pub struct TsrcScript {
pub teams: HashMap<String, String>,
@ -15,6 +22,7 @@ pub struct TsrcScript {
pub home_var: String,
pub away_var: String,
pub goals: Option<Vec<ScriptedGoal>>,
pub output_mode: OutputMode,
}
pub fn parse_tsrc(path: &str) -> Result<TsrcScript, String> {
@ -31,6 +39,7 @@ pub fn parse_tsrc(path: &str) -> Result<TsrcScript, String> {
let mut player_entries: HashMap<(String, String), usize> = HashMap::new();
let mut goals: Vec<ScriptedGoal> = Vec::new();
let mut goal_entries: HashMap<(u8, String), usize> = HashMap::new();
let mut output_mode: OutputMode = OutputMode::UnicodeTable;
for (line_num, raw_line) in content.lines().enumerate() {
let n = line_num + 1;
@ -40,7 +49,16 @@ pub fn parse_tsrc(path: &str) -> Result<TsrcScript, String> {
continue;
}
if let Some(rest) = line.strip_prefix("string ") {
if let Some(rest) = line.strip_prefix("#define ") {
if output_mode != OutputMode::UnicodeTable {
return Err(format!(
"tsrc error: output mode already defined on line {} (duplicate #define)",
n
));
}
output_mode = parse_define(rest, n)?;
}
else if let Some(rest) = line.strip_prefix("string ") {
parse_string_decl(rest, n, &mut teams, &mut var_lines)?;
}
else if let Some(rest) = line.strip_prefix("players") {
@ -78,9 +96,22 @@ pub fn parse_tsrc(path: &str) -> Result<TsrcScript, String> {
home_var,
away_var,
goals: if goals.is_empty() { None } else { Some(goals) },
output_mode,
})
}
fn parse_define(s: &str, n: usize) -> Result<OutputMode, String> {
match s.trim() {
"JSON" => Ok(OutputMode::Json),
"UNICODE_TABLE" => Ok(OutputMode::UnicodeTable),
"ASCII_TABLE" => Ok(OutputMode::AsciiTable),
other => Err(format!(
"tsrc error: unknown #define '{}' on line {} (expected JSON, UNICODE_TABLE, or ASCII_TABLE)",
other, n
)),
}
}
fn validate_script(
teams: &HashMap<String, String>,
roster: &HashMap<String, Vec<String>>,