Skip to content

Commit

Permalink
clipdel: add -F to match literal instead of regex
Browse files Browse the repository at this point in the history
this adds an -F flag similar to grep to allow matching literals
instead of a regex.

useful in scripting context where the script has a literal line
to match against. using -F avoids having to escape troublesome
regex characters.
  • Loading branch information
N-R-K committed Nov 9, 2024
1 parent 7d6e821 commit 97dace5
Showing 1 changed file with 34 additions and 13 deletions.
47 changes: 34 additions & 13 deletions src/clipdel.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "config.h"
Expand All @@ -24,20 +25,31 @@ enum delete_mode {
struct clipdel_state {
enum delete_mode mode;
bool invert_match;
regex_t rgx;
bool literal_match;
union {
regex_t rgx;
const char *needle;
};
};

/**
* Callback for cs_remove. In order for the delete to actually happen, we must
* be running DELETE_REAL.
*/
static enum cs_remove_action _nonnull_
remove_if_rgx_match(uint64_t hash _unused_, const char *line, void *private) {
static enum cs_remove_action _nonnull_ remove_if_match(uint64_t hash _unused_,
const char *line,
void *private) {
struct clipdel_state *state = private;
int ret = regexec(&state->rgx, line, 0, NULL, 0);
expect(ret == 0 || ret == REG_NOMATCH);
bool matches;
if (state->literal_match) {
matches = strstr(line, state->needle) != NULL;
} else {
int ret = regexec(&state->rgx, line, 0, NULL, 0);
expect(ret == 0 || ret == REG_NOMATCH);
matches = ret == 0;
}

bool wants_del = state->invert_match ? ret : !ret;
bool wants_del = state->invert_match ? !matches : matches;
if (wants_del) {
puts(line);
}
Expand All @@ -47,21 +59,25 @@ remove_if_rgx_match(uint64_t hash _unused_, const char *line, void *private) {
}

int main(int argc, char *argv[]) {
const char usage[] = "Usage: clipdel [-d] [-v] regex";
const char usage[] = "Usage: clipdel [-d] [-F] [-v] pattern";

_drop_(config_free) struct config cfg = setup("clipdel");

struct clipdel_state state = {
.mode = DELETE_DRY_RUN,
.invert_match = false,
.literal_match = false,
};

int opt;
while ((opt = getopt(argc, argv, "dv")) != -1) {
while ((opt = getopt(argc, argv, "dFv")) != -1) {
switch (opt) {
case 'd':
state.mode = DELETE_REAL;
break;
case 'F':
state.literal_match = true;
break;
case 'v':
state.invert_match = true;
break;
Expand All @@ -80,13 +96,18 @@ int main(int argc, char *argv[]) {
_drop_(cs_destroy) struct clip_store cs;
expect(cs_init(&cs, snip_fd, content_dir_fd) == 0);

die_on(regcomp(&state.rgx, argv[optind], REG_EXTENDED | REG_NOSUB),
"Could not compile regex\n");
if (!state.literal_match) {
die_on(regcomp(&state.rgx, argv[optind], REG_EXTENDED | REG_NOSUB),
"Could not compile regex\n");
} else {
state.needle = argv[optind];
}

expect(cs_remove(&cs, CS_ITER_OLDEST_FIRST, remove_if_rgx_match, &state) ==
0);
expect(cs_remove(&cs, CS_ITER_OLDEST_FIRST, remove_if_match, &state) == 0);

regfree(&state.rgx);
if (!state.literal_match) {
regfree(&state.rgx);
}

return 0;
}

0 comments on commit 97dace5

Please sign in to comment.