Deprecated --confirm flag
This commit is contained in:
parent
3d0c07a0b8
commit
5eb905b01f
@ -15,7 +15,6 @@ It's written in pure C with no dependencies.
|
||||
* `-v` `--verbose` print verbose debugging info
|
||||
* `-i` `--ignore-case` perform a case-insensitive match
|
||||
* `-I` `--inplace` perform replacements or filtering in-place on files
|
||||
* `-c` `--confirm` during replacement, confirm before each replacement
|
||||
* `-e` `--explain` print an explanation of the matches
|
||||
* `-j` `--json` print matches as JSON objects
|
||||
* `-l` `--list-files` print only filenames containing matches
|
||||
|
4
bp.1
4
bp.1
@ -41,10 +41,6 @@ Perform pattern matching case-insensitively.
|
||||
Perform filtering or replacement in-place (i.e.\ overwrite files with
|
||||
new content).
|
||||
.TP
|
||||
\f[B]-c\f[R], \f[B]--confirm\f[R]
|
||||
During in-place modification of a file, confirm before each
|
||||
modification.
|
||||
.TP
|
||||
\f[B]-r\f[R], \f[B]--replace\f[R] \f[I]replacement\f[R]
|
||||
Replace all occurrences of the main pattern with the given string.
|
||||
.TP
|
||||
|
3
bp.1.md
3
bp.1.md
@ -42,9 +42,6 @@ themselves.
|
||||
: Perform filtering or replacement in-place (i.e. overwrite files with new
|
||||
content).
|
||||
|
||||
`-c`, `--confirm`
|
||||
: During in-place modification of a file, confirm before each modification.
|
||||
|
||||
`-r`, `--replace` *replacement*
|
||||
: Replace all occurrences of the main pattern with the given string.
|
||||
|
||||
|
86
bp.c
86
bp.c
@ -45,7 +45,6 @@ static const char *usage = (
|
||||
" -j --json print matches as a list of JSON objects\n"
|
||||
" -i --ignore-case preform matching case-insensitively\n"
|
||||
" -I --inplace modify a file in-place\n"
|
||||
" -c --confirm ask for confirmation on each replacement\n"
|
||||
" -l --list-files list filenames only\n"
|
||||
" -p --pattern <pat> provide a pattern (equivalent to bp '\\(<pat>)')\n"
|
||||
" -w --word <string-pat> find words matching the given string pattern\n"
|
||||
@ -61,11 +60,9 @@ static const char *usage = (
|
||||
#define CHECK_FIRST_N_BYTES 256
|
||||
|
||||
// Flag-configurable options:
|
||||
typedef enum { CONFIRM_ASK, CONFIRM_ALL, CONFIRM_NONE } confirm_t;
|
||||
static struct {
|
||||
int context_before, context_after;
|
||||
bool ignorecase, verbose, git_mode;
|
||||
confirm_t confirm;
|
||||
enum { MODE_NORMAL, MODE_LISTFILES, MODE_INPLACE, MODE_JSON, MODE_EXPLAIN } mode;
|
||||
enum { FORMAT_AUTO, FORMAT_FANCY, FORMAT_PLAIN } format;
|
||||
pat_t *skip;
|
||||
@ -74,7 +71,6 @@ static struct {
|
||||
.context_after = USE_DEFAULT_CONTEXT,
|
||||
.ignorecase = false,
|
||||
.verbose = false,
|
||||
.confirm = CONFIRM_ALL,
|
||||
.mode = MODE_NORMAL,
|
||||
.format = FORMAT_AUTO,
|
||||
.skip = NULL,
|
||||
@ -84,9 +80,6 @@ static struct {
|
||||
static FILE *modifying_file = NULL;
|
||||
static file_t *backup_file;
|
||||
|
||||
// Used for user input/output that doesn't interfere with unix pipeline
|
||||
static FILE *tty_out = NULL, *tty_in = NULL;
|
||||
|
||||
//
|
||||
// Helper function to reduce code duplication
|
||||
//
|
||||
@ -226,63 +219,6 @@ static void sig_handler(int sig)
|
||||
if (kill(0, sig)) _exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
//
|
||||
// Present the user with a prompt to confirm replacements before they happen.
|
||||
// If the user rejects a replacement, the match object is set to the underlying
|
||||
// non-replacement value.
|
||||
//
|
||||
static void confirm_replacements(file_t *f, match_t *m, confirm_t *confirm)
|
||||
{
|
||||
if (*confirm == CONFIRM_ALL) return;
|
||||
if (m->pat->type == BP_REPLACE) {
|
||||
if (*confirm == CONFIRM_NONE) {
|
||||
m->skip_replacement = true;
|
||||
goto check_children;
|
||||
}
|
||||
|
||||
{ // Print the original
|
||||
printer_t pr = {.file = f, .context_before = options.context_before,
|
||||
.context_after = options.context_after,
|
||||
.use_color = true, .print_line_numbers = true};
|
||||
print_match(tty_out, &pr, m->children[0]);
|
||||
// Print trailing context lines:
|
||||
print_match(tty_out, &pr, NULL);
|
||||
}
|
||||
if (options.context_before > 1 || options.context_after > 1) fprintf(tty_out, "\n");
|
||||
{ // Print the replacement
|
||||
printer_t pr = {.file = f, .context_before = options.context_before,
|
||||
.context_after = options.context_after,
|
||||
.use_color = true, .print_line_numbers = true};
|
||||
print_match(tty_out, &pr, m);
|
||||
// Print trailing context lines:
|
||||
print_match(tty_out, &pr, NULL);
|
||||
}
|
||||
|
||||
retry:
|
||||
fprintf(tty_out, "\033[1mReplace? (y)es (n)o (r)emaining (d)one\033[0m ");
|
||||
(void)fflush(tty_out);
|
||||
|
||||
char *answer = NULL;
|
||||
size_t len = 0;
|
||||
if (getline(&answer, &len, tty_in) > 0) {
|
||||
if (strlen(answer) > 2) goto retry;
|
||||
switch (answer[0]) {
|
||||
case 'y': case '\n': break;
|
||||
case 'n': m->skip_replacement = 1; break;
|
||||
case 'r': *confirm = CONFIRM_ALL; break;
|
||||
case 'd': m->skip_replacement = 1; *confirm = CONFIRM_NONE; break;
|
||||
default: goto retry;
|
||||
}
|
||||
}
|
||||
if (answer) delete(&answer);
|
||||
fprintf(tty_out, "\n");
|
||||
}
|
||||
|
||||
check_children:
|
||||
for (int i = 0; m->children && m->children[i]; i++)
|
||||
confirm_replacements(f, m->children[i], confirm);
|
||||
}
|
||||
|
||||
//
|
||||
// Replace a file's contents with the text version of a match.
|
||||
// (Useful for replacements)
|
||||
@ -306,7 +242,6 @@ static int inplace_modify_file(def_t *defs, file_t *f, pat_t *pattern)
|
||||
|
||||
FILE *dest = NULL; // Lazy-open this on the first match
|
||||
int matches = 0;
|
||||
confirm_t confirm_file = options.confirm;
|
||||
match_t *m = NULL;
|
||||
while ((m = next_match(defs, f, m, pattern, options.skip, options.ignorecase))) {
|
||||
++matches;
|
||||
@ -317,10 +252,7 @@ static int inplace_modify_file(def_t *defs, file_t *f, pat_t *pattern)
|
||||
dest = check_nonnull(fopen(f->filename, "w"), "Failed to open %s for modification", f->filename);
|
||||
backup_file = f;
|
||||
modifying_file = dest;
|
||||
if (options.confirm == CONFIRM_ASK && f->filename)
|
||||
fprint_filename(tty_out, f->filename);
|
||||
}
|
||||
confirm_replacements(f, m, &confirm_file);
|
||||
print_match(dest, &pr, m);
|
||||
}
|
||||
if (m) recycle_if_unused(&m);
|
||||
@ -328,8 +260,6 @@ static int inplace_modify_file(def_t *defs, file_t *f, pat_t *pattern)
|
||||
if (dest) {
|
||||
// Print trailing context lines:
|
||||
print_match(dest, &pr, NULL);
|
||||
if (options.confirm == CONFIRM_ALL)
|
||||
printf("%s\n", f->filename);
|
||||
(void)fclose(dest);
|
||||
if (modifying_file == dest) modifying_file = NULL;
|
||||
if (backup_file == f) backup_file = NULL;
|
||||
@ -528,8 +458,6 @@ int main(int argc, char *argv[])
|
||||
options.mode = MODE_JSON;
|
||||
} else if (BOOLFLAG("-I") || BOOLFLAG("--inplace")) {
|
||||
options.mode = MODE_INPLACE;
|
||||
} else if (BOOLFLAG("-c") || BOOLFLAG("--confirm")) {
|
||||
options.confirm = CONFIRM_ASK;
|
||||
} else if (BOOLFLAG("-G") || BOOLFLAG("--git")) {
|
||||
options.git_mode = true;
|
||||
} else if (BOOLFLAG("-i") || BOOLFLAG("--ignore-case")) {
|
||||
@ -560,6 +488,7 @@ int main(int argc, char *argv[])
|
||||
file_t *arg_file = spoof_file(&loaded_files, "<pattern argument>", flag, -1);
|
||||
pat_t *p = bp_pattern(arg_file, arg_file->start);
|
||||
if (!p) file_err(arg_file, arg_file->start, arg_file->end, "Failed to compile this part of the argument");
|
||||
if (after_spaces(p->end, true) < arg_file->end) file_err(arg_file, p->end, arg_file->end, "Failed to compile this part of the argument");
|
||||
pattern = chain_together(arg_file, pattern, p);
|
||||
} else if (FLAG("-w") || FLAG("--word")) {
|
||||
check_nonnegative(asprintf(&flag, "\\|%s\\|", flag), "Could not allocate memory");
|
||||
@ -604,9 +533,6 @@ int main(int argc, char *argv[])
|
||||
if (pattern == NULL)
|
||||
errx(EXIT_FAILURE, "No pattern provided.\n\n%s", usage);
|
||||
|
||||
if (options.confirm == CONFIRM_ASK && options.mode != MODE_INPLACE)
|
||||
errx(EXIT_FAILURE, "Confirm mode (-C flag) can only be used with inplace mode (-I flag)");
|
||||
|
||||
for (argc = 0; argv[argc]; ++argc) ; // update argc
|
||||
|
||||
if (options.context_before == USE_DEFAULT_CONTEXT) options.context_before = 0;
|
||||
@ -625,13 +551,6 @@ int main(int argc, char *argv[])
|
||||
// Handle exit() calls gracefully:
|
||||
check_nonnegative(atexit(&cleanup), "Failed to set cleanup handler at exit");
|
||||
|
||||
// User input/output is handled through /dev/tty so that normal unix pipes
|
||||
// can work properly while simultaneously asking for user input.
|
||||
if (options.confirm == CONFIRM_ASK) {
|
||||
tty_in = fopen("/dev/tty", "r");
|
||||
tty_out = fopen("/dev/tty", "w");
|
||||
}
|
||||
|
||||
// No need for these caches anymore:
|
||||
for (file_t *f = loaded_files; f; f = f->next)
|
||||
cache_destroy(f);
|
||||
@ -658,9 +577,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
if (options.mode == MODE_JSON) printf("]\n");
|
||||
|
||||
if (tty_out) { (void)fclose(tty_out); tty_out = NULL; }
|
||||
if (tty_in) { (void)fclose(tty_in); tty_in = NULL; }
|
||||
|
||||
// This code frees up all residual heap-allocated memory. Since the program
|
||||
// is about to exit, this step is unnecessary. However, it is useful for
|
||||
// tracking down memory leaks.
|
||||
|
4
print.c
4
print.c
@ -110,10 +110,6 @@ static void _print_match(FILE *out, printer_t *pr, match_t *m)
|
||||
{
|
||||
pr->pos = m->start;
|
||||
if (m->pat->type == BP_REPLACE) {
|
||||
if (m->skip_replacement) {
|
||||
_print_match(out, pr, m->children[0]);
|
||||
return;
|
||||
}
|
||||
size_t line = get_line_number(pr->file, m->start);
|
||||
size_t line_end = get_line_number(pr->file, m->end);
|
||||
|
||||
|
5
types.h
5
types.h
@ -114,11 +114,6 @@ typedef struct match_s {
|
||||
match_dll_t gc, cache;
|
||||
size_t defs_id;
|
||||
int refcount;
|
||||
// If skip_replacement is set to 1, that means the user wants to not print
|
||||
// the replaced text when printing this match:
|
||||
// TODO: this is a bit hacky, there is probably a better way to go about
|
||||
// this but it's less hacky that mutating the match objects more drastically
|
||||
bool skip_replacement:1;
|
||||
struct match_s **children;
|
||||
struct match_s *_children[3];
|
||||
} match_t;
|
||||
|
Loading…
Reference in New Issue
Block a user