support of usage colors in sdcv output

This commit is contained in:
Evgeniy Dushistov
2013-07-07 14:43:53 +00:00
parent 7ddc3e2ea9
commit f5c62baeb9
3 changed files with 144 additions and 107 deletions

View File

@@ -32,8 +32,22 @@
#include "libwrapper.hpp" #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; std::string res;
for (; *p; ++p) { for (; *p; ++p) {
@@ -59,40 +73,48 @@ static std::string xdxf2text(const char *p)
if (!next) if (!next)
continue; continue;
std::string name(p+1, next-p-1); const std::string name(p+1, next-p-1);
if (name == "abr") if (name == "abr")
res+=""; res += colorize_output ? ABR_VISFMT : "";
else if (name=="/abr") else if (name=="/abr")
res+=""; res += colorize_output ? ESC_END : "";
else if (name == "k") { else if (name == "k") {
const char *begin = next; const char *begin = next;
if ((next = strstr(begin, "</k>")) != nullptr) if ((next = strstr(begin, "</k>")) != nullptr)
next += sizeof("</k>") - 1 - 1; next += sizeof("</k>") - 1 - 1;
else else
next = begin; next = begin;
} else if (name == "kref") {
res += colorize_output ? KREF_VISFMT : "";
} else if (name == "/kref") {
res += colorize_output ? ESC_END : "";
} else if (name == "b") } else if (name == "b")
res+=""; res += colorize_output ? ESC_BOLD : "";
else if (name=="/b") else if (name=="/b")
res+=""; res += colorize_output ? ESC_END : "";
else if (name == "i") else if (name == "i")
res+=""; res += colorize_output ? ESC_ITALIC : "";
else if (name == "/i") else if (name == "/i")
res+=""; res += colorize_output ? ESC_END : "";
else if (name=="tr") else if (name == "tr") {
if (colorize_output)
res += TRANSCRIPTION_VISFMT;
res += "["; res += "[";
else if (name=="/tr") } else if (name == "/tr") {
res += "]"; res += "]";
else if (name=="ex") if (colorize_output)
res+=""; res += ESC_END;
} else if (name == "ex")
res += colorize_output ? EXAMPLE_VISFMT : "";
else if (name == "/ex") else if (name == "/ex")
res+=""; res += colorize_output ? ESC_END : "";
else if (!name.empty() && name[0] == 'c' && name != "co") { else if (!name.empty() && name[0] == 'c' && name != "co") {
std::string::size_type pos = name.find("code"); std::string::size_type pos = name.find("code");
if (pos!=std::string::size_type(-1)) { if (pos != std::string::npos) {
pos += sizeof("code=\"") - 1; pos += sizeof("code=\"") - 1;
std::string::size_type end_pos = name.find("\""); std::string::size_type end_pos = name.find("\"");
std::string color(name, pos, end_pos-pos); const std::string color(name, pos, end_pos - pos);
res += ""; res += "";
} else { } else {
res += ""; res += "";
@@ -105,12 +127,12 @@ static std::string xdxf2text(const char *p)
return res; return res;
} }
static string parse_data(const gchar *data) static std::string parse_data(const gchar *data, bool colorize_output)
{ {
if (!data) if (!data)
return ""; return "";
string res; std::string res;
guint32 data_size, sec_size=0; guint32 data_size, sec_size=0;
gchar *m_str; gchar *m_str;
const gchar *p=data; const gchar *p=data;
@@ -135,7 +157,7 @@ static string parse_data(const gchar *data)
if (sec_size) { if (sec_size) {
res+="\n"; res+="\n";
m_str = g_strndup(p, sec_size); m_str = g_strndup(p, sec_size);
res += xdxf2text(m_str); res += xdxf2text(m_str, colorize_output);
g_free(m_str); g_free(m_str);
} }
sec_size++; sec_size++;
@@ -144,9 +166,11 @@ static string parse_data(const gchar *data)
sec_size = strlen(p); sec_size = strlen(p);
if(sec_size){ if(sec_size){
res += "\n"; res += "\n";
m_str = g_strndup(p, sec_size); if (colorize_output)
res += "["+string(m_str)+"]"; res += TRANSCRIPTION_VISFMT;
g_free(m_str); res += "[" + std::string(p, sec_size) + "]";
if (colorize_output)
res += ESC_END;
} }
sec_size++; sec_size++;
break; break;
@@ -167,7 +191,7 @@ static string parse_data(const gchar *data)
return res; return res;
} }
void Library::SimpleLookup(const string &str, TSearchResultList& res_list) void Library::SimpleLookup(const std::string &str, TSearchResultList& res_list)
{ {
glong ind; glong ind;
res_list.reserve(ndicts()); res_list.reserve(ndicts());
@@ -176,11 +200,11 @@ void Library::SimpleLookup(const string &str, TSearchResultList& res_list)
res_list.push_back( res_list.push_back(
TSearchResult(dict_name(idict), TSearchResult(dict_name(idict),
poGetWord(ind, idict), poGetWord(ind, idict),
parse_data(poGetWordData(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; 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<gchar *> match_res((MAX_MATCH_ITEM_PER_LIB) * ndicts()); std::vector<gchar *> match_res((MAX_MATCH_ITEM_PER_LIB) * ndicts());
@@ -209,32 +233,39 @@ 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<std::vector<gchar *> > drl(ndicts()); std::vector<std::vector<gchar *> > drl(ndicts());
if (!Libs::LookupData(str.c_str(), &drl[0])) if (!Libs::LookupData(str.c_str(), &drl[0]))
return; return;
for (int idict = 0; idict < ndicts(); ++idict) for (int idict = 0; idict < ndicts(); ++idict)
for (std::vector<gchar *>::size_type j=0; j < drl[idict].size(); ++j) { for (gchar *res : drl[idict]) {
SimpleLookup(drl[idict][j], res_list); SimpleLookup(res, res_list);
g_free(drl[idict][j]); g_free(res);
} }
} }
void Library::print_search_result(FILE *out, const TSearchResult & res) void Library::print_search_result(FILE *out, const TSearchResult & res)
{ {
std::string loc_bookname, loc_def, loc_exp; std::string loc_bookname, loc_def, loc_exp;
if(!utf8_output){
if (!utf8_output_){
loc_bookname = utf8_to_locale_ign_err(res.bookname); loc_bookname = utf8_to_locale_ign_err(res.bookname);
loc_def = utf8_to_locale_ign_err(res.def); loc_def = utf8_to_locale_ign_err(res.def);
loc_exp = utf8_to_locale_ign_err(res.exp); loc_exp = utf8_to_locale_ign_err(res.exp);
} }
fprintf(out,
fprintf(out, "-->%s\n-->%s\n%s\n\n", "-->%s%s%s\n"
utf8_output ? res.bookname.c_str() : loc_bookname.c_str(), "-->%s%s%s\n"
utf8_output ? res.def.c_str() : loc_def.c_str(), "%s\n\n",
utf8_output ? res.exp.c_str() : loc_exp.c_str()); 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 { namespace {
@@ -277,7 +308,7 @@ bool Library::process_phrase(const char *loc_str, IReadLine &io, bool force)
gsize bytes_written; gsize bytes_written;
GError *err = nullptr; GError *err = nullptr;
char *str = nullptr; char *str = nullptr;
if (!utf8_input) if (!utf8_input_)
str = g_locale_to_utf8(loc_str, -1, &bytes_read, &bytes_written, &err); str = g_locale_to_utf8(loc_str, -1, &bytes_read, &bytes_written, &err);
else else
str = g_strdup(loc_str); str = g_strdup(loc_str);
@@ -318,7 +349,7 @@ bool Library::process_phrase(const char *loc_str, IReadLine &io, bool force)
one or zero results per dictionary show all one or zero results per dictionary show all
*/ */
bool show_all_results = true; bool show_all_results = true;
typedef std::map< string, int, std::less<string> > DictResMap; typedef std::map< std::string, int, std::less<std::string> > DictResMap;
if (!force) { if (!force) {
DictResMap res_per_dict; DictResMap res_per_dict;
for (const TSearchResult& search_res : res_list) { 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) { if (!show_all_results && !force) {
printf(_("Found %zu items, similar to %s.\n"), res_list.size(), 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) { 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_bookname = utf8_to_locale_ign_err(res_list[i].bookname);
const std::string loc_def = utf8_to_locale_ign_err(res_list[i].def); const std::string loc_def = utf8_to_locale_ign_err(res_list[i].def);
printf("%zu)%s-->%s\n", i, printf("%zu)%s%s%s-->%s%s%s\n", i,
utf8_output ? res_list[i].bookname.c_str() : loc_bookname.c_str(), colorize_output_ ? NAME_OF_DICT_VISFMT : "",
utf8_output ? res_list[i].def.c_str() : loc_def.c_str()); 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; int choise;
std::unique_ptr<IReadLine> choice_readline(create_readline_object()); std::unique_ptr<IReadLine> choice_readline(create_readline_object());
@@ -365,17 +400,17 @@ bool Library::process_phrase(const char *loc_str, IReadLine &io, bool force)
} else { } else {
sdcv_pager pager(force); sdcv_pager pager(force);
fprintf(pager.get_stream(), _("Found %zu items, similar to %s.\n"), 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) for (const TSearchResult& search_res : res_list)
print_search_result(pager.get_stream(), search_res); print_search_result(pager.get_stream(), search_res);
} }
} else { } else {
std::string loc_str; std::string loc_str;
if (!utf8_output) if (!utf8_output_)
loc_str = utf8_to_locale_ign_err(str); 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); g_free(str);

View File

@@ -7,17 +7,14 @@
#include "lib.hpp" #include "lib.hpp"
#include "readline.hpp" #include "readline.hpp"
using std::string;
using std::vector;
//this structure is wrapper and it need for unification //this structure is wrapper and it need for unification
//results of search whith return Dicts class //results of search whith return Dicts class
struct TSearchResult { struct TSearchResult {
string bookname; std::string bookname;
string def; std::string def;
string exp; 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_) : bookname(bookname_), def(def_), exp(exp_)
{ {
} }
@@ -29,17 +26,19 @@ typedef std::vector<TSearchResult> TSearchResultList;
//of it //of it
class Library : public Libs { class Library : public Libs {
public: public:
Library(bool uinput, bool uoutput) : Library(bool uinput, bool uoutput, bool colorize_output):
utf8_input(uinput), utf8_output(uoutput) {} 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: private:
bool utf8_input, utf8_output; bool utf8_input_;
bool utf8_output_;
bool colorize_output_;
void SimpleLookup(const string &str, TSearchResultList& res_list); void SimpleLookup(const std::string &str, TSearchResultList& res_list);
void LookupWithFuzzy(const string &str, TSearchResultList& res_list); void LookupWithFuzzy(const std::string &str, TSearchResultList& res_list);
void LookupWithRule(const string &str, TSearchResultList& res_lsit); void LookupWithRule(const std::string &str, TSearchResultList& res_lsit);
void LookupData(const string &str, TSearchResultList& res_list); void LookupData(const std::string &str, TSearchResultList& res_list);
void print_search_result(FILE *out, const TSearchResult & res); void print_search_result(FILE *out, const TSearchResult & res);
}; };

View File

@@ -73,6 +73,7 @@ int main(int argc, char *argv[])
gboolean utf8_output = FALSE; gboolean utf8_output = FALSE;
gboolean utf8_input = FALSE; gboolean utf8_input = FALSE;
glib::CharStr opt_data_dir; glib::CharStr opt_data_dir;
gboolean colorize = FALSE;
const GOptionEntry entries[] = { const GOptionEntry entries[] = {
{"version", 'v', 0, G_OPTION_ARG_NONE, &show_version, {"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), {"data-dir", '2', 0, G_OPTION_ARG_STRING, get_addr(opt_data_dir),
_("use this directory as path to stardict data directory"), _("use this directory as path to stardict data directory"),
_("path/to/dir")}, _("path/to/dir")},
{"color", 'c', 0, G_OPTION_ARG_NONE, &colorize,
_("colorize the output"), nullptr },
{ nullptr }, { nullptr },
}; };
@@ -139,7 +142,7 @@ int main(int argc, char *argv[])
disable_list, [](const std::string& filename, bool) -> void { disable_list, [](const std::string& filename, bool) -> void {
DictInfo dict_info; DictInfo dict_info;
if (dict_info.load_from_ifo_file(filename, false)) { 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); 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"; 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) if (g_mkdir(conf_dir.c_str(), S_IRWXU) == -1 && errno!=EEXIST)
fprintf(stderr, _("g_mkdir failed: %s\n"), strerror(errno)); 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; strlist_t empty_list;
lib.load(dicts_dir_list, empty_list, disable_list); lib.load(dicts_dir_list, empty_list, disable_list);
@@ -182,7 +185,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE; return EXIT_FAILURE;
} else if (!non_interactive) { } else if (!non_interactive) {
string phrase; std::string phrase;
while (io->read(_("Enter word or phrase: "), phrase)) { while (io->read(_("Enter word or phrase: "), phrase)) {
if (!lib.process_phrase(phrase.c_str(), *io)) if (!lib.process_phrase(phrase.c_str(), *io))
return EXIT_FAILURE; return EXIT_FAILURE;