commit 6aceb30069a69d1ea40eb8f756ec44698ed78d4d
parent 70f1594284d577ebaca53e1d92026c0f9cecf27e
Author: Jacob R. Edwards <n/a>
Date: Tue, 27 Dec 2022 10:52:48 -0800
Add a string search type and change regex syntax
This string search type is useful for referencing an item (whoose
position may change) for later use. The string must be absolutely
identical to the item's to match.
Regular expression syntax was also changed. Instead of encasing the
regex in '//' or '??', just one at the beginning is used (and the
negation operator is now to be put at the beginning). This makes
more sense for this application as argument separating has already
been done.
Diffstat:
4 files changed, 39 insertions(+), 25 deletions(-)
diff --git a/README b/README
@@ -26,7 +26,7 @@ Add files from 'playlist' to the queue:
Keep only items which end in ogg or flac:
- $ apc remove '/(ogg|flac)$/!'
+ $ apc remove '!/(ogg|flac)$'
Change the player to ogg123(1):
@@ -36,6 +36,6 @@ Sort the queue:
$ apc list | sort | apc truncate ^
-Reorder the queue (so that items matching "/pattern/" are next):
+Reorder the queue (so that items matching "/pattern" are next):
- $ apc remove /pattern/ | apc add ^
+ $ apc remove /pattern | apc add ^
diff --git a/aps/command.c b/aps/command.c
@@ -90,7 +90,7 @@ com_list(struct aps *aps, int fd, int argc, char **argv)
struct search search;
char *err;
- err = prepsearch(&search, aps->queue, argc ? *argv : "//");
+ err = prepsearch(&search, aps->queue, argc ? *argv : "/^");
if (err)
return err;
diff --git a/aps/find.c b/aps/find.c
@@ -92,6 +92,12 @@ matchnum(struct search *state)
return match;
}
+struct item *
+matchstr(struct search *state)
+{
+ return strcmp(state->u.str, state->cur->path) == 0 ? state->cur : NULL;
+}
+
void
renewsearch(struct search *state, struct item *start)
{
@@ -117,33 +123,40 @@ char *
prepsearch(struct search *state, struct item *start, char *pattern)
{
static char err[128];
- char reg[1024];
int rcode;
- char *p;
- char *ep;
- char c;
+ char *p, *ep;
+
+ state->inc = nextitem;
+ state->inv = 0;
if (!pattern || !pattern[0]) {
return "Empty pattern";
- } else if (*pattern == '/' || *pattern == '?') {
- c = *pattern;
- pattern += 1;
- p = strrchr(pattern, c);
- if (!p || (p[1] && (p[1] != '!' || p[2])))
- return "Unterminated regular expression";
- if (p - pattern >= sizeof(reg))
- return "Regular expression too long";
- state->inv = p[1] == '!';
- memcpy(reg, pattern, p - pattern);
- reg[p - pattern] = 0;
- if (!reg[0])
- strcpy(reg, "^");
- if ((rcode = regcomp(&state->u.reg, reg, REG_EXTENDED | REG_NOSUB | REG_ICASE))) {
+ } else if (*pattern == '!' || *pattern == '/' || *pattern == '?') {
+ /* NOTE: I'd like '!' to be a global modifier, but
+ * it wouldn't work with the current numeric patterns.
+ */
+ if (*pattern == '!') {
+ state->inv = 1;
+ ++pattern;
+ }
+
+ if (*pattern == '?')
+ state->inc = previtem;
+ else if (*pattern != '/')
+ return "Invalid regex direction (not / or ?)";
+ ++pattern;
+
+ if ((rcode = regcomp(&state->u.reg, pattern,
+ REG_EXTENDED | REG_NOSUB | REG_ICASE))) {
regerror(rcode, &state->u.reg, err, sizeof(err));
return err;
}
- state->inc = (c == '/') ? nextitem : previtem;
state->match = matchreg;
+ } else if (pattern[0] == '"') {
+ state->u.str = strdup(pattern + 1);
+ if (!state->u.str)
+ return "Unable to duplicate string";
+ state->match = matchstr;
} else if (pattern[0]) {
if ((ep = findnum(pattern, &state->u.num.min, &p)))
return ep;
@@ -166,8 +179,6 @@ prepsearch(struct search *state, struct item *start, char *pattern)
*/
return "Ranges spanning from negative to positive indexes not yet implemented";
}
- state->inv = 0;
- state->inc = nextitem;
state->match = matchnum;
}
@@ -180,6 +191,8 @@ stopsearch(struct search *state)
{
if (state->match == matchreg)
regfree(&state->u.reg);
+ else if (state->match == matchstr)
+ free(state->u.str);
}
struct item *
diff --git a/aps/find.h b/aps/find.h
@@ -9,6 +9,7 @@ struct search {
struct item *(*match)(struct search *);
union {
regex_t reg;
+ char *str;
struct {
int ind;
int min, max;