#include #include #include #include #include #include #include "../src/path_utils.hpp" #include "../src/text_processor/text_processor.hpp" #include "hoshidicts/deinflector.hpp" #include "hoshidicts/importer.hpp" #include "hoshidicts/lookup.hpp" #include "hoshidicts/query.hpp" void print_usage(const char* program) { std::cout << std::format("Usage:\n"); std::cout << std::format("{} import \n", program); std::cout << std::format("{} deinflect \n", program); std::cout << std::format("{} preprocess \n", program); std::cout << std::format("{} query \n", program); std::cout << std::format("{} lookup \n", program); std::cout << std::format("{} freq \n", program); std::cout << std::format("{} kanji \n", program); } void cmd_import(const std::string& path) { std::filesystem::path source_path = path_utils::from_utf8(path); std::string output_dir = path_utils::to_utf8(source_path.parent_path()); if (output_dir.empty()) { output_dir = "."; } ImportResult result = dictionary_importer::import(path, output_dir); if (result.success) { std::cout << std::format("title: {}\n", result.title); std::cout << std::format("term_count: {}\n", result.summary.counts.terms.total); std::cout << std::format("meta_count: {}\n", result.summary.counts.termMeta["total"]); std::cout << std::format("freq_count: {}\n", result.summary.counts.termMeta["freq"]); std::cout << std::format("pitch_count: {}\n", result.summary.counts.termMeta["pitch"] + result.summary.counts.termMeta["ipa"]); std::cout << std::format("kanji_count: {}\n", result.summary.counts.kanji.total); std::cout << std::format("media_count: {}\n", result.summary.counts.media.total); } else { std::cout << std::format("could not import dictionary: {}\n", result.error); } } void cmd_deinflect(const std::string& inflected) { Deinflector deinflector; auto results = deinflector.deinflect(inflected); std::cout << std::format("deinflections for: {} length: {}\n", inflected, utf8::distance(inflected.begin(), inflected.end())); std::cout << std::format("found {} candidates\n\n", results.size()); for (const auto& r : results) { std::cout << std::format("{} (conditions: {})", r.text, r.conditions); if (!r.trace.empty()) { std::cout << std::format(" "); for (size_t i = 0; i < r.trace.size(); ++i) { std::cout << std::format("{}{}", r.trace[i].name, i < r.trace.size() - 1 ? " -> " : ""); } std::cout << std::format("\n"); } } } void cmd_preprocess(const std::string& text) { auto results = text_processor::process(text); std::cout << std::format("preproccesing for: {} length: {}\n", text, utf8::distance(text.begin(), text.end())); std::cout << std::format("found {} variants\n", results.size()); for (const auto& r : results) { std::cout << std::format("{}\n", r.text); } } void cmd_query(const std::string& db_path, const std::string& expression) { DictionaryQuery dict_query; dict_query.add_term_dict(db_path); auto result = dict_query.query(expression); std::cout << std::format("query results for: {} length: {}\n", expression, utf8::distance(expression.begin(), expression.end())); std::cout << std::format("{} entries\n", result.size()); for (const auto& r : result) { std::cout << std::format("---------------------------------------------------------------\n"); std::cout << std::format("{} {} {}\n", r.expression, r.reading, r.rules); std::cout << std::format("{} glossary entries\n", r.glossaries.size()); for (const auto& g : r.glossaries) { std::cout << std::format("------\n"); std::cout << std::format("{}\n", g.dict_name); std::cout << std::format("{}\n", g.glossary); } } } void cmd_freq(const std::string& path, const std::string& expression, const std::string& reading) { std::vector terms; terms.emplace_back(TermResult{.expression = expression, .reading = reading}); DictionaryQuery query; query.add_freq_dict(path); query.query_freq(terms); std::cout << std::format("frequency entries for: {}\n", expression); int count = 0; for (auto& freq : terms[0].frequencies) { std::cout << std::format("dict: {}\n", freq.dict_name); for (auto& freq_entry : freq.frequencies) { std::cout << std::format("val: {} display_val: {}\n", freq_entry.value, freq_entry.display_value); count++; } } std::cout << std::format("count: {}\n", count); } void cmd_kanji(const std::string& path, const std::string& kanji) { DictionaryQuery query; query.add_kanji_dict(path); auto result = query.query_kanji(kanji); std::cout << std::format("kanji result for: {}\n", kanji); std::cout << std::format("{} entries\n", result.entries.size()); for (const auto& e : result.entries) { std::cout << std::format("---------------------------------------------------------------\n"); std::cout << std::format("dict: {}\n", e.dict_name); std::cout << std::format("onyomi: {}\n", e.onyomi); std::cout << std::format("kunyomi: {}\n", e.kunyomi); std::cout << std::format("tags: {}\n", e.tags); std::cout << std::format("definitions:\n"); for (const auto& def : e.definitions) { std::cout << std::format(" - {}\n", def); } if (!e.stats.empty()) { std::cout << std::format("stats:\n"); for (const auto& [k, v] : e.stats) { std::cout << std::format(" {}: {}\n", k, v); } } } } void cmd_lookup(const std::vector& db_paths, const std::string& lookup_string, int max_results = 8, int scan_length = 16) { DictionaryQuery dict_query; for (const auto& path : db_paths) { dict_query.add_term_dict(path); } Deinflector deinflect; Lookup lookup(dict_query, deinflect); auto result = lookup.lookup(lookup_string, max_results, scan_length); std::cout << std::format("lookup results for: {} max_results: {} scan_length: {}\n", lookup_string, max_results, scan_length); std::cout << std::format("{} results\n", result.size()); for (const auto& r : result) { std::cout << std::format("---------------------------------------------------------------\n"); std::cout << std::format("{}\n", r.matched); if (!r.trace.empty()) { std::cout << std::format(" "); for (size_t i = 0; i < r.trace.size(); ++i) { std::cout << std::format("{}{}", r.trace[i].name, i < r.trace.size() - 1 ? " -> " : ""); } std::cout << std::format("\n"); } std::cout << std::format("{} {}\n", r.term.expression, r.term.reading); for (const auto& g : r.term.glossaries) { std::cout << std::format("------\n"); std::cout << std::format("{}\n", g.dict_name); std::cout << std::format("{}\n", g.glossary); } } std::cout << std::format("styles: \n"); for (const auto& s : dict_query.get_styles()) { std::cout << std::format("{}\n", s.dict_name); std::cout << std::format("{}\n", s.styles); } } int main(int argc, char* argv[]) { if (argc < 2) { print_usage(argv[0]); return 1; } const auto begin = std::chrono::steady_clock::now(); std::string_view command = argv[1]; if (command == "import" && argc >= 3) { cmd_import(argv[2]); } else if (command == "deinflect" && argc >= 3) { cmd_deinflect(argv[2]); } else if (command == "preprocess" && argc >= 3) { cmd_preprocess(argv[2]); } else if (command == "query" && argc >= 4) { cmd_query(argv[2], argv[3]); } else if (command == "lookup" && argc >= 4) { auto db_paths = std::views::counted(argv + 2, argc - 3) | std::views::transform([](const char* arg) { return std::string(arg); }) | std::ranges::to(); std::string term = argv[argc - 1]; cmd_lookup(db_paths, term); } else if (command == "freq" && argc >= 5) { cmd_freq(argv[2], argv[3], argv[4]); } else if (command == "kanji" && argc >= 4) { cmd_kanji(argv[2], argv[3]); } else { print_usage(argv[0]); return 1; } const auto end = std::chrono::steady_clock::now(); std::chrono::duration duration = end - begin; std::cout << std::format("runtime: {}ms\n", duration.count()); return 0; }