From 4d7f63203724d246d5b58a50a57b6e7d42ab7951 Mon Sep 17 00:00:00 2001 From: JJ Date: Sat, 17 Jun 2023 14:23:06 -0700 Subject: minor idiomatic changes --- LICENSE | 2 +- parse_wiki_text/src/display.rs | 4 +-- src/lib.rs | 64 ++++++++++++++++++++++++------------------ src/main.rs | 27 +++++++++--------- 4 files changed, 53 insertions(+), 44 deletions(-) diff --git a/LICENSE b/LICENSE index 90f2d3c..d4d246a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 - Copyright (C) 2022 JJ + Copyright (C) 2023 JJ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/parse_wiki_text/src/display.rs b/parse_wiki_text/src/display.rs index cc2b258..4c1f03a 100644 --- a/parse_wiki_text/src/display.rs +++ b/parse_wiki_text/src/display.rs @@ -6,8 +6,8 @@ use crate::{Node, Parameter}; use std::fmt::Error; -// why is std::other::Result not usable when i import std::fmt::Result? +// why is core::result::Result not usable when i import std::fmt::Result? impl std::fmt::Display for Node<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { return match self { @@ -186,7 +186,7 @@ fn get<'a>(parameters: &'a Vec, index: usize) -> Result<&'a str, Erro } -fn get_language<'a>(country_code: &'a str) -> &'a str { +fn get_language(country_code: &str) -> &'static str { return "English"; // todo: implement necessary parts of isolang // if country_code.len() == 3 { diff --git a/src/lib.rs b/src/lib.rs index afcf8e8..cf2249c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,8 +2,7 @@ #![allow(unused_variables)] #![feature(let_chains)] -use std::io::*; -use std::fs::File; +use std::{io::*, fs::File}; // note that bufread::MultiBzDecoder is _distinct_ from read::MultiBzDecoder use bzip2::bufread::*; use parse_wiki_text::*; @@ -13,13 +12,13 @@ const version: &str = env!("CARGO_PKG_VERSION"); const index_path: &str = env!("index_path"); const dictionary_path: &str = env!("dictionary_path"); -pub fn handle(word: String, state: &State) { +pub fn handle_word(word: String, state: &State) { // if lets are kinda clunky - if let Some(definition) = lookup(&word) { + if let Some(definition) = lookup(&word).unwrap() { display(definition, &state); } else if let Some(corrected) = correct(&word) { println!("Could not find word {}, continuing with {}...", word, corrected); - if let Some(definition) = lookup(&corrected) { + if let Some(definition) = lookup(&corrected).unwrap() { display(definition, &state); } else { println!("Could not find corrected word {}.", corrected); @@ -29,10 +28,22 @@ pub fn handle(word: String, state: &State) { } } +// i don't like that there are multiple result types +// that seems Bad +// also having to explicitly box dyn Error sucks, fine fuck you it's the rust way +type Lookup = std::result::Result, Box>; + // WHY can you not implement traits on external types, like what?? // fortunately we needed to copy-paste the parse_wiki_text library to fix some bugs anyhow -fn lookup(word: &str) -> Option { - let file = File::open(index_path).expect("Failed to open index file"); +fn lookup(word: &str) -> Lookup { + if let Ok(file) = File::open(index_path) { + return lookup_local(word, file); + } else { + return lookup_online(word); + } +} + +fn lookup_local(word: &str, file: File) -> Lookup { let reader = BufReader::new(MultiBzDecoder::new(BufReader::new(file))); for line in reader.lines() { let line = line.expect("Failed to read line"); @@ -41,15 +52,12 @@ fn lookup(word: &str) -> Option { let line = line.splitn(3, ":").collect::>(); assert!(line.len() == 3, "Failed to parse line. Is your index file valid?"); - let offset = line.get(0).unwrap().parse::() - .expect("Failed to parse offset. Is your index file valid?"); - let id = line.get(1).unwrap().parse::() - .expect("Failed to parse id. Is your index file valid?"); + let offset = line.get(0).unwrap().parse::()?; + let id = line.get(1).unwrap().parse::()?; let title = *line.get(2).unwrap(); // this dereference now makes sense if title == word { - let file = File::open(dictionary_path) - .expect("Failed to open dictionary file"); + let file = File::open(dictionary_path)?; let mut reader = BufReader::new(file); // note: our chunk contains multiple pages @@ -74,16 +82,19 @@ fn lookup(word: &str) -> Option { } } } - return Some(buffer); + return Ok(Some(buffer)); } } - return None; + return Ok(None); +} + +fn lookup_online(word: &str) -> Lookup { + todo!(); } // http://norvig.com/spell-correct.html fn correct(word: &str) -> Option<&str> { - // todo: implement - return None; + todo!(); } // now we do somewhat inefficient string manipulation @@ -92,8 +103,8 @@ fn display(definition: String, state: &State) { let definition = Configuration::default().parse(&definition); // this is really quite terrible code - if !display_ii(&definition, |value| value == &state.lang) { - display_ii(&definition, |value| true); + if !display_language(&definition, &state.lang) { + display_language(&definition, ""); } } @@ -106,7 +117,8 @@ const skippable_headers: &[&str; 15] = // no overloading?? O_O // matching on an enum of structs SUCKS -fn display_ii bool>(definition: &Output, f: F) -> bool { +// functions as parameters is too hard +fn display_language(definition: &Output, lang: &str) -> bool { let mut inside_heading = false; let mut correct_language = false; let mut skipping_heading = false; @@ -125,7 +137,7 @@ fn display_ii bool>(definition: &Output, f: F) -> bool { } print!("\n{}\n", node); } - } else if *level == 2 && f(*value) { + } else if *level == 2 && *value == lang { inside_heading = true; correct_language = true; print!("{}", node); @@ -160,16 +172,12 @@ impl State { } // mut state: State, yet state: &mut State?? huh?? -pub fn param(word: String, state: &mut State) { - match word.as_str() { // curious about this +pub fn handle_parameter(word: &str, state: &mut State) { + match word { // todo: extend "--help" => { - println!("dictionarium {}", version); - println!(""); + println!("dictionarium {}\n", version); println!("Usage: dictionarium "); }, - "--full" => { // set some global variable - state.full = true; - }, _ => { println!("Unknown flag \"{}\".", word); } diff --git a/src/main.rs b/src/main.rs index a64aec8..e31b384 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,20 +6,21 @@ fn main() { let args: Vec = env::args().skip(1).collect(); if args.len() == 0 { - dictionarium::param(String::from("--help"), &mut state); - } else { - let mut words = Vec::::new(); - for word in args { - if word.len() > 2 && word.get(0..2).unwrap_or_default() == "--" { - dictionarium::param(word, &mut state); - } else { - words.push(word); - } - } + dictionarium::handle_parameter("--help", &mut state); + std::process::exit(0); + } - // we accept multiple words gladly - for word in words { - dictionarium::handle(word, &state); + let mut words = Vec::::new(); + for word in args { + if word.get(0..2) == Some("--") { + dictionarium::handle_parameter(&word, &mut state); + } else { + words.push(word); } } + + // we accept multiple words gladly + for word in words { + dictionarium::handle_word(word, &state); + } } -- cgit v1.2.3-70-g09d2