Support file colors

This commit is contained in:
Arun Prakash Jana 2020-08-04 19:22:29 +05:30
parent ccfccb7187
commit ae961da157
No known key found for this signature in database
GPG key ID: A75979F35C080412
2 changed files with 127 additions and 13 deletions

View file

@ -61,6 +61,10 @@ ifeq ($(O_NOFIFO),1)
CPPFLAGS += -DNOFIFO CPPFLAGS += -DNOFIFO
endif endif
ifeq ($(O_NOFCOLORS),1)
CPPFLAGS += -DNOFCOLORS
endif
ifeq ($(O_CTX8),1) ifeq ($(O_CTX8),1)
CPPFLAGS += -DCTX8 CPPFLAGS += -DCTX8
endif endif

136
src/nnn.c
View file

@ -668,6 +668,25 @@ static const char * const patterns[] = {
"sed -i 's|^%s\\(.*\\)$|%s\\1|' %s", "sed -i 's|^%s\\(.*\\)$|%s\\1|' %s",
}; };
/* Colors */
#define C_BLK (CTX_MAX + 1) /* Block device: DarkSeaGreen1 */
#define C_CHR (C_BLK + 1) /* Character device: Yellow1 */
#define C_DIR (C_CHR + 1) /* Directory: DeepSkyBlue1 */
#define C_EXE (C_DIR + 1) /* Executable file: Green1 */
#define C_FIL (C_EXE + 1) /* Regular file: Normal */
#define C_HRD (C_FIL + 1) /* Hard link: Plum4 */
#define C_LNK (C_HRD + 1) /* Symbolic link: Cyan1 */
#define C_MIS (C_LNK + 1) /* Missing file: Grey70 */
#define C_ORP (C_MIS + 1) /* Orphaned symlink: DeepPink1 */
#define C_PIP (C_ORP + 1) /* Named pipe (FIFO): Orange1 */
#define C_SOC (C_PIP + 1) /* Socket: MediumOrchid1 */
#define C_UND (C_SOC + 1) /* Unknown OR 0B regular/exe file: Red1 */
#ifndef NOFCOLORS
static char gcolors[] = "c1e2272e006033f9c6d6abc4";
static uint fcolors[C_UND + 1] = {0};
#endif
/* Event handling */ /* Event handling */
#ifdef LINUX_INOTIFY #ifdef LINUX_INOTIFY
#define NUM_EVENT_SLOTS 32 /* Make room for 8 events */ #define NUM_EVENT_SLOTS 32 /* Make room for 8 events */
@ -1550,6 +1569,28 @@ static void export_file_list(void)
unlink(g_tmpfpath); unlink(g_tmpfpath);
} }
#ifndef NOFCOLORS
static bool init_fcolors(void)
{
char *f_colors = getenv("NNN_FCOLORS");
if (f_colors) {
for (uchar id = C_BLK; *f_colors && id <= C_UND; ++id) {
fcolors[id] = xchartohex(*f_colors) << 4;
if (*++f_colors) {
fcolors[id] += xchartohex(*f_colors);
if (fcolors[id])
init_pair(id, fcolors[id], -1);
} else
return FALSE;
++f_colors;
}
}
return TRUE;
}
#endif
/* Initialize curses mode */ /* Initialize curses mode */
static bool initcurses(void *oldmask) static bool initcurses(void *oldmask)
{ {
@ -1608,6 +1649,14 @@ static bool initcurses(void *oldmask)
*/ */
if (sep) if (sep)
*sep = '\0'; *sep = '\0';
#ifndef NOFCOLORS
if (!init_fcolors()) {
exitcurses();
fprintf(stderr, "NNN_FCOLORS!\n");
return FALSE;
}
#endif
} else { } else {
colors = sep; /* Detect if 8 colors fallback is appended */ colors = sep; /* Detect if 8 colors fallback is appended */
if (colors) if (colors)
@ -3171,6 +3220,7 @@ static char *get_kv_val(kv *kvarr, char *buf, int key, uchar max, uchar id)
return NULL; return NULL;
} }
#ifdef NOFCOLORS
static void resetdircolor(int flags) static void resetdircolor(int flags)
{ {
if (g_state.dircolor && !(flags & DIR_OR_LINK_TO_DIR)) { if (g_state.dircolor && !(flags & DIR_OR_LINK_TO_DIR)) {
@ -3178,6 +3228,7 @@ static void resetdircolor(int flags)
g_state.dircolor = 0; g_state.dircolor = 0;
} }
} }
#endif
/* /*
* Replace escape characters in a string with '?' * Replace escape characters in a string with '?'
@ -3313,28 +3364,47 @@ static char *coolsize(off_t size)
return size_buf; return size_buf;
} }
static char get_ind(mode_t mode, bool perms) static char get_ind(mode_t mode, bool perms, uchar *pair)
{ {
switch (mode & S_IFMT) { switch (mode & S_IFMT) {
case S_IFREG: case S_IFREG:
if (perms) if (perms)
return '-'; return '-';
if (mode & 0100) if (mode & 0100) {
*pair = C_EXE;
return '*'; return '*';
}
*pair = C_FIL;
return '\0'; return '\0';
case S_IFDIR: case S_IFDIR:
return perms ? 'd' : '/'; if (perms)
return 'd';
*pair = C_DIR;
return '/';
case S_IFLNK: case S_IFLNK:
return perms ? 'l' : '@'; return perms ? 'l' : '@';
case S_IFSOCK: case S_IFSOCK:
return perms ? 's' : '='; if (perms)
return 's';
*pair = C_SOC;
return '=';
case S_IFIFO: case S_IFIFO:
return perms ? 'p' : '|'; if (perms)
return 'p';
*pair = C_PIP;
return '|';
case S_IFBLK: case S_IFBLK:
return perms ? 'b' : '\0'; if (perms)
return 'b';
*pair = C_BLK;
return '\0';
case S_IFCHR: case S_IFCHR:
return perms ? 'c' : '\0'; if (perms)
return 'c';
*pair = C_CHR;
return '\0';
default: default:
*pair = C_UND;
return '?'; return '?';
} }
} }
@ -3345,7 +3415,7 @@ static char *get_lsperms(mode_t mode)
static const char * const rwx[] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"}; static const char * const rwx[] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"};
static char bits[11] = {'\0'}; static char bits[11] = {'\0'};
bits[0] = get_ind(mode, TRUE); bits[0] = get_ind(mode, TRUE, NULL);
xstrsncpy(&bits[1], rwx[(mode >> 6) & 7], 4); xstrsncpy(&bits[1], rwx[(mode >> 6) & 7], 4);
xstrsncpy(&bits[4], rwx[(mode >> 3) & 7], 4); xstrsncpy(&bits[4], rwx[(mode >> 3) & 7], 4);
@ -3371,26 +3441,53 @@ static void print_time(const time_t *timep)
static void printent(const struct entry *ent, uint namecols, bool sel) static void printent(const struct entry *ent, uint namecols, bool sel)
{ {
char ind = get_ind(ent->mode, FALSE); uchar pair = 0;
char ind = get_ind(ent->mode, FALSE, &pair);
#ifdef NOFCOLORS
int attrs = ((ind == '@' || (ent->flags & HARD_LINK)) ? A_DIM : 0) | (sel ? A_REVERSE : 0); int attrs = ((ind == '@' || (ent->flags & HARD_LINK)) ? A_DIM : 0) | (sel ? A_REVERSE : 0);
if (ind == '@' && (ent->flags & DIR_OR_LINK_TO_DIR)) #else
ind = '/'; int attrs = sel ? A_REVERSE : 0;
#endif
if (ind == '@') {
pair = (ent->flags & SYM_ORPHAN) ? C_ORP : C_LNK;
if (ent->flags & DIR_OR_LINK_TO_DIR)
ind = '/';
} else if (!ent->size && (pair == C_FIL || pair == C_EXE))
pair = C_UND;
else if (ent->flags & HARD_LINK)
pair = C_HRD;
else if (ent->flags & FILE_MISSING)
pair = C_MIS;
if (!ind) if (!ind)
++namecols; ++namecols;
#ifdef NOFCOLORS
/* Directories are always shown on top */ /* Directories are always shown on top */
resetdircolor(ent->flags); resetdircolor(ent->flags);
#endif
addch((ent->flags & FILE_SELECTED) ? '+' : ' '); addch((ent->flags & FILE_SELECTED) ? '+' : ' ');
#ifndef NOFCOLORS
if (pair && fcolors[pair])
attrs |= COLOR_PAIR(pair);
#endif
if (attrs) if (attrs)
attron(attrs); attron(attrs);
#ifndef NOLOCALE #ifndef NOLOCALE
addwstr(unescape(ent->name, namecols)); addwstr(unescape(ent->name, namecols));
#else #else
addstr(unescape(ent->name, MIN(namecols, ent->nlen) + 1)); addstr(unescape(ent->name, MIN(namecols, ent->nlen) + 1));
#endif #endif
#ifndef NOFCOLORS
if (pair && fcolors[pair])
attrs |= COLOR_PAIR(pair);
#endif
if (attrs) if (attrs)
attroff(attrs); attroff(attrs);
@ -3407,8 +3504,10 @@ static void printent_long(const struct entry *ent, uint namecols, bool sel)
uint len; uint len;
char *size; char *size;
#ifdef NOFCOLORS
/* Directories are always shown on top */ /* Directories are always shown on top */
resetdircolor(ent->flags); resetdircolor(ent->flags);
#endif
addch((ent->flags & FILE_SELECTED) ? '+' : ' '); addch((ent->flags & FILE_SELECTED) ? '+' : ' ');
@ -5273,17 +5372,21 @@ static int adjust_cols(int ncols)
static void draw_line(char *path, int ncols) static void draw_line(char *path, int ncols)
{ {
bool dir = FALSE;
ncols = adjust_cols(ncols); ncols = adjust_cols(ncols);
#ifdef NOFCOLORS
bool dir = FALSE;
if (pdents[last].flags & DIR_OR_LINK_TO_DIR) { if (pdents[last].flags & DIR_OR_LINK_TO_DIR) {
attron(COLOR_PAIR(cfg.curctx + 1) | A_BOLD); attron(COLOR_PAIR(cfg.curctx + 1) | A_BOLD);
dir = TRUE; dir = TRUE;
} }
#endif
move(2 + last - curscroll, 0); move(2 + last - curscroll, 0);
printptr(&pdents[last], ncols, false); printptr(&pdents[last], ncols, false);
#ifdef NOFCOLORS
if (pdents[cur].flags & DIR_OR_LINK_TO_DIR) { if (pdents[cur].flags & DIR_OR_LINK_TO_DIR) {
if (!dir) {/* First file is not a directory */ if (!dir) {/* First file is not a directory */
attron(COLOR_PAIR(cfg.curctx + 1) | A_BOLD); attron(COLOR_PAIR(cfg.curctx + 1) | A_BOLD);
@ -5293,13 +5396,16 @@ static void draw_line(char *path, int ncols)
attroff(COLOR_PAIR(cfg.curctx + 1) | A_BOLD); attroff(COLOR_PAIR(cfg.curctx + 1) | A_BOLD);
dir = FALSE; dir = FALSE;
} }
#endif
move(2 + cur - curscroll, 0); move(2 + cur - curscroll, 0);
printptr(&pdents[cur], ncols, true); printptr(&pdents[cur], ncols, true);
#ifdef NOFCOLORS
/* Must reset e.g. no files in dir */ /* Must reset e.g. no files in dir */
if (dir) if (dir)
attroff(COLOR_PAIR(cfg.curctx + 1) | A_BOLD); attroff(COLOR_PAIR(cfg.curctx + 1) | A_BOLD);
#endif
statusbar(path); statusbar(path);
} }
@ -5390,18 +5496,22 @@ static void redraw(char *path)
ncols = adjust_cols(ncols); ncols = adjust_cols(ncols);
#ifdef NOFCOLORS
attron(COLOR_PAIR(cfg.curctx + 1) | A_BOLD); attron(COLOR_PAIR(cfg.curctx + 1) | A_BOLD);
g_state.dircolor = 1; g_state.dircolor = 1;
#endif
/* Print listing */ /* Print listing */
for (i = curscroll; i < ndents && i < curscroll + onscreen; ++i) for (i = curscroll; i < ndents && i < curscroll + onscreen; ++i)
printptr(&pdents[i], ncols, i == cur); printptr(&pdents[i], ncols, i == cur);
#ifdef NOFCOLORS
/* Must reset e.g. no files in dir */ /* Must reset e.g. no files in dir */
if (g_state.dircolor) { if (g_state.dircolor) {
attroff(COLOR_PAIR(cfg.curctx + 1) | A_BOLD); attroff(COLOR_PAIR(cfg.curctx + 1) | A_BOLD);
g_state.dircolor = 0; g_state.dircolor = 0;
} }
#endif
statusbar(path); statusbar(path);
} }