Commit 8e3a3cb3 authored by Leah Neukirchen's avatar Leah Neukirchen

add -e REGEX as a shortcut to filter basenames

parent 9c797d4d
......@@ -3,6 +3,7 @@
* Feature: lr is substantially faster as files only are stat(2)ed if
the output requires it.
* Feature: new option `-X` to print OSC 8 hyperlinks.
* Feature: new option `-e` for the common case of filtering file names.
* Bug: lr doesn't fail on symlinks refering to themselves anymore.
## 1.0 (2017-08-29)
......
......@@ -46,7 +46,7 @@ Over ls:
## Usage:
lr [-0|-F|-l [-TA|-TC|-TM]|-S|-f FMT] [-D] [-H|-L] [-1AGQXdhsx] [-U|-o ORD] [-t TEST]* PATH...
lr [-0|-F|-l [-TA|-TC|-TM]|-S|-f FMT] [-D] [-H|-L] [-1AGQXdhsx] [-U|-o ORD] [-e REGEX]* [-t TEST]* PATH...
The special path argument `-` makes `lr` read file names from standard
input, instead of traversing path.
......@@ -75,6 +75,7 @@ input, instead of traversing path.
* `-x`: don't enter other filesystems.
* `-U`: don't sort results.
* `-o ORD`: sort according to the string `ORD`, see below.
* `-e REGEX`: only show files where basename matches `REGEX`.
* `-t TEST`: only show files matching all `TEST`s, see below.
## Output formatting:
......
......@@ -13,6 +13,7 @@
.Op Fl 1AGQXdhsx
.Op Fl U | Fl o Ar ord
.br
.Op Fl e Ar regex
.Op Fl t Ar test
.Op Fl C Oo Ar color Ns Li \&: Oc Ns Ar path
.Ar path\ ...
......@@ -122,6 +123,9 @@ Sort according to
.Ar ord ,
see
.Sx SORT ORDER .
.It Fl e Ar regex
Only show files where basename matches the POSIX ERE
.Ar regex .
.It Fl t Ar test
Only show files matching the expression
.Ar test ,
......@@ -129,6 +133,8 @@ see
.Sx TESTS .
Multiple occurrences of
.Fl t
and
.Fl e
are regarded as a conjunction.
.It Fl C Oo Ar color Ns Li \&: Oc Ns Ar path
Behaves as if
......
......@@ -611,6 +611,38 @@ parse_dur(int64_t *n)
return 0;
}
static struct expr *
mkstrexpr(enum prop prop, enum op op, char *s, int negate)
{
int r = 0;
struct expr *e = mkexpr(op);
e->a.prop = prop;
if (op == EXPR_REGEX) {
e->b.regex = malloc(sizeof (regex_t));
r = regcomp(e->b.regex, s, REG_EXTENDED | REG_NOSUB);
} else if (op == EXPR_REGEXI) {
e->b.regex = malloc(sizeof (regex_t));
r = regcomp(e->b.regex, s, REG_EXTENDED | REG_NOSUB | REG_ICASE);
} else {
e->b.string = s;
}
if (r != 0) {
char msg[256];
regerror(r, e->b.regex, msg, sizeof msg);
parse_error("invalid regex '%s': %s", s, msg);
exit(2);
}
if (negate) {
struct expr *not = mkexpr(EXPR_NOT);
not->a.expr = e;
return not;
}
return e;
}
static struct expr *
parse_strcmp()
{
......@@ -665,35 +697,8 @@ parse_strcmp()
parse_error("invalid string operator at '%.15s'", pos);
char *s;
if (parse_string(&s)) {
int r = 0;
struct expr *e = mkexpr(op);
e->a.prop = prop;
if (op == EXPR_REGEX) {
e->b.regex = malloc(sizeof (regex_t));
r = regcomp(e->b.regex, s, REG_EXTENDED | REG_NOSUB);
} else if (op == EXPR_REGEXI) {
e->b.regex = malloc(sizeof (regex_t));
r = regcomp(e->b.regex, s, REG_EXTENDED | REG_NOSUB | REG_ICASE);
} else {
e->b.string = s;
}
if (r != 0) {
char msg[256];
regerror(r, e->b.regex, msg, sizeof msg);
parse_error("invalid regex '%s': %s", s, msg);
exit(2);
}
if (negate) {
struct expr *not = mkexpr(EXPR_NOT);
not->a.expr = e;
return not;
}
return e;
}
if (parse_string(&s))
return mkstrexpr(prop, op, s, negate);
parse_error("invalid string at '%.15s'", pos);
return 0;
......@@ -2083,11 +2088,11 @@ main(int argc, char *argv[])
setlocale(LC_ALL, "");
while ((c = getopt(argc, argv, "01AC:DFGHLQST:UXdf:lho:st:x")) != -1)
while ((c = getopt(argc, argv, "01AC:DFGHLQST:UXde:f:lho:st:x")) != -1)
switch (c) {
case '0': format = zero_format; input_delim = 0; Qflag = 0; break;
case '1': expr = chain(parse_expr("depth == 0 || prune"), EXPR_AND, expr); break;
case 'A': expr = chain(parse_expr("!(path ~~ \"*/.*\" && prune) && !path == \".\""), EXPR_AND, expr); break;
case 'A': expr = chain(expr, EXPR_AND, parse_expr("!(path ~~ \"*/.*\" && prune) && path != \".\"")); break;
case 'C':
if ((unsigned int)Cflag <
sizeof Cflags / sizeof Cflags[0]) {
......@@ -2109,6 +2114,8 @@ main(int argc, char *argv[])
case 'U': Uflag++; break;
case 'X': Xflag++; break;
case 'd': expr = chain(parse_expr("type == d && prune || print"), EXPR_AND, expr); break;
case 'e': expr = chain(expr, EXPR_AND,
mkstrexpr(PROP_NAME, EXPR_REGEX, optarg, 0)); break;
case 'f': format = optarg; break;
case 'h': hflag++; break;
case 'l': lflag++; Qflag++; format = long_format; break;
......@@ -2121,7 +2128,7 @@ main(int argc, char *argv[])
default:
fprintf(stderr,
"Usage: %s [-0|-F|-l [-TA|-TC|-TM]|-S|-f FMT] [-D] [-H|-L] [-1AGQdhsx]\n"
" [-U|-o ORD] [-t TEST]* [-C [COLOR:]PATH]* PATH...\n", argv0);
" [-U|-o ORD] [-e REGEX]* [-t TEST]* [-C [COLOR:]PATH]* PATH...\n", argv0);
exit(2);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment