mirror of https://github.com/jarun/nnn.git
Support substring match in filter mode
This commit is contained in:
parent
08520ac80e
commit
098c2acb27
|
@ -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
9
nnn.1
|
@ -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
|
||||||
|
|
49
src/nnn.c
49
src/nnn.c
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue