void Library::print_search_result(FILE *out, const TSearchResult & res) { string loc_bookname, loc_def, loc_exp; if(!utf8_output){ loc_bookname=utf8_to_locale_ign_err(res.bookname); loc_def=utf8_to_locale_ign_err(res.def); loc_exp=utf8_to_locale_ign_err(res.exp); } fprintf(out, "-->%s\n-->%s\n%s\n\n", utf8_output ? res.bookname.c_str() : loc_bookname.c_str(), utf8_output ? res.def.c_str() : loc_def.c_str(), utf8_output ? res.exp.c_str() : loc_exp.c_str()); }
void operator()(const std::string& filename, bool) { DictInfo dict_info; if (dict_info.load_from_ifo_file(filename, false)) { string bookname=utf8_to_locale_ign_err(dict_info.bookname); printf("%s %d\n", bookname.c_str(), dict_info.wordcount); } }
static void list_dicts(const std::list<std::string> &dicts_dir_list, bool use_json) { bool first_entry = true; if (!use_json) printf(_("Dictionary's name Word count\n")); else fputc('[', stdout); std::list<std::string> order_list, disable_list; for_each_file(dicts_dir_list, ".ifo", order_list, disable_list, [use_json, &first_entry](const std::string &filename, bool) -> void { DictInfo dict_info; if (dict_info.load_from_ifo_file(filename, false)) { const std::string bookname = utf8_to_locale_ign_err(dict_info.bookname); if (use_json) { if (first_entry) { first_entry = false; } else { fputc(',', stdout); // comma between entries } printf("{\"name\": \"%s\", \"wordcount\": \"%d\"}", json_escape_string(bookname).c_str(), dict_info.wordcount); } else { printf("%s %d\n", bookname.c_str(), dict_info.wordcount); } } }); if (use_json) fputs("]\n", stdout); }
bool Library::process_phrase(const char *loc_str, read_line &io, bool force, bool json) { if (NULL==loc_str) return true; std::string query; analyze_query(loc_str, query); if (!query.empty()) io.add_to_history(query.c_str()); gsize bytes_read; gsize bytes_written; GError *err=NULL; char *str=NULL; if (!utf8_input) str=g_locale_to_utf8(loc_str, -1, &bytes_read, &bytes_written, &err); else str=g_strdup(loc_str); if (NULL==str) { fprintf(stderr, _("Can not convert %s to utf8.\n"), loc_str); fprintf(stderr, "%s\n", err->message); g_error_free(err); return false; } if (str[0]=='\0') return true; TSearchResultList res_list; switch (analyze_query(str, query)) { case qtFUZZY: LookupWithFuzzy(query, res_list); break; case qtREGEXP: LookupWithRule(query, res_list); break; case qtSIMPLE: SimpleLookup(str, res_list); if (res_list.empty()) LookupWithFuzzy(str, res_list); break; case qtDATA: LookupData(query, res_list); break; default: /*nothing*/; } if (!res_list.empty()) { /* try to be more clever, if there are one or zero results per dictionary show all */ bool show_all_results=true; typedef std::map< string, int, std::less<string> > DictResMap; if (!force) { DictResMap res_per_dict; for(TSearchResultList::iterator ptr=res_list.begin(); ptr!=res_list.end(); ++ptr){ std::pair<DictResMap::iterator, DictResMap::iterator> r = res_per_dict.equal_range(ptr->bookname); DictResMap tmp(r.first, r.second); if (tmp.empty()) //there are no yet such bookname in map res_per_dict.insert(DictResMap::value_type(ptr->bookname, 1)); else { ++((tmp.begin())->second); if (tmp.begin()->second>1) { show_all_results=false; break; } } } }//if (!force) if (!show_all_results && !force) { printf(_("Found %d items, similar to %s.\n"), res_list.size(), utf8_output ? str : utf8_to_locale_ign_err(str).c_str()); for (size_t i=0; i<res_list.size(); ++i) { string loc_bookname, loc_def; loc_bookname=utf8_to_locale_ign_err(res_list[i].bookname); loc_def=utf8_to_locale_ign_err(res_list[i].def); printf("%d)%s-->%s\n", i, utf8_output ? res_list[i].bookname.c_str() : loc_bookname.c_str(), utf8_output ? res_list[i].def.c_str() : loc_def.c_str()); } int choise; for (;;) { string str_choise; printf(_("Your choice[-1 to abort]: ")); if(!stdio_getline(stdin, str_choise)){ putchar('\n'); exit(EXIT_SUCCESS); } sscanf(str_choise.c_str(), "%d", &choise); if (choise>=0 && choise<int(res_list.size())) { sdcv_pager pager; print_search_result(pager.get_stream(), res_list[choise]); break; } else if (choise==-1) break; else printf(_("Invalid choise.\nIt must be from 0 to %d or -1.\n"), res_list.size()-1); } } else { sdcv_pager pager(force); if (!json) { fprintf(pager.get_stream(), _("Found %d items, similar to %s.\n"), res_list.size(), utf8_output ? str : utf8_to_locale_ign_err(str).c_str()); for (PSearchResult ptr=res_list.begin(); ptr!=res_list.end(); ++ptr) print_search_result(pager.get_stream(), *ptr); } else { char *out; cJSON *root,*fld; root=cJSON_CreateArray(); for (PSearchResult ptr=res_list.begin(); ptr!=res_list.end(); ++ptr) { const TSearchResult & res = *ptr; string loc_bookname, loc_def, loc_exp; if(!utf8_output){ loc_bookname=utf8_to_locale_ign_err(res.bookname); loc_def=utf8_to_locale_ign_err(res.def); loc_exp=utf8_to_locale_ign_err(res.exp); } cJSON_AddItemToArray(root,fld=cJSON_CreateObject()); cJSON_AddStringToObject(fld, "dict", utf8_output ? res.bookname.c_str() : loc_bookname.c_str()); cJSON_AddStringToObject(fld, "word", utf8_output ? res.def.c_str() : loc_def.c_str()); cJSON_AddStringToObject(fld, "definition", utf8_output ? res.exp.c_str() : loc_exp.c_str()); } out=cJSON_Print(root); cJSON_Delete(root); fprintf(pager.get_stream(), "%s", out); free(out); } } } else { string loc_str; if (!utf8_output) loc_str=utf8_to_locale_ign_err(str); printf(_("Nothing similar to %s, sorry :(\n"), utf8_output ? str : loc_str.c_str()); } g_free(str); return true; }
int main(int argc, char *argv[]) try { setlocale(LC_ALL, ""); #if ENABLE_NLS bindtextdomain("sdcv", //"./locale"//< for testing GETTEXT_TRANSLATIONS_PATH //< should be ); textdomain("sdcv"); #endif gboolean show_version = FALSE; gboolean show_list_dicts = FALSE; glib::StrArr use_dict_list; gboolean non_interactive = FALSE; gboolean utf8_output = FALSE; gboolean utf8_input = FALSE; glib::CharStr opt_data_dir; gboolean colorize = FALSE; const GOptionEntry entries[] = { { "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, _("display version information and exit"), nullptr }, { "list-dicts", 'l', 0, G_OPTION_ARG_NONE, &show_list_dicts, _("display list of available dictionaries and exit"), nullptr }, { "use-dict", 'u', 0, G_OPTION_ARG_STRING_ARRAY, get_addr(use_dict_list), _("for search use only dictionary with this bookname"), _("bookname") }, { "non-interactive", 'n', 0, G_OPTION_ARG_NONE, &non_interactive, _("for use in scripts"), nullptr }, { "utf8-output", '0', 0, G_OPTION_ARG_NONE, &utf8_output, _("output must be in utf8"), nullptr }, { "utf8-input", '1', 0, G_OPTION_ARG_NONE, &utf8_input, _("input of sdcv in utf8"), nullptr }, { "data-dir", '2', 0, G_OPTION_ARG_STRING, get_addr(opt_data_dir), _("use this directory as path to stardict data directory"), _("path/to/dir") }, { "color", 'c', 0, G_OPTION_ARG_NONE, &colorize, _("colorize the output"), nullptr }, { nullptr }, }; glib::Error error; GOptionContext *context = g_option_context_new(_(" words")); g_option_context_set_help_enabled(context, TRUE); g_option_context_add_main_entries(context, entries, nullptr); const gboolean parse_res = g_option_context_parse(context, &argc, &argv, get_addr(error)); g_option_context_free(context); if (!parse_res) { fprintf(stderr, _("Invalid command line arguments: %s\n"), error->message); return EXIT_FAILURE; } if (show_version) { printf(_("Console version of Stardict, version %s\n"), gVersion); return EXIT_SUCCESS; } const gchar *stardict_data_dir = g_getenv("STARDICT_DATA_DIR"); std::string data_dir; if (!opt_data_dir) { if (stardict_data_dir) data_dir = stardict_data_dir; else data_dir = "/usr/share/stardict/dic"; } else { data_dir = get_impl(opt_data_dir); } const char *homedir = g_getenv("HOME"); if (!homedir) homedir = g_get_home_dir(); const std::list<std::string> dicts_dir_list = { std::string(homedir) + G_DIR_SEPARATOR + ".stardict" + G_DIR_SEPARATOR + "dic", data_dir }; if (show_list_dicts) { printf(_("Dictionary's name Word count\n")); std::list<std::string> order_list, disable_list; for_each_file(dicts_dir_list, ".ifo", order_list, disable_list, [](const std::string &filename, bool) -> void { DictInfo dict_info; if (dict_info.load_from_ifo_file(filename, false)) { const std::string bookname = utf8_to_locale_ign_err(dict_info.bookname); printf("%s %d\n", bookname.c_str(), dict_info.wordcount); } }); return EXIT_SUCCESS; } std::list<std::string> disable_list; if (use_dict_list) { std::list<std::string> empty_list; for_each_file(dicts_dir_list, ".ifo", empty_list, empty_list, [&disable_list, &use_dict_list](const std::string &filename, bool) -> void { DictInfo dict_info; const bool load_ok = dict_info.load_from_ifo_file(filename, false); if (!load_ok) return; for (gchar **p = get_impl(use_dict_list); *p != nullptr; ++p) if (strcmp(*p, dict_info.bookname.c_str()) == 0) return; disable_list.push_back(dict_info.ifo_file_name); }); } const std::string conf_dir = std::string(g_get_home_dir()) + G_DIR_SEPARATOR + ".stardict"; if (g_mkdir(conf_dir.c_str(), S_IRWXU) == -1 && errno != EEXIST) fprintf(stderr, _("g_mkdir failed: %s\n"), strerror(errno)); Library lib(utf8_input, utf8_output, colorize); std::list<std::string> empty_list; lib.load(dicts_dir_list, empty_list, disable_list); std::unique_ptr<IReadLine> io(create_readline_object()); if (optind < argc) { for (int i = optind; i < argc; ++i) if (!lib.process_phrase(argv[i], *io, non_interactive)) return EXIT_FAILURE; } else if (!non_interactive) { std::string phrase; while (io->read(_("Enter word or phrase: "), phrase)) { if (!lib.process_phrase(phrase.c_str(), *io)) return EXIT_FAILURE; phrase.clear(); } putchar('\n'); } else { fprintf(stderr, _("There are no words/phrases to translate.\n")); } return EXIT_SUCCESS; } catch (const std::exception &ex) { fprintf(stderr, "Internal error: %s\n", ex.what()); exit(EXIT_FAILURE); }