]> Sergey Matveev's repositories - nnn.git/commitdiff
Support icon-specific colors
authorArun Prakash Jana <engineerarun@gmail.com>
Sun, 16 Aug 2020 08:19:09 +0000 (13:49 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Sun, 16 Aug 2020 08:19:09 +0000 (13:49 +0530)
src/icons.h
src/nnn.c

index 69872be48ea9ab6d63ed9bb974555e3bdcf0bdb3..97a624d94abf3caf52dc54545e58e94d4d66cce5 100644 (file)
@@ -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 */
 };
index a001d136745fde6ce6d87a49ca423bdfc9e75e24..f9f56f647a7afdd41f1ef2a169cb4f64a026ee71 100644 (file)
--- 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];
+
+       /* 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);
 
-       return file_icon.icon;
+       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) ? '+' : ' ');
 
-       if (attrs)
-               attron(attrs);
-
 #ifdef ICONS
-       if (!g_state.oldcolor) {
-               addstr(ICON_PADDING_LEFT);
-               addstr(get_icon(ent));
-               addstr(ICON_PADDING_RIGHT);
-       }
+       if (!g_state.oldcolor)
+               print_icon(ent, attrs);
 #endif
 
+       if (sel)
+               attrs |= A_REVERSE;
+       if (attrs)
+               attron(attrs);
+
 #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));