Yakudatsu/src/kanji_search.rs
Hiers 6fcd5489d5 Removed unnecessary mallocs.
The colored crate was being used for convinient coloring of the terminal
text, but after profiling I found it was responsible for almost 1/3 of
the memory allocations of the jisho searching feature.

Decided to write ANSI codes manually instead, along with using write! +
format_args! instead of format! for similar reasons, but not as
egregious.
2024-02-17 19:12:09 +00:00

119 lines
4.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use std::{
io::{stdin, stdout, Write},
collections::HashSet,
};
use kradical_parsing::radk;
pub fn search_by_radical(query: &mut String, radk_list: &[radk::Membership]) -> Option<()> {
let mut result: HashSet<_> = HashSet::new();
let mut aux: HashSet<_> = HashSet::new();
if !radk_list.is_empty() {
result.clear();
/* First iteration: get the baseline for the results */
let mut rad = query.chars().nth(1).unwrap();
if rad == '*' || rad == '' {
/* if search_by_strokes failed, then something is very wrong */
rad = search_by_strokes(query, radk_list, 1)?;
}
for k in radk_list.iter() {
if k.radical.glyph.contains(rad) {
for input in &k.kanji {
result.insert(input);
}
break;
}
}
/* Iterate until you've exhausted user input: refine the baseline to get final output */
for (i, mut rad) in query.clone().chars().skip(2).enumerate() {
if rad == '*' || rad == '' {
/* if search_by_strokes failed, then something is very wrong */
rad = search_by_strokes(query, radk_list, i+2)?;
}
for k in radk_list.iter() {
if k.radical.glyph.contains(rad) {
for input in &k.kanji {
aux.insert(input);
}
result = &result & &aux;
aux.clear();
break;
}
}
}
for r in result {
print!("{r} ");
}
println!();
} else {
eprintln!("Error while reading radkfile\nIf you don't have the radkfile, download it from\n\
https://www.edrdg.org/krad/kradinf.html and place it in \"~/.local/share/\" on Linux or \"~\\AppData\\Local\\\" on Windows.\n\
This file is needed to search radicals by strokes.");
}
Some(())
}
fn search_by_strokes(query: &mut String, radk_list: &[radk::Membership], n: usize) -> Option<char> {
let mut strokes = String::new();
let mut radicals: Vec<char> = Vec::new();
let rad;
loop{
print!("How many strokes does your radical have? ");
stdout().flush().ok()?;
strokes.clear();
if stdin().read_line(&mut strokes).ok()? == 0{
std::process::exit(0);
}
match strokes.trim().parse::<u8>() {
Ok(strk) => {
let mut i = 1;
for k in radk_list.iter() {
if k.radical.strokes == strk {
print!("{}{} ", i, k.radical.glyph);
radicals.push(k.radical.glyph.chars().next()?);
i += 1;
} else if k.radical.strokes > strk {
println!();
break;
}
}
loop {
print!("Choose the radical to use for your search: ");
stdout().flush().ok()?;
strokes.clear();
if stdin().read_line(&mut strokes).ok()? == 0{
std::process::exit(0);
}
match strokes.trim().parse::<usize>() {
Ok(strk) => {
if strk < 1 || strk > i-1 {
eprintln!("Couldn't parse input: number not in range");
} else {
rad = radicals.get(strk-1)?;
/* UTF-8 is not fun */
let char_and_index = query.char_indices().nth(n)?;
query.replace_range(char_and_index.0..
char_and_index.0 +
char_and_index.1.len_utf8(),
rad.to_string().as_str());
println!("\x1b[90m{}\x1b[m", query);
return Some(*rad);
}
},
Err(e) => { eprintln!("{e}"); }
}
}
},
Err(e) => { eprintln!("{e}") }
}
}
}