use std::{error::Error, path::PathBuf};
use clap::{Parser, Subcommand, ValueEnum};
use jpreprocess_dictionary::dictionary::to_dict::JPreprocessDictionaryBuilder;
use lindera::dictionary::{load_fs_dictionary, load_user_dictionary_from_bin};
use lindera_dictionary::{builder::DictionaryBuilder, dictionary::metadata::Metadata};
use crate::dict_query::QueryDict;
mod dict_query;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand, Debug)]
enum Commands {
Inspect {
#[arg(short, long)]
word_id: Option<u32>,
input: PathBuf,
},
Build {
#[arg(short, long)]
user: bool,
serializer: Serializer,
#[arg(short, long)]
metadata: Option<PathBuf>,
input: PathBuf,
output: PathBuf,
},
}
#[derive(Clone, ValueEnum, Debug)]
enum Serializer {
Lindera,
Jpreprocess,
}
fn main() -> Result<(), Box<dyn Error>> {
let cli = Cli::parse();
match cli.command {
Commands::Inspect { word_id, input } => {
let is_system_dict = input.is_dir()
&& input.join("dict.wordsidx").exists()
&& input.join("dict.words").exists();
let is_user_bin_dict =
input.is_file() && matches!(input.extension(),Some(s) if s.to_str()==Some("bin"));
if is_system_dict || is_user_bin_dict {
let dict = if is_system_dict {
println!("Lindera/JPreprocess system dictionary.");
let dict = load_fs_dictionary(&input)?;
QueryDict::System(dict)
} else {
println!("Lindera/JPreprocess user dictionary.");
if input.extension().unwrap() != "bin" {
eprintln!("User dictionary must be a `.bin` file.");
std::process::exit(-1);
}
let dict = load_user_dictionary_from_bin(&input)?;
QueryDict::User(dict)
};
let serializer = if let Some(identifier) = dict.identifier() {
println!("Dictionary identifier: {}", identifier);
if identifier.starts_with("jpreprocess") {
Serializer::Jpreprocess
} else {
Serializer::Lindera
}
} else {
println!("No identifier found. Assuming lindera dictionary.");
Serializer::Lindera
};
if let Some(word_id) = word_id {
match serializer {
Serializer::Lindera => {
let Some(word_details) = dict.get_as_lindera(word_id) else {
eprintln!("Word not found");
std::process::exit(-1);
};
for detail in word_details {
println!("{}", detail);
}
}
Serializer::Jpreprocess => {
let Some(word_details) = dict.get_as_jpreprocess(word_id) else {
eprintln!("Word not found");
std::process::exit(-1);
};
println!("{}", word_details.to_str_vec("".to_owned()).join(","));
}
}
}
}
}
Commands::Build {
user,
serializer: serializer_config,
metadata: metadata_path,
input,
output,
} => {
let metadata = if let Some(metadata_path) = metadata_path {
println!("Loading metadata from {:?}", metadata_path);
let data = std::fs::read(&metadata_path)?;
Metadata::load(&data)?
} else {
match serializer_config {
Serializer::Lindera => {
println!("Using default lindera metadata.");
Metadata::default()
}
Serializer::Jpreprocess => {
println!("Using default jpreprocess metadata.");
JPreprocessDictionaryBuilder::default_metadata()
}
}
};
println!("Building dictionary...");
match serializer_config {
Serializer::Lindera => {
let builder = DictionaryBuilder::new(metadata);
if user {
builder.build_user_dictionary(&input, &output)?;
} else {
builder.build_dictionary(&input, &output)?;
}
}
Serializer::Jpreprocess => {
let builder = JPreprocessDictionaryBuilder::new(metadata);
if user {
builder.build_user_dictionary(&input, &output)?;
} else {
builder.build_dictionary(&input, &output)?;
}
}
}
println!("done.");
}
}
Ok(())
}