README.md | 6 +++++- nnn.1 | 9 ++++++++- src/nnn.c | 49 ++++++++++++++++++++++++++++++++++--------------- diff --git a/README.md b/README.md index 793ccced08889b2f1978f52a67604dd7a8dfe6ea..88b36c814840a56e023a0bb8ceaa267bea93b1bf 100644 --- a/README.md +++ b/README.md @@ -320,12 +320,16 @@ The path is shown in the help and configuration screen. #### Filters -Filters support regexes to instantly (search-as-you-type) list the matching entries in the current directory. +Filters support regexes by default to instantly (search-as-you-type) list the matching entries in the current directory. Common use cases: - to list all matches starting with the filter expression, start the expression with a `^` (caret) symbol - type `\.mkv` to list all MKV files - use `.*` to match any character (_sort of_ fuzzy search) + +To filter entries by substring match: + + export NNN_PLAIN_FILTER=1 If `nnn` is invoked as root or the environment variable `NNN_SHOW_HIDDEN` is set the default filter will also match hidden files. diff --git a/nnn.1 b/nnn.1 index afefc08f026497fbb96786ff4c17891f6d00743c..d3e97e0f5b12d1df42a7c1810224a09622032e33 100644 --- a/nnn.1 +++ b/nnn.1 @@ -219,7 +219,7 @@ The first time a context is entered, it copies the state of the last visited context. Each context remembers its start directory and last visited directory. .Pp When a context is quit, the next active context is selected. If the last active context is quit, the program quits. .Sh FILTERS -Filters support regexes to instantly (search-as-you-type) list the matching +Filters support regexes by default to instantly (search-as-you-type) list the matching entries in the current directory. .Pp Common use cases: @@ -230,6 +230,8 @@ .br (2) Type '\\.mkv' to list all MKV files. .br (3) Use '.*' to match any character (\fIsort of\fR fuzzy search). +.Pp +To filter entries by substring match export the environment variable \fBNNN_PLAIN_FILTER\fR. .Pp If .Nm @@ -313,6 +315,11 @@ .Pp \fBNNN_RESTRICT_0B:\fR restrict opening 0-byte files due to unexpected behaviour; use \fIedit\fR or \fIopen with\fR to open the file. .Bd -literal export NNN_RESTRICT_0B=1 +.Ed +.Pp +\fBNNN_PLAIN_FILTER:\fR use substring match in filter mode. +.Bd -literal + export NNN_PLAIN_FILTER=1 .Ed .Sh KNOWN ISSUES If you are using urxvt you might have to set backspace key to DEC. diff --git a/src/nnn.c b/src/nnn.c index 76e448e72a2dc0e07d1089b66c387bd13d5609a6..723a636b575455031829c824309d2d7e6072c2c6 100644 --- a/src/nnn.c +++ b/src/nnn.c @@ -260,7 +260,7 @@ uint showcolor : 1; /* Set to show dirs in blue */ uint dircolor : 1; /* Current status of dir color */ uint metaviewer : 1; /* Index of metadata viewer in utils[] */ uint ctxactive : 1; /* Context active or not */ - uint reserved : 9; + uint reserved : 8; /* The following settings are global */ uint curctx : 2; /* Current context number */ uint picker : 1; /* Write selection to user-specified file */ @@ -270,6 +270,7 @@ uint useeditor : 1; /* Use VISUAL to open text files */ uint runscript : 1; /* Choose script to run mode */ uint runctx : 2; /* The context in which script is to be run */ uint restrict0b : 1; /* Restrict 0-byte file opening */ + uint filter_re : 1; /* Use regex filters */ } settings; /* Contexts or workspaces */ @@ -285,7 +286,7 @@ /* GLOBALS */ /* Configuration, contexts */ -static settings cfg = {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static settings cfg = {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; static context g_ctx[CTX_MAX] __attribute__ ((aligned)); static struct entry *dents; @@ -1065,10 +1066,17 @@ return r; } -static int visible(regex_t *regex, char *file) +static int visible_re(regex_t *regex, char *fname, char *fltr) +{ + return regexec(regex, fname, 0, NULL, 0) == 0; +} + +static int visible_str(regex_t *regex, char *fname, char *fltr) { - return regexec(regex, file, 0, NULL, 0) == 0; + return strcasestr(fname, fltr) != NULL; } + +static int (*filterfn)(regex_t *regex, char *fname, char *fltr) = &visible_re; static int entrycmp(const void *va, const void *vb) { @@ -1172,16 +1180,16 @@ /* * Move non-matching entries to the end */ -static int fill(struct entry **dents, int (*filter)(regex_t *, char *), regex_t *re) +static int fill(char* fltr, regex_t *re) { static int count; static struct entry _dent, *pdent1, *pdent2; for (count = 0; count < ndents; ++count) { - if (filter(re, (*dents)[count].name) == 0) { + if (filterfn(re, dents[count].name, fltr) == 0) { if (count != --ndents) { - pdent1 = &(*dents)[count]; - pdent2 = &(*dents)[ndents]; + pdent1 = &dents[count]; + pdent2 = &dents[ndents]; *(&_dent) = *pdent1; *pdent1 = *pdent2; @@ -1201,11 +1209,12 @@ { static regex_t re; /* Search filter */ - if (setfilter(&re, fltr) != 0) + if (cfg.filter_re && setfilter(&re, fltr) != 0) return -1; - ndents = fill(&dents, visible, &re); - regfree(&re); + ndents = fill(fltr, &re); + if (cfg.filter_re) + regfree(&re); if (!ndents) return 0; @@ -2159,10 +2168,14 @@ if (runpath) dprintf(fd, "NNN_SCRIPT: %s\n", runpath); if (getenv("NNN_SHOW_HIDDEN")) dprintf(fd, "NNN_SHOW_HIDDEN: 1\n"); - if (getenv("NNN_NO_AUTOSELECT")) + if (cfg.autoselect) dprintf(fd, "NNN_NO_AUTOSELECT: 1\n"); - if (getenv("NNN_NO_FILE_OPEN_ON_NAV")) + if (cfg.nonavopen) dprintf(fd, "NNN_NO_FILE_OPEN_ON_NAV: 1\n"); + if (cfg.restrict0b) + dprintf(fd, "NNN_RESTRICT_0B: 1\n"); + if (!cfg.filter_re) + dprintf(fd, "NNN_PLAIN_FILTER: 1\n"); dprintf(fd, "\n"); @@ -2373,7 +2386,7 @@ return n; } /* Return the position of the matching entry or 0 otherwise */ -static int dentfind(struct entry *dents, const char *fname, int n) +static int dentfind(const char *fname, int n) { static int i; @@ -2420,7 +2433,7 @@ DPRINTF_U(ts2.tv_nsec - ts1.tv_nsec); #endif /* Find cur from history */ - cur = dentfind(dents, lastname, ndents); + cur = dentfind(lastname, ndents); return TRUE; } @@ -3784,6 +3797,12 @@ /* Restrict opening of 0-byte files */ if (getenv("NNN_RESTRICT_0B")) cfg.restrict0b = 1; + + /* Use string-comparison in filter mode */ + if (getenv("NNN_PLAIN_FILTER")) { + cfg.filter_re = 0; + filterfn = &visible_str; + } signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN);