diff --git a/src/icons.h b/src/icons.h index 69872be4..97a624d9 100644 --- a/src/icons.h +++ b/src/icons.h @@ -3,7 +3,11 @@ struct icon_pair { const char *match; const char *icon; - const unsigned char color; /* Hex xterm 256 color code, 0 to follow file specific */ + /* + * Hex xterm 256 color code, 0 to follow file specific (if any) + * Codes: https://jonasjacek.github.io/colors/ + */ + const unsigned char color; }; /* @@ -14,14 +18,21 @@ struct icon_pair { #define ICON_PADDING_LEFT "" #define ICON_PADDING_RIGHT " " +#define VIDEO_COLOR 93 /* Purple */ +#define AUDIO_COLOR 220 /* Gold1 */ +#define IMAGE_COLOR 82 /* Chartreuse2 */ +#define BOOKS_COLOR 202 /* OrangeRed1 */ +#define ARCHIVE_COLOR 209 /* Salmon1 */ + /* * Using symbols defined in icons-in-terminal.h, or even using icons-in-terminal is not necessary. * You can use whatever pathched font you like. You just have to put the desired icon as a string. * If you are using icons-in-terminal the creator recommends that you do use the symbols in the generated header. */ -static const struct icon_pair dir_icon = {"", FA_FOLDER, 0}; -static const struct icon_pair file_icon = {"", FA_FILE, 0}; +static const struct icon_pair dir_icon = {"", FA_FOLDER, 0}; +static const struct icon_pair file_icon = {"", FA_FILE_O, 0}; +static const struct icon_pair exec_icon = {"", FA_TERMINAL, 0}; /* All entries are case-insensitive */ @@ -46,26 +57,26 @@ static const struct icon_pair icons_name[] = { static const struct icon_pair icons_ext[] = { /* Numbers */ - {"7z", FA_FILE_ARCHIVE_O, 0}, + {"7z", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, /* A */ {"a", FILE_MANPAGE, 0}, - {"apk", FA_FILE_ARCHIVE_O, 0}, + {"apk", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, {"asm", FILE_NASM, 0}, - {"aup", FA_FILE_AUDIO_O, 0}, - {"avi", FA_FILE_MOVIE_O, 0}, + {"aup", FA_FILE_AUDIO_O, AUDIO_COLOR}, + {"avi", FA_FILE_MOVIE_O, VIDEO_COLOR}, /* B */ {"bat", MFIZZ_SCRIPT, 0}, - {"bmp", FA_FILE_IMAGE_O, 0}, - {"bz2", FA_FILE_ARCHIVE_O, 0}, + {"bmp", FA_FILE_IMAGE_O, IMAGE_COLOR}, + {"bz2", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, /* C */ {"c", MFIZZ_C, 0}, {"c++", MFIZZ_CPLUSPLUS, 0}, - {"cab", FA_FILE_ARCHIVE_O, 0}, - {"cbr", FA_FILE_ARCHIVE_O, 0}, - {"cbz", FA_FILE_ARCHIVE_O, 0}, + {"cab", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, + {"cbr", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, + {"cbz", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, {"cc", MFIZZ_CPLUSPLUS, 0}, {"class", MFIZZ_JAVA, 0}, {"clj", MFIZZ_CLOJURE, 0}, @@ -74,16 +85,16 @@ static const struct icon_pair icons_ext[] = { {"cmake", FILE_CMAKE, 0}, {"coffee", MFIZZ_COFFEE_BEAN, 0}, {"conf", FA_COGS, 0}, - {"cpio", FA_FILE_ARCHIVE_O, 0}, + {"cpio", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, {"cpp", MFIZZ_CPLUSPLUS, 0}, {"css", MFIZZ_CSS3, 0}, - {"cue", FA_FILE_AUDIO_O, 0}, + {"cue", FA_FILE_AUDIO_O, AUDIO_COLOR}, {"cvs", FA_COGS, 0}, {"cxx", MFIZZ_CPLUSPLUS, 0}, /* D */ {"db", MFIZZ_DATABASE_ALT2, 0}, - {"deb", MFIZZ_DEBIAN, 0}, + {"deb", MFIZZ_DEBIAN, ARCHIVE_COLOR}, {"dll", FILE_MANPAGE, 0}, {"doc", FILE_WORD, 0}, {"docx", FILE_WORD, 0}, @@ -91,13 +102,13 @@ static const struct icon_pair icons_ext[] = { /* E */ {"ejs", FA_FILE_CODE_O, 0}, {"elf", FA_LINUX, 0}, - {"epub", FA_FILE_PDF_O, 0}, + {"epub", FA_FILE_PDF_O, BOOKS_COLOR}, {"exe", FA_WINDOWS, 0}, /* F */ {"f#", DEV_FSHARP, 0}, - {"flac", FA_FILE_AUDIO_O, 0}, - {"flv", FA_FILE_MOVIE_O, 0}, + {"flac", FA_FILE_AUDIO_O, AUDIO_COLOR}, + {"flv", FA_FILE_MOVIE_O, VIDEO_COLOR}, {"fs", DEV_FSHARP, 0}, {"fsi", DEV_FSHARP, 0}, {"fsscript", DEV_FSHARP, 0}, @@ -105,10 +116,10 @@ static const struct icon_pair icons_ext[] = { /* G */ {"gem", FA_FILE_ARCHIVE_O, 0}, - {"gif", FA_FILE_IMAGE_O, 0}, + {"gif", FA_FILE_IMAGE_O, IMAGE_COLOR}, {"go", MFIZZ_GO, 0}, - {"gz", FA_FILE_ARCHIVE_O, 0}, - {"gzip", FA_FILE_ARCHIVE_O, 0}, + {"gz", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, + {"gzip", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, /* H */ {"h", MFIZZ_C, 0}, @@ -120,17 +131,17 @@ static const struct icon_pair icons_ext[] = { {"hxx", MFIZZ_CPLUSPLUS, 0}, /* I */ - {"ico", FA_FILE_IMAGE_O, 0}, - {"img", FA_FILE_IMAGE_O, 0}, + {"ico", FA_FILE_IMAGE_O, IMAGE_COLOR}, + {"img", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, {"ini", FA_COGS, 0}, - {"iso", LINEA_MUSIC_CD, 0}, + {"iso", LINEA_MUSIC_CD, ARCHIVE_COLOR}, /* J */ {"jar", MFIZZ_JAVA, 0}, {"java", MFIZZ_JAVA, 0}, {"jl", FA_COGS, 0}, - {"jpeg", FA_FILE_IMAGE_O, 0}, - {"jpg", FA_FILE_IMAGE_O, 0}, + {"jpeg", FA_FILE_IMAGE_O, IMAGE_COLOR}, + {"jpg", FA_FILE_IMAGE_O, IMAGE_COLOR}, {"js", DEV_JAVASCRIPT_BADGE, 0}, {"json", MFIZZ_JAVASCRIPT, 0}, {"jsx", FILE_JSX, 0}, @@ -138,36 +149,36 @@ static const struct icon_pair icons_ext[] = { /* K */ /* L */ - {"lha", FA_FILE_ARCHIVE_O, 0}, + {"lha", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, {"log", FA_FILE_TEXT_O, 0}, {"lua", FILE_LUA, 0}, - {"lzh", FA_FILE_ARCHIVE_O, 0}, - {"lzma", FA_FILE_ARCHIVE_O, 0}, + {"lzh", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, + {"lzma", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, /* M */ - {"m4a", FA_FILE_AUDIO_O, 0}, - {"m4v", FA_FILE_MOVIE_O, 0}, + {"m4a", FA_FILE_AUDIO_O, AUDIO_COLOR}, + {"m4v", FA_FILE_MOVIE_O, VIDEO_COLOR}, {"markdown", OCT_MARKDOWN, 0}, {"md", OCT_MARKDOWN, 0}, - {"mkv", FA_FILE_MOVIE_O, 0}, - {"mov", FA_FILE_MOVIE_O, 0}, - {"mp3", FA_FILE_AUDIO_O, 0}, - {"mp4", FA_FILE_MOVIE_O, 0}, - {"mpeg", FA_FILE_MOVIE_O, 0}, - {"mpg", FA_FILE_MOVIE_O, 0}, + {"mkv", FA_FILE_MOVIE_O, VIDEO_COLOR}, + {"mov", FA_FILE_MOVIE_O, VIDEO_COLOR}, + {"mp3", FA_FILE_AUDIO_O, AUDIO_COLOR}, + {"mp4", FA_FILE_MOVIE_O, VIDEO_COLOR}, + {"mpeg", FA_FILE_MOVIE_O, VIDEO_COLOR}, + {"mpg", FA_FILE_MOVIE_O, VIDEO_COLOR}, {"msi", FA_WINDOWS, 0}, /* N */ /* O */ {"o", FILE_MANPAGE, 0}, - {"ogg", FA_FILE_AUDIO_O, 0}, + {"ogg", FA_FILE_AUDIO_O, AUDIO_COLOR}, {"out", FA_LINUX, 0}, /* P */ - {"pdf", FA_FILE_PDF_O, 0}, + {"pdf", FA_FILE_PDF_O, BOOKS_COLOR}, {"php", MFIZZ_PHP, 0}, - {"png", FA_FILE_IMAGE_O, 0}, + {"png", FA_FILE_IMAGE_O, IMAGE_COLOR}, {"ppt", FILE_POWERPOINT, 0}, {"pptx", FILE_POWERPOINT, 0}, {"psb", DEV_PHOTOSHOP, 0}, @@ -180,10 +191,10 @@ static const struct icon_pair icons_ext[] = { /* Q */ /* R */ - {"rar", FA_FILE_ARCHIVE_O, 0}, + {"rar", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, {"rc", FA_COGS, 0}, {"rom", FA_LOCK, 0}, - {"rpm", FA_FILE_ARCHIVE_O, 0}, + {"rpm", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, {"rss", FA_RSS_SQUARE, 0}, {"rtf", FA_FILE_PDF_O, 0}, @@ -194,15 +205,16 @@ static const struct icon_pair icons_ext[] = { {"slim", FA_FILE_CODE_O, 0}, {"sln", DEV_VISUALSTUDIO, 0}, {"sql", MFIZZ_MYSQL, 0}, - {"svg", FA_FILE_IMAGE_O, 0}, + {"svg", FA_FILE_IMAGE_O, IMAGE_COLOR}, /* T */ - {"tar", FA_FILE_ARCHIVE_O, 0}, + {"tar", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, {"tex", FILE_TEX, 0}, - {"tgz", FA_FILE_ARCHIVE_O, 0}, + {"tgz", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, {"ts", FILE_TS, 0}, {"tsx", FILE_TSX, 0}, {"txt", FA_FILE_TEXT_O, 0}, + {"txz", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, /* U */ @@ -211,23 +223,25 @@ static const struct icon_pair icons_ext[] = { {"vimrc", DEV_VIM, 0}, /* W */ - {"wav", FA_FILE_AUDIO_O, 0}, - {"webm", FA_FILE_MOVIE_O, 0}, + {"wav", FA_FILE_AUDIO_O, AUDIO_COLOR}, + {"webm", FA_FILE_MOVIE_O, VIDEO_COLOR}, + {"wma", FA_FILE_AUDIO_O, AUDIO_COLOR}, + {"wmv", FA_FILE_MOVIE_O, VIDEO_COLOR}, /* X */ - {"xbps", FA_FILE_ARCHIVE_O, 0}, + {"xbps", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, {"xhtml", FA_FILE_CODE_O, 0}, {"xls", FILE_EXCEL, 0}, {"xlsx", FILE_EXCEL, 0}, {"xml", FA_FILE_CODE_O, 0}, - {"xz", FA_FILE_ARCHIVE_O, 0}, + {"xz", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR}, /* Y */ {"yaml", FA_COGS, 0}, {"yml", FA_COGS, 0}, /* Z */ - {"zip", FA_FILE_ARCHIVE_O, 0} + {"zip", FA_FILE_ARCHIVE_O, ARCHIVE_COLOR} /* Other */ }; diff --git a/src/nnn.c b/src/nnn.c index a001d136..f9f56f64 100644 --- a/src/nnn.c +++ b/src/nnn.c @@ -1677,6 +1677,9 @@ static bool initcurses(void *oldmask) } else g_state.oldcolor = 1; + DPRINTF_D(COLORS); + DPRINTF_D(COLOR_PAIRS); + if (colors && *colors == '#') { char *sep = strchr(colors, ';'); @@ -1724,12 +1727,20 @@ static bool initcurses(void *oldmask) #ifdef ICONS if (!g_state.oldcolor) { + uchar icolors[256] = {0}; + char c; + bool found = TRUE; + memset(icon_positions, 0x7f, sizeof(icon_positions)); - if (icons_ext[0].match[0] >= '0' && icons_ext[0].match[0] <= '9') + if (icons_ext[0].match[0] >= '0' && icons_ext[0].match[0] <= '9') { icon_positions[0] = 0; + if (icons_ext[0].color && !icolors[icons_ext[0].color]) { + init_pair(C_UND + 1 + icons_ext[0].color, icons_ext[0].color, -1); + icolors[icons_ext[0].color] = 1; + } + } - char c; for (uint i = 0; i < sizeof(icons_ext)/sizeof(struct icon_pair); ++i) { c = TOUPPER(icons_ext[i].match[0]); if (c >= 'A' && c <= 'Z') { @@ -1738,7 +1749,16 @@ static bool initcurses(void *oldmask) } else if (!(c >= '0' && c <= '9')) { if (icon_positions[27] == 0x7f7f) icon_positions[27] = i; - } + } else + found = FALSE; + + if (found) { + if (icons_ext[i].color && !icolors[icons_ext[i].color]) { + init_pair(C_UND + 1 + icons_ext[i].color, icons_ext[i].color, -1); + icolors[icons_ext[i].color] = 1; + } + } else + found = TRUE; } } #endif @@ -3456,20 +3476,24 @@ static char *get_lsperms(mode_t mode) } #ifdef ICONS -static const char *get_icon(const struct entry *ent){ +static const struct icon_pair * get_icon(const struct entry *ent){ ushort i, j; char *tmp; for (i = 0; i < sizeof(icons_name)/sizeof(struct icon_pair); ++i) if (strcasecmp(ent->name, icons_name[i].match) == 0) - return icons_name[i].icon; + return &icons_name[i]; if (ent->flags & DIR_OR_LINK_TO_DIR) - return dir_icon.icon; + return &dir_icon; tmp = xextension(ent->name, ent->nlen); - if (!tmp) - return file_icon.icon; + if (!tmp) { + if (ent->mode & 0100) + return &exec_icon; + + return &file_icon; + } /* Skip the . */ ++tmp; @@ -3484,9 +3508,30 @@ static const char *get_icon(const struct entry *ent){ for (j = icon_positions[i]; j < sizeof(icons_ext)/sizeof(struct icon_pair) && icons_ext[j].match[0] == icons_ext[icon_positions[i]].match[0]; ++j) if (strcasecmp(tmp, icons_ext[j].match) == 0) - return icons_ext[j].icon; + return &icons_ext[j]; - return file_icon.icon; + /* If there's no match and the file is executable, icon that */ + if (ent->mode & 0100) + return &exec_icon; + + return &file_icon; +} + +static void print_icon(const struct entry *ent, const int attrs) +{ + const struct icon_pair *picon = get_icon(ent); + + addstr(ICON_PADDING_LEFT); + if (picon->color) + attron(COLOR_PAIR(C_UND + 1 + picon->color)); + else if (attrs) + attron(attrs); + addstr(picon->icon); + if (picon->color) + attroff(COLOR_PAIR(C_UND + 1 + picon->color)); + else if (attrs) + attroff(attrs); + addstr(ICON_PADDING_RIGHT); } #endif @@ -3502,7 +3547,7 @@ static void printent(const struct entry *ent, uint namecols, bool sel) { uchar pair = 0; char ind = '\0'; - int attrs = sel ? A_REVERSE : 0; + int attrs = 0; switch (ent->mode & S_IFMT) { case S_IFREG: @@ -3573,17 +3618,16 @@ static void printent(const struct entry *ent, uint namecols, bool sel) addch((ent->flags & FILE_SELECTED) ? '+' : ' '); +#ifdef ICONS + if (!g_state.oldcolor) + print_icon(ent, attrs); +#endif + + if (sel) + attrs |= A_REVERSE; if (attrs) attron(attrs); -#ifdef ICONS - if (!g_state.oldcolor) { - addstr(ICON_PADDING_LEFT); - addstr(get_icon(ent)); - addstr(ICON_PADDING_RIGHT); - } -#endif - #ifndef NOLOCALE addwstr(unescape(ent->name, namecols)); #else @@ -3696,14 +3740,16 @@ static void printent_long(const struct entry *ent, uint namecols, bool sel) break; } - addstr(" "); - if (g_state.oldcolor) { + addstr(" "); if (!ln) { attroff(A_DIM); attrs ^= A_DIM; } } else { +#ifndef ICONS + addstr(" "); +#endif if (ent->flags & FILE_MISSING) pair = C_MIS; else { @@ -3711,19 +3757,19 @@ static void printent_long(const struct entry *ent, uint namecols, bool sel) attrs ^= (COLOR_PAIR(C_MIS)); } - if (pair && fcolors[pair]) { + if (pair && fcolors[pair]) attrs |= COLOR_PAIR(pair); - attron(attrs); - } - } - #ifdef ICONS - if (!g_state.oldcolor) { - addstr(ICON_PADDING_LEFT); - addstr(get_icon(ent)); - addstr(ICON_PADDING_RIGHT); - } + attroff(attrs); + addstr(" "); + if (sel) + attrs &= ~A_REVERSE; + print_icon(ent, attrs); + if (sel) + attrs |= A_REVERSE; #endif + attron(attrs); + } #ifndef NOLOCALE addwstr(unescape(ent->name, namecols));