mirror of
https://github.com/Dushistov/sdcv.git
synced 2025-12-15 09:21:55 +00:00
support of usage colors in sdcv output
This commit is contained in:
@@ -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, "</k>"))!=nullptr)
|
||||
next+=sizeof("</k>")-1-1;
|
||||
res += colorize_output ? ESC_END : "";
|
||||
else if (name == "k") {
|
||||
const char *begin = next;
|
||||
if ((next = strstr(begin, "</k>")) != nullptr)
|
||||
next += sizeof("</k>") - 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<gchar *> 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<std::vector<gchar *> > drl(ndicts());
|
||||
if (!Libs::LookupData(str.c_str(), &drl[0]))
|
||||
return;
|
||||
for (int idict = 0; idict < ndicts(); ++idict)
|
||||
for (std::vector<gchar *>::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<string> > DictResMap;
|
||||
typedef std::map< std::string, int, std::less<std::string> > 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<IReadLine> 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);
|
||||
|
||||
|
||||
@@ -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<TSearchResult> 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);
|
||||
};
|
||||
|
||||
|
||||
13
src/sdcv.cpp
13
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;
|
||||
|
||||
Reference in New Issue
Block a user