diff --git a/src/libwrapper.cpp b/src/libwrapper.cpp index b3c2d3d..c50baaa 100644 --- a/src/libwrapper.cpp +++ b/src/libwrapper.cpp @@ -32,85 +32,107 @@ #include "libwrapper.hpp" +static const char ESC_BLUE[] = "\033[0;34m"; +static const char ESC_END[] = "\033[0m"; +static const char ESC_BOLD[] = "\033[1m"; +static const char ESC_ITALIC[] = "\033[3m"; +static const char ESC_LIGHT_GRAY[] = "\033[0;37m"; +static const char ESC_GREEN[] = "\033[0;32m"; -static std::string xdxf2text(const char *p) +static const char *SEARCH_TERM_VISFMT = ESC_BOLD; +static const char *NAME_OF_DICT_VISFMT = ESC_BLUE; +static const char *TRANSCRIPTION_VISFMT = ESC_BOLD; +static const char *DEF_COLOR_VISFMT = ESC_BLUE; +static const char *EXAMPLE_VISFMT = ESC_LIGHT_GRAY; +static const char *KREF_VISFMT = ESC_BOLD; +static const char *ABR_VISFMT = ESC_GREEN; + +static std::string xdxf2text(const char *p, bool colorize_output) { std::string res; for (; *p; ++p) { - if (*p!='<') { + if (*p != '<') { if (g_str_has_prefix(p, ">")) { - res+=">"; - p+=3; + res += ">"; + p += 3; } else if (g_str_has_prefix(p, "<")) { - res+="<"; - p+=3; + res += "<"; + p += 3; } else if (g_str_has_prefix(p, "&")) { - res+="&"; - p+=4; + res += "&"; + p += 4; } else if (g_str_has_prefix(p, """)) { - res+="\""; - p+=5; + res += "\""; + p += 5; } else - res+=*p; + res += *p; continue; } - const char *next=strchr(p, '>'); + const char *next = strchr(p, '>'); if (!next) continue; - std::string name(p+1, next-p-1); + const std::string name(p+1, next-p-1); - if (name=="abr") - res+=""; + if (name == "abr") + res += colorize_output ? ABR_VISFMT : ""; else if (name=="/abr") - res+=""; - else if (name=="k") { - const char *begin=next; - if ((next=strstr(begin, ""))!=nullptr) - next+=sizeof("")-1-1; + res += colorize_output ? ESC_END : ""; + else if (name == "k") { + const char *begin = next; + if ((next = strstr(begin, "")) != nullptr) + next += sizeof("") - 1 - 1; else - next=begin; - } else if (name=="b") - res+=""; + next = begin; + } else if (name == "kref") { + res += colorize_output ? KREF_VISFMT : ""; + } else if (name == "/kref") { + res += colorize_output ? ESC_END : ""; + } else if (name == "b") + res += colorize_output ? ESC_BOLD : ""; else if (name=="/b") - res+=""; - else if (name=="i") - res+=""; - else if (name=="/i") - res+=""; - else if (name=="tr") - res+="["; - else if (name=="/tr") - res+="]"; - else if (name=="ex") - res+=""; - else if (name=="/ex") - res+=""; - else if (!name.empty() && name[0]=='c' && name!="co") { - std::string::size_type pos=name.find("code"); - if (pos!=std::string::size_type(-1)) { - pos+=sizeof("code=\"")-1; - std::string::size_type end_pos=name.find("\""); - std::string color(name, pos, end_pos-pos); - res+=""; + res += colorize_output ? ESC_END : ""; + else if (name == "i") + res += colorize_output ? ESC_ITALIC : ""; + else if (name == "/i") + res += colorize_output ? ESC_END : ""; + else if (name == "tr") { + if (colorize_output) + res += TRANSCRIPTION_VISFMT; + res += "["; + } else if (name == "/tr") { + res += "]"; + if (colorize_output) + res += ESC_END; + } else if (name == "ex") + res += colorize_output ? EXAMPLE_VISFMT : ""; + else if (name == "/ex") + res += colorize_output ? ESC_END : ""; + else if (!name.empty() && name[0] == 'c' && name != "co") { + std::string::size_type pos = name.find("code"); + if (pos != std::string::npos) { + pos += sizeof("code=\"") - 1; + std::string::size_type end_pos = name.find("\""); + const std::string color(name, pos, end_pos - pos); + res += ""; } else { - res+=""; + res += ""; } - } else if (name=="/c") - res+=""; + } else if (name == "/c") + res += ""; - p=next; + p = next; } return res; } -static string parse_data(const gchar *data) +static std::string parse_data(const gchar *data, bool colorize_output) { if (!data) return ""; - string res; + std::string res; guint32 data_size, sec_size=0; gchar *m_str; const gchar *p=data; @@ -135,7 +157,7 @@ static string parse_data(const gchar *data) if (sec_size) { res+="\n"; m_str = g_strndup(p, sec_size); - res += xdxf2text(m_str); + res += xdxf2text(m_str, colorize_output); g_free(m_str); } sec_size++; @@ -143,10 +165,12 @@ static string parse_data(const gchar *data) case 't': sec_size = strlen(p); if(sec_size){ - res+="\n"; - m_str = g_strndup(p, sec_size); - res += "["+string(m_str)+"]"; - g_free(m_str); + res += "\n"; + if (colorize_output) + res += TRANSCRIPTION_VISFMT; + res += "[" + std::string(p, sec_size) + "]"; + if (colorize_output) + res += ESC_END; } sec_size++; break; @@ -156,8 +180,8 @@ static string parse_data(const gchar *data) break; case 'W': case 'P': - sec_size=*((guint32 *)p); - sec_size+=sizeof(guint32); + sec_size = *((guint32 *)p); + sec_size += sizeof(guint32); break; } p += sec_size; @@ -167,7 +191,7 @@ static string parse_data(const gchar *data) return res; } -void Library::SimpleLookup(const string &str, TSearchResultList& res_list) +void Library::SimpleLookup(const std::string &str, TSearchResultList& res_list) { glong ind; res_list.reserve(ndicts()); @@ -175,12 +199,12 @@ void Library::SimpleLookup(const string &str, TSearchResultList& res_list) if (SimpleLookupWord(str.c_str(), ind, idict)) res_list.push_back( TSearchResult(dict_name(idict), - poGetWord(ind, idict), - parse_data(poGetWordData(ind, idict)))); + poGetWord(ind, idict), + parse_data(poGetWordData(ind, idict), colorize_output_))); } -void Library::LookupWithFuzzy(const string &str, TSearchResultList& res_list) +void Library::LookupWithFuzzy(const std::string &str, TSearchResultList& res_list) { static const int MAXFUZZY=10; @@ -195,7 +219,7 @@ void Library::LookupWithFuzzy(const string &str, TSearchResultList& res_list) } } -void Library::LookupWithRule(const string &str, TSearchResultList& res_list) +void Library::LookupWithRule(const std::string &str, TSearchResultList& res_list) { std::vector match_res((MAX_MATCH_ITEM_PER_LIB) * ndicts()); @@ -209,38 +233,45 @@ void Library::LookupWithRule(const string &str, TSearchResultList& res_list) } } -void Library::LookupData(const string &str, TSearchResultList& res_list) +void Library::LookupData(const std::string &str, TSearchResultList& res_list) { std::vector > drl(ndicts()); if (!Libs::LookupData(str.c_str(), &drl[0])) return; for (int idict = 0; idict < ndicts(); ++idict) - for (std::vector::size_type j=0; j < drl[idict].size(); ++j) { - SimpleLookup(drl[idict][j], res_list); - g_free(drl[idict][j]); + for (gchar *res : drl[idict]) { + SimpleLookup(res, res_list); + g_free(res); } } void Library::print_search_result(FILE *out, const TSearchResult & res) { std::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); + + 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()); + fprintf(out, + "-->%s%s%s\n" + "-->%s%s%s\n" + "%s\n\n", + colorize_output_ ? NAME_OF_DICT_VISFMT : "", + utf8_output_ ? res.bookname.c_str() : loc_bookname.c_str(), + colorize_output_ ? ESC_END : "", + colorize_output_ ? SEARCH_TERM_VISFMT : "", + utf8_output_ ? res.def.c_str() : loc_def.c_str(), + colorize_output_ ? ESC_END : "", + utf8_output_ ? res.exp.c_str() : loc_exp.c_str()); } namespace { class sdcv_pager { public: - sdcv_pager(bool ignore_env=false) { + sdcv_pager(bool ignore_env = false) { output = stdout; if (ignore_env) return; @@ -264,7 +295,7 @@ namespace { bool Library::process_phrase(const char *loc_str, IReadLine &io, bool force) { - if (nullptr==loc_str) + if (nullptr == loc_str) return true; std::string query; @@ -277,12 +308,12 @@ bool Library::process_phrase(const char *loc_str, IReadLine &io, bool force) gsize bytes_written; GError *err = nullptr; char *str = nullptr; - if (!utf8_input) + if (!utf8_input_) str = g_locale_to_utf8(loc_str, -1, &bytes_read, &bytes_written, &err); else str = g_strdup(loc_str); - if (nullptr==str) { + if (nullptr == str) { fprintf(stderr, _("Can not convert %s to utf8.\n"), loc_str); fprintf(stderr, "%s\n", err->message); g_error_free(err); @@ -318,7 +349,7 @@ bool Library::process_phrase(const char *loc_str, IReadLine &io, bool force) one or zero results per dictionary show all */ bool show_all_results = true; - typedef std::map< string, int, std::less > DictResMap; + typedef std::map< std::string, int, std::less > DictResMap; if (!force) { DictResMap res_per_dict; for (const TSearchResult& search_res : res_list) { @@ -338,13 +369,17 @@ bool Library::process_phrase(const char *loc_str, IReadLine &io, bool force) if (!show_all_results && !force) { printf(_("Found %zu items, similar to %s.\n"), res_list.size(), - utf8_output ? str : utf8_to_locale_ign_err(str).c_str()); + utf8_output_ ? str : utf8_to_locale_ign_err(str).c_str()); for (size_t i = 0; i < res_list.size(); ++i) { const std::string loc_bookname = utf8_to_locale_ign_err(res_list[i].bookname); const std::string loc_def = utf8_to_locale_ign_err(res_list[i].def); - printf("%zu)%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()); + printf("%zu)%s%s%s-->%s%s%s\n", i, + colorize_output_ ? NAME_OF_DICT_VISFMT : "", + utf8_output_ ? res_list[i].bookname.c_str() : loc_bookname.c_str(), + colorize_output_ ? ESC_END : "", + colorize_output_ ? SEARCH_TERM_VISFMT : "", + utf8_output_ ? res_list[i].def.c_str() : loc_def.c_str(), + colorize_output_ ? ESC_END : ""); } int choise; std::unique_ptr choice_readline(create_readline_object()); @@ -365,17 +400,17 @@ bool Library::process_phrase(const char *loc_str, IReadLine &io, bool force) } else { sdcv_pager pager(force); fprintf(pager.get_stream(), _("Found %zu items, similar to %s.\n"), - res_list.size(), utf8_output ? str : utf8_to_locale_ign_err(str).c_str()); + res_list.size(), utf8_output_ ? str : utf8_to_locale_ign_err(str).c_str()); for (const TSearchResult& search_res : res_list) print_search_result(pager.get_stream(), search_res); } } else { std::string loc_str; - if (!utf8_output) - loc_str=utf8_to_locale_ign_err(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()); + printf(_("Nothing similar to %s, sorry :(\n"), utf8_output_ ? str : loc_str.c_str()); } g_free(str); diff --git a/src/libwrapper.hpp b/src/libwrapper.hpp index b3a215c..4eb3f62 100644 --- a/src/libwrapper.hpp +++ b/src/libwrapper.hpp @@ -7,17 +7,14 @@ #include "lib.hpp" #include "readline.hpp" -using std::string; -using std::vector; - //this structure is wrapper and it need for unification //results of search whith return Dicts class struct TSearchResult { - string bookname; - string def; - string exp; + std::string bookname; + std::string def; + std::string exp; - TSearchResult(const string& bookname_, const string& def_, const string& exp_) + TSearchResult(const std::string& bookname_, const std::string& def_, const std::string& exp_) : bookname(bookname_), def(def_), exp(exp_) { } @@ -29,17 +26,19 @@ typedef std::vector TSearchResultList; //of it class Library : public Libs { public: - Library(bool uinput, bool uoutput) : - utf8_input(uinput), utf8_output(uoutput) {} + Library(bool uinput, bool uoutput, bool colorize_output): + utf8_input_(uinput), utf8_output_(uoutput), colorize_output_(colorize_output) {} - bool process_phrase(const char *loc_str, IReadLine &io, bool force=false); + bool process_phrase(const char *loc_str, IReadLine &io, bool force = false); private: - bool utf8_input, utf8_output; + bool utf8_input_; + bool utf8_output_; + bool colorize_output_; - void SimpleLookup(const string &str, TSearchResultList& res_list); - void LookupWithFuzzy(const string &str, TSearchResultList& res_list); - void LookupWithRule(const string &str, TSearchResultList& res_lsit); - void LookupData(const string &str, TSearchResultList& res_list); + void SimpleLookup(const std::string &str, TSearchResultList& res_list); + void LookupWithFuzzy(const std::string &str, TSearchResultList& res_list); + void LookupWithRule(const std::string &str, TSearchResultList& res_lsit); + void LookupData(const std::string &str, TSearchResultList& res_list); void print_search_result(FILE *out, const TSearchResult & res); }; diff --git a/src/sdcv.cpp b/src/sdcv.cpp index d821c7b..b50673b 100644 --- a/src/sdcv.cpp +++ b/src/sdcv.cpp @@ -73,6 +73,7 @@ int main(int argc, char *argv[]) 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, @@ -91,6 +92,8 @@ int main(int argc, char *argv[]) {"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 }, }; @@ -139,7 +142,7 @@ int main(int argc, char *argv[]) disable_list, [](const std::string& filename, bool) -> void { DictInfo dict_info; if (dict_info.load_from_ifo_file(filename, false)) { - const string bookname = utf8_to_locale_ign_err(dict_info.bookname); + const std::string bookname = utf8_to_locale_ign_err(dict_info.bookname); printf("%s %d\n", bookname.c_str(), dict_info.wordcount); } }); @@ -166,12 +169,12 @@ int main(int argc, char *argv[]) }); } - const string conf_dir = string(g_get_home_dir())+G_DIR_SEPARATOR+".stardict"; - if (g_mkdir(conf_dir.c_str(), S_IRWXU)==-1 && errno!=EEXIST) + 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); + Library lib(utf8_input, utf8_output, colorize); strlist_t empty_list; lib.load(dicts_dir_list, empty_list, disable_list); @@ -182,7 +185,7 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } else if (!non_interactive) { - string phrase; + std::string phrase; while (io->read(_("Enter word or phrase: "), phrase)) { if (!lib.process_phrase(phrase.c_str(), *io)) return EXIT_FAILURE;