aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nnn.16
-rw-r--r--src/nnn.c69
2 files changed, 58 insertions, 17 deletions
diff --git a/nnn.1 b/nnn.1
index 5094cd3..2193f08 100644
--- a/nnn.1
+++ b/nnn.1
@@ -138,13 +138,15 @@ When a session is loaded dynamically, the last working session is saved automati
All the session files are located in the \fB${XDG_CONFIG_HOME:-$HOME/.config}/nnn/sessions\fR directory by the session name.
"@" is the "last session" file.
.Sh FILTERS
-Filters are substrings to find matching entries in the current directory instantly (\fIsearch-as-you-type\fR). There is a program option to switch to regex filters.
+Filters are strings to find matching entries in the current directory instantly (\fIsearch-as-you-type\fR). There is a program option to switch to regex filters. Matches are case-insensitive by default.
.Pp
-To switch the filter type at runtime:
+To modify match criteria at runtime:
.br
- string to regex: press '\\' at empty filter prompt
.br
- regex to string: press '/' at empty filter prompt
+.br
+- toggle case sensitivity: press '|' at empty filter prompt
.Pp
Common regex use cases:
.Pp
diff --git a/src/nnn.c b/src/nnn.c
index 57d5289..9ef016c 100644
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -693,6 +693,18 @@ static void printprompt(const char *str)
addstr(str);
}
+static void clearinfoln(void)
+{
+ move(xlines - 2, 0);
+ addstr("");
+}
+
+static void printinfoln(const char *str)
+{
+ clearinfoln();
+ mvaddstr(xlines - 2, xcols - strlen(str), str);
+}
+
static int get_input(const char *prompt)
{
int r = KEY_RESIZE;
@@ -1817,9 +1829,12 @@ static char xchartohex(char c)
return c;
}
+static char * (*fnstrstr)(const char *haystack, const char *needle) = &strcasestr;
+static int regflags = REG_NOSUB | REG_EXTENDED | REG_ICASE;
+
static int setfilter(regex_t *regex, const char *filter)
{
- return regcomp(regex, filter, REG_NOSUB | REG_EXTENDED | REG_ICASE);
+ return regcomp(regex, filter, regflags);
}
static int visible_re(const fltrexp_t *fltrexp, const char *fname)
@@ -1829,7 +1844,7 @@ static int visible_re(const fltrexp_t *fltrexp, const char *fname)
static int visible_str(const fltrexp_t *fltrexp, const char *fname)
{
- return strcasestr(fname, fltrexp->str) != NULL;
+ return fnstrstr(fname, fltrexp->str) != NULL;
}
static int (*filterfn)(const fltrexp_t *fltr, const char *fname) = &visible_str;
@@ -1992,6 +2007,22 @@ static int nextsel(int presel)
return 0;
}
+static void showfilterinfo(void)
+{
+ char info[REGEX_MAX];
+
+ snprintf(info, REGEX_MAX - 1, " %s [/\\], %s [|]",
+ (cfg.regex ? "regex" : "str"),
+ ((fnstrstr == &strcasestr) ? "ic" : "noic"));
+ printinfoln(info);
+}
+
+static void showfilter(char *str)
+{
+ showfilterinfo();
+ printprompt(str);
+}
+
static inline void swap_ent(int id1, int id2)
{
struct entry _dent, *pdent1 = &dents[id1], *pdent2 = &dents[id2];
@@ -2063,7 +2094,7 @@ static int filterentries(char *path, char *lastname)
cleartimeout();
curs_set(TRUE);
- printprompt(ln);
+ showfilter(ln);
while ((r = get_wch(ch)) != ERR) {
//DPRINTF_D(*ch);
@@ -2074,7 +2105,7 @@ static int filterentries(char *path, char *lastname)
case KEY_RESIZE:
clearoldprompt();
redraw(path);
- printprompt(ln);
+ showfilter(ln);
continue;
#endif
case KEY_DC: // fallthrough
@@ -2101,12 +2132,12 @@ static int filterentries(char *path, char *lastname)
if (matches(pln) != -1)
redraw(path);
- printprompt(ln);
+ showfilter(ln);
continue;
case KEY_MOUSE: // fallthrough
case 27: /* Exit filter mode on Escape */
goto end;
- case KEY_UP: /* On the first Up, show previous filter */
+ case KEY_UP: /* On the first Up, apply previous filter */
if (len == 1 && ln[REGEX_MAX - 1]) {
ln[1] = ln[REGEX_MAX - 1];
ln[REGEX_MAX - 1] = '\0';
@@ -2115,7 +2146,7 @@ static int filterentries(char *path, char *lastname)
if (matches(pln) != -1)
redraw(path);
- printprompt(ln);
+ showfilter(ln);
continue;
}
}
@@ -2135,23 +2166,29 @@ static int filterentries(char *path, char *lastname)
goto end;
}
- DPRINTF_S(ln);
+ /* Toggle case-sensitivity */
+ if (*ch == '|') {
+ fnstrstr = (fnstrstr == &strcasestr) ? &strstr : &strcasestr;
+ regflags ^= REG_ICASE;
+ showfilter(ln);
+ continue;
+ }
+ /* string to regex */
if (*ch == RFILTER && ln[0] == FILTER) {
- DPRINTF_S("set back");
wln[0] = ln[0] = RFILTER;
cfg.regex = TRUE;
filterfn = &visible_re;
- printprompt(ln);
+ showfilter(ln);
continue;
}
+ /* regex to string */
if (*ch == FILTER && ln[0] == RFILTER) {
- DPRINTF_S("set forward");
wln[0] = ln[0] = FILTER;
cfg.regex = FALSE;
filterfn = &visible_str;
- printprompt(ln);
+ showfilter(ln);
continue;
}
}
@@ -2173,7 +2210,7 @@ static int filterentries(char *path, char *lastname)
/* ndents = total; */
if (matches(pln) == -1) {
- printprompt(ln);
+ showfilter(ln);
continue;
}
@@ -2193,11 +2230,13 @@ static int filterentries(char *path, char *lastname)
* cases where the dir has permissions. This skips a redraw().
*/
redraw(path);
- printprompt(ln);
+ showfilter(ln);
} else
break;
}
end:
+ clearinfoln();
+
/* Save last working filter in-filter */
if (ln[1])
ln[REGEX_MAX - 1] = ln[1];
@@ -5608,7 +5647,7 @@ static void usage(void)
" -H show hidden files\n"
" -K detect key collision\n"
" -n nav-as-you-type mode\n"
- " -o open files on Enter\n"
+ " -o open files only on Enter\n"
" -p file selection file [stdout if '-']\n"
" -Q no quit confirmation\n"
" -r use advcpmv patched cp, mv\n"