commit 1b9d4438f2a013f35ef21afddf1e1950145a2939
parent 8a013d965d41a1a0c68ca11e173a88b6ffa58afe
Author: Arun Prakash Jana <engineerarun@gmail.com>
Date: Sun, 22 Feb 2026 18:08:19 +0530
Dim characters matching filters
Enabled by default. To disable:
make O_DIMFILTERED=0
Diffstat:
3 files changed, 61 insertions(+), 66 deletions(-)
diff --git a/Makefile b/Makefile
@@ -28,7 +28,7 @@ O_NOUG := 0 # disable user, group name in status bar
O_NOX11 := 0 # disable X11 integration
O_MATCHFLTR := 0 # allow filters without matches
O_NOSORT := 0 # disable sorting entries on dir load
-O_NOHIGHLIGHT := 0 # disable filter match highlights (default: enabled)
+O_DIMFILTERED := 1 # dim characters matching filter (default: enabled)
# User patches
O_COLEMAK := 0 # change key bindings to colemak compatible layout
@@ -147,8 +147,8 @@ ifeq ($(strip $(O_NOSORT)),1)
CPPFLAGS += -DNOSORT
endif
-ifeq ($(strip $(O_NOHIGHLIGHT)),1)
- CPPFLAGS += -DNOHIGHLIGHT_FILTER
+ifeq ($(strip $(O_DIMFILTERED)),1)
+ CPPFLAGS += -DDIM_FILTERED
endif
ifeq ($(shell $(PKG_CONFIG) ncursesw && echo 1),1)
diff --git a/patches/namefirst/mainline.diff b/patches/namefirst/mainline.diff
@@ -10,41 +10,41 @@ index 19ebc2cf..42a0a6b0 100644
@@ -430,6 +430,10 @@ typedef struct {
} session_header_t;
#endif
-
+
+static struct {
+ ushort_t maxnameln, maxsizeln, maxuidln, maxgidln, maxentln, uidln, gidln, printguid;
+} dtls;
+
/* GLOBALS */
-
+
/* Configuration, contexts */
@@ -1175,10 +1179,13 @@ static char *getpwname(uid_t uid)
static char *namecache;
-
+
if (uidcache != uid) {
+ if (dtls.maxuidln && !dtls.printguid)
+ dtls.printguid = 1;
struct passwd *pw = getpwuid(uid);
-
+
uidcache = uid;
namecache = pw ? pw->pw_name : NULL;
+ dtls.uidln = xstrlen(namecache ? namecache : xitoa(uid));
}
-
+
return namecache ? namecache : xitoa(uid);
@@ -1190,10 +1197,13 @@ static char *getgrname(gid_t gid)
static char *grpcache;
-
+
if (gidcache != gid) {
+ if (dtls.maxgidln && !dtls.printguid)
+ dtls.printguid = 1;
struct group *gr = getgrgid(gid);
-
+
gidcache = gid;
grpcache = gr ? gr->gr_name : NULL;
+ dtls.gidln = xstrlen(grpcache ? grpcache : xitoa(gid));
}
-
+
return grpcache ? grpcache : xitoa(gid);
@@ -4346,14 +4356,13 @@ static void resetdircolor(int flags)
* Max supported str length: NAME_MAX;
@@ -67,27 +67,27 @@ index 19ebc2cf..42a0a6b0 100644
@@ -4378,7 +4387,7 @@ static wchar_t *unescape(const char *str, uint_t maxcols)
++buf;
}
-
+
- return wbuf;
+ return len;
}
-
+
static off_t get_size(off_t size, off_t *pval, int comp)
@@ -4627,9 +4636,10 @@ static uchar_t get_color_pair_name_ind(const struct entry *ent, char *pind, int
}
-
- #ifndef NOHIGHLIGHT_FILTER
--static void printent_name(const struct entry *ent, uint_t namecols, bool sel)
-+static size_t printent_name(const struct entry *ent, uint_t namecols, bool sel)
+
+ #ifdef DIM_FILTERED
+-static void printent_name(const struct entry *ent, uint_t namecols)
++static size_t printent_name(const struct entry *ent, uint_t namecols)
{
char * const fltr = g_ctx[cfg.curctx].c_fltr;
+ size_t namelen;
-
- /* If there's a filter string, highlight matches */
+
+ /* If there's a filter string, dim matching characters */
if (fltr[1]) {
-@@ -4644,15 +4654,18 @@ static void printent_name(const struct entry *ent, uint_t namecols, bool sel)
+@@ -4644,15 +4654,18 @@ static void printent_name(const struct entry *ent, uint_t namecols)
if (cfg.regex) {
- /* For regex, we don't highlight - just print normally */
+ /* For regex, we don't dim - just print normally */
#ifndef NOLC
- addwstr(unescape(ent->name, namecols));
+ namelen = unescape(ent->name, namecols);
@@ -107,18 +107,18 @@ index 19ebc2cf..42a0a6b0 100644
uint_t col = 0;
for (wchar_t *p = wbuf; *p && col < namecols; ++p, ++col) {
if (matched[col]) {
-@@ -4665,7 +4678,8 @@ static void printent_name(const struct entry *ent, uint_t namecols, bool sel)
+@@ -4665,7 +4678,8 @@ static void printent_name(const struct entry *ent, uint_t namecols)
}
#else
- /* Non-wide character version for fuzzy highlighting */
+ /* Non-wide character version for fuzzy dimming */
- const char *name = unescape(ent->name, MIN(namecols, ent->nlen) + 1);
+ namelen = unescape(ent->name, MIN(namecols, ent->nlen) + 1);
+ const char *name = (char *)g_buf;
for (uint_t i = 0; (i < namecols) && name[i]; ++i) {
if (matched[i]) {
attron(match_attrs);
-@@ -4680,7 +4694,8 @@ static void printent_name(const struct entry *ent, uint_t namecols, bool sel)
- /* String match - highlight the substring */
+@@ -4680,7 +4694,8 @@ static void printent_name(const struct entry *ent, uint_t namecols)
+ /* String match - dim the substring */
string_match_positions(fltr + 1, ent->name, matched);
#ifndef NOLC
- wchar_t * const wbuf = unescape(ent->name, namecols);
@@ -127,17 +127,17 @@ index 19ebc2cf..42a0a6b0 100644
uint_t col = 0;
for (wchar_t *p = wbuf; *p && col < namecols; ++p, ++col) {
if (matched[col]) {
-@@ -4693,7 +4708,8 @@ static void printent_name(const struct entry *ent, uint_t namecols, bool sel)
+@@ -4693,7 +4708,8 @@ static void printent_name(const struct entry *ent, uint_t namecols)
}
#else
- /* Non-wide character version for string highlighting */
+ /* Non-wide character version for string dimming */
- const char *name = unescape(ent->name, MIN(namecols, ent->nlen) + 1);
+ namelen = unescape(ent->name, MIN(namecols, ent->nlen) + 1);
+ const char *name = (char *)g_buf;
for (uint_t i = 0; (i < namecols) && name[i]; ++i) {
if (matched[i]) {
attron(match_attrs);
-@@ -4708,22 +4724,30 @@ static void printent_name(const struct entry *ent, uint_t namecols, bool sel)
+@@ -4708,22 +4724,30 @@ static void printent_name(const struct entry *ent, uint_t namecols)
} else {
/* No filter or filter not active - print normally */
#ifndef NOLC
@@ -154,9 +154,9 @@ index 19ebc2cf..42a0a6b0 100644
+ return namelen;
}
#else
- /* Without highlight support, just print the name normally */
--static inline void printent_name(const struct entry *ent, uint_t namecols, bool sel)
-+static inline size_t printent_name(const struct entry *ent, uint_t namecols, bool sel)
+ /* Without dimming support, just print the name normally */
+-static inline void printent_name(const struct entry *ent, uint_t namecols)
++static inline size_t printent_name(const struct entry *ent, uint_t namecols)
{
(void)sel; /* Suppress unused parameter warning */
#ifndef NOLC
@@ -172,8 +172,8 @@ index 19ebc2cf..42a0a6b0 100644
+ return namelen;
}
#endif
-
-@@ -4731,38 +4755,14 @@ static void printent(int pdents_index, uint_t namecols, bool sel)
+
+@@ -4731,38 +4755,14 @@ static void printent(int pdents_index, uint_t namecols)
{
const struct entry *ent = &pdents[pdents_index];
char ind = '\0';
@@ -203,24 +203,24 @@ index 19ebc2cf..42a0a6b0 100644
- }
+ int attrs = 0;
+ size_t namelen;
-
+
if (g_state.showlines) {
ptrdiff_t rel_num = pdents_index - cur;
printw(rel_num == 0 ? "%4td" : "%+4td", rel_num);
}
-
+
- attrs = 0;
-
uchar_t color_pair = get_color_pair_name_ind(ent, &ind, &attrs);
-
+
addch((ent->flags & FILE_SELECTED) ? '+' | A_REVERSE | A_BOLD : ' ');
-@@ -4786,12 +4786,44 @@ static void printent(int pdents_index, uint_t namecols, bool sel)
+@@ -4786,12 +4786,44 @@ static void printent(int pdents_index, uint_t namecols)
if (!ind)
++namecols;
-
-- printent_name(ent, namecols, sel);
-+ namelen = printent_name(ent, namecols, sel);
-
+
+- printent_name(ent, namecols);
++ namelen = printent_name(ent, namecols);
+
- if (attrs)
+ if (!sel && attrs)
attroff(attrs);
@@ -259,12 +259,12 @@ index 19ebc2cf..42a0a6b0 100644
+ if (attrs)
+ attroff(attrs);
}
-
+
/**
@@ -7670,26 +7702,19 @@ static void statusbar(char *path)
tocursor();
}
-
+
-static inline void markhovered(void)
-{
- if (cfg.showdetail && ndents) { /* Bold forward arrowhead */
@@ -289,7 +289,7 @@ index 19ebc2cf..42a0a6b0 100644
- n -= 32;
+ n -= (dtls.maxentln - 2 - dtls.maxnameln);
}
-
+
/* 2 columns for preceding space and indicator */
@@ -7728,8 +7753,6 @@ static void draw_line(int ncols)
/* Must reset e.g. no files in dir */
@@ -298,12 +298,12 @@ index 19ebc2cf..42a0a6b0 100644
-
- markhovered();
}
-
+
static void redraw(char *path)
@@ -7837,6 +7860,26 @@ static void redraw(char *path)
int onscreen = MIN(ONSCREEN + curscroll, ndents);
int len = scanselforpath(path, FALSE);
-
+
+ if (cfg.showdetail) {
+ ushort_t lenbuf = dtls.maxnameln = dtls.maxsizeln = dtls.maxuidln = dtls.maxgidln = dtls.printguid = 0;
+ for (i = curscroll; i < onscreen; ++i) {
@@ -325,14 +325,14 @@ index 19ebc2cf..42a0a6b0 100644
+ }
+
ncols = adjust_cols(ncols);
-
+
/* Print listing */
@@ -7865,7 +7908,7 @@ static void redraw(char *path)
#endif
}
-
+
- markhovered();
+ statusbar(path);
}
-
+
static bool cdprep(char *lastdir, char *lastname, char *path, char *newpath)
diff --git a/src/nnn.c b/src/nnn.c
@@ -3159,7 +3159,7 @@ static int visible_str(const fltrexp_t *fltrexp, const char *fname)
return fnstrstr(fname, fltrexp->str) != NULL;
}
-#ifndef NOHIGHLIGHT_FILTER
+#ifdef DIM_FILTERED
/*
* Get match positions for fuzzy matching
* Populates matched array with 1 for matched bytes, 0 otherwise
@@ -4626,23 +4626,19 @@ static uchar_t get_color_pair_name_ind(const struct entry *ent, char *pind, int
return C_UND;
}
-#ifndef NOHIGHLIGHT_FILTER
-static void printent_name(const struct entry *ent, uint_t namecols, bool sel)
+#ifdef DIM_FILTERED
+static void printent_name(const struct entry *ent, uint_t namecols)
{
char * const fltr = g_ctx[cfg.curctx].c_fltr;
- /* If there's a filter string, highlight matches */
+ /* If there's a filter string, dim matching characters */
if (fltr[1]) {
uchar_t matched[NAME_MAX] = {0};
- int match_attrs = A_BOLD; /* Default: just bold for selected entries */
-
- /* For non-selected entries, also add reverse video to matches */
- if (!sel)
- match_attrs |= A_REVERSE;
+ int match_attrs = A_DIM;
/* Get match positions based on filter type */
if (cfg.regex) {
- /* For regex, we don't highlight - just print normally */
+ /* For regex, we don't dim - just print normally */
#ifndef NOLC
addwstr(unescape(ent->name, namecols));
#else
@@ -4664,7 +4660,7 @@ static void printent_name(const struct entry *ent, uint_t namecols, bool sel)
}
}
#else
- /* Non-wide character version for fuzzy highlighting */
+ /* Non-wide character version for fuzzy dimming */
const char *name = unescape(ent->name, MIN(namecols, ent->nlen) + 1);
for (uint_t i = 0; (i < namecols) && name[i]; ++i) {
if (matched[i]) {
@@ -4677,7 +4673,7 @@ static void printent_name(const struct entry *ent, uint_t namecols, bool sel)
}
#endif
} else {
- /* String match - highlight the substring */
+ /* String match - dim the substring */
string_match_positions(fltr + 1, ent->name, matched);
#ifndef NOLC
wchar_t * const wbuf = unescape(ent->name, namecols);
@@ -4692,7 +4688,7 @@ static void printent_name(const struct entry *ent, uint_t namecols, bool sel)
}
}
#else
- /* Non-wide character version for string highlighting */
+ /* Non-wide character version for string dimming */
const char *name = unescape(ent->name, MIN(namecols, ent->nlen) + 1);
for (uint_t i = 0; (i < namecols) && name[i]; ++i) {
if (matched[i]) {
@@ -4715,10 +4711,9 @@ static void printent_name(const struct entry *ent, uint_t namecols, bool sel)
}
}
#else
-/* Without highlight support, just print the name normally */
-static inline void printent_name(const struct entry *ent, uint_t namecols, bool sel)
+/* Without dimming support, just print the name normally */
+static inline void printent_name(const struct entry *ent, uint_t namecols)
{
- (void)sel; /* Suppress unused parameter warning */
#ifndef NOLC
addwstr(unescape(ent->name, namecols));
#else
@@ -4786,7 +4781,7 @@ static void printent(int pdents_index, uint_t namecols, bool sel)
if (!ind)
++namecols;
- printent_name(ent, namecols, sel);
+ printent_name(ent, namecols);
if (attrs)
attroff(attrs);