Support substring match in filter mode

This commit is contained in:
Arun Prakash Jana 2019-01-13 22:49:14 +05:30
parent 08520ac80e
commit 098c2acb27
No known key found for this signature in database
GPG Key ID: A75979F35C080412
3 changed files with 47 additions and 17 deletions

View File

@ -320,13 +320,17 @@ The path is shown in the help and configuration screen.
#### Filters #### 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: Common use cases:
- to list all matches starting with the filter expression, start the expression with a `^` (caret) symbol - to list all matches starting with the filter expression, start the expression with a `^` (caret) symbol
- type `\.mkv` to list all MKV files - type `\.mkv` to list all MKV files
- use `.*` to match any character (_sort of_ fuzzy search) - 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. If `nnn` is invoked as root or the environment variable `NNN_SHOW_HIDDEN` is set the default filter will also match hidden files.
#### Navigate-as-you-type mode #### Navigate-as-you-type mode

9
nnn.1
View File

@ -219,7 +219,7 @@ The first time a context is entered, it copies the state of the last visited con
.Pp .Pp
When a context is quit, the next active context is selected. If the last active context is quit, the program quits. When a context is quit, the next active context is selected. If the last active context is quit, the program quits.
.Sh FILTERS .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. entries in the current directory.
.Pp .Pp
Common use cases: Common use cases:
@ -231,6 +231,8 @@ with a '^' (caret) symbol.
.br .br
(3) Use '.*' to match any character (\fIsort of\fR fuzzy search). (3) Use '.*' to match any character (\fIsort of\fR fuzzy search).
.Pp .Pp
To filter entries by substring match export the environment variable \fBNNN_PLAIN_FILTER\fR.
.Pp
If If
.Nm .Nm
is invoked as root or the environment variable \fBNNN_SHOW_HIDDEN\fR is set the default filter will also match hidden files. is invoked as root or the environment variable \fBNNN_SHOW_HIDDEN\fR is set the default filter will also match hidden files.
@ -314,6 +316,11 @@ files.
.Bd -literal .Bd -literal
export NNN_RESTRICT_0B=1 export NNN_RESTRICT_0B=1
.Ed .Ed
.Pp
\fBNNN_PLAIN_FILTER:\fR use substring match in filter mode.
.Bd -literal
export NNN_PLAIN_FILTER=1
.Ed
.Sh KNOWN ISSUES .Sh KNOWN ISSUES
If you are using urxvt you might have to set backspace key to DEC. If you are using urxvt you might have to set backspace key to DEC.
.Sh AUTHORS .Sh AUTHORS

View File

@ -260,7 +260,7 @@ typedef struct {
uint dircolor : 1; /* Current status of dir color */ uint dircolor : 1; /* Current status of dir color */
uint metaviewer : 1; /* Index of metadata viewer in utils[] */ uint metaviewer : 1; /* Index of metadata viewer in utils[] */
uint ctxactive : 1; /* Context active or not */ uint ctxactive : 1; /* Context active or not */
uint reserved : 9; uint reserved : 8;
/* The following settings are global */ /* The following settings are global */
uint curctx : 2; /* Current context number */ uint curctx : 2; /* Current context number */
uint picker : 1; /* Write selection to user-specified file */ uint picker : 1; /* Write selection to user-specified file */
@ -270,6 +270,7 @@ typedef struct {
uint runscript : 1; /* Choose script to run mode */ uint runscript : 1; /* Choose script to run mode */
uint runctx : 2; /* The context in which script is to be run */ uint runctx : 2; /* The context in which script is to be run */
uint restrict0b : 1; /* Restrict 0-byte file opening */ uint restrict0b : 1; /* Restrict 0-byte file opening */
uint filter_re : 1; /* Use regex filters */
} settings; } settings;
/* Contexts or workspaces */ /* Contexts or workspaces */
@ -285,7 +286,7 @@ typedef struct {
/* GLOBALS */ /* GLOBALS */
/* Configuration, contexts */ /* 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 context g_ctx[CTX_MAX] __attribute__ ((aligned));
static struct entry *dents; static struct entry *dents;
@ -1065,11 +1066,18 @@ static int setfilter(regex_t *regex, char *filter)
return r; return r;
} }
static int visible(regex_t *regex, char *file) static int visible_re(regex_t *regex, char *fname, char *fltr)
{ {
return regexec(regex, file, 0, NULL, 0) == 0; return regexec(regex, fname, 0, NULL, 0) == 0;
} }
static int visible_str(regex_t *regex, char *fname, char *fltr)
{
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) static int entrycmp(const void *va, const void *vb)
{ {
static pEntry pa, pb; static pEntry pa, pb;
@ -1172,16 +1180,16 @@ static int nextsel(int *presel)
/* /*
* Move non-matching entries to the end * 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 int count;
static struct entry _dent, *pdent1, *pdent2; static struct entry _dent, *pdent1, *pdent2;
for (count = 0; count < ndents; ++count) { for (count = 0; count < ndents; ++count) {
if (filter(re, (*dents)[count].name) == 0) { if (filterfn(re, dents[count].name, fltr) == 0) {
if (count != --ndents) { if (count != --ndents) {
pdent1 = &(*dents)[count]; pdent1 = &dents[count];
pdent2 = &(*dents)[ndents]; pdent2 = &dents[ndents];
*(&_dent) = *pdent1; *(&_dent) = *pdent1;
*pdent1 = *pdent2; *pdent1 = *pdent2;
@ -1201,11 +1209,12 @@ static int matches(char *fltr)
static regex_t re; static regex_t re;
/* Search filter */ /* Search filter */
if (setfilter(&re, fltr) != 0) if (cfg.filter_re && setfilter(&re, fltr) != 0)
return -1; return -1;
ndents = fill(&dents, visible, &re); ndents = fill(fltr, &re);
regfree(&re); if (cfg.filter_re)
regfree(&re);
if (!ndents) if (!ndents)
return 0; return 0;
@ -2159,10 +2168,14 @@ static bool show_help(char *path)
dprintf(fd, "NNN_SCRIPT: %s\n", runpath); dprintf(fd, "NNN_SCRIPT: %s\n", runpath);
if (getenv("NNN_SHOW_HIDDEN")) if (getenv("NNN_SHOW_HIDDEN"))
dprintf(fd, "NNN_SHOW_HIDDEN: 1\n"); dprintf(fd, "NNN_SHOW_HIDDEN: 1\n");
if (getenv("NNN_NO_AUTOSELECT")) if (cfg.autoselect)
dprintf(fd, "NNN_NO_AUTOSELECT: 1\n"); 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"); 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"); dprintf(fd, "\n");
@ -2373,7 +2386,7 @@ static int dentfill(char *path, struct entry **dents)
} }
/* Return the position of the matching entry or 0 otherwise */ /* 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; static int i;
@ -2420,7 +2433,7 @@ static bool populate(char *path, char *lastname)
#endif #endif
/* Find cur from history */ /* Find cur from history */
cur = dentfind(dents, lastname, ndents); cur = dentfind(lastname, ndents);
return TRUE; return TRUE;
} }
@ -3785,6 +3798,12 @@ int main(int argc, char *argv[])
if (getenv("NNN_RESTRICT_0B")) if (getenv("NNN_RESTRICT_0B"))
cfg.restrict0b = 1; 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(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN); signal(SIGQUIT, SIG_IGN);