Added --git/-G

This commit is contained in:
Bruce Hill 2021-01-17 09:21:58 -08:00
parent 05b9b0ff97
commit 58af933f4e
3 changed files with 45 additions and 4 deletions

View File

@ -17,9 +17,10 @@ It's written in pure C with no dependencies.
* `-l` `--list-files` print only filenames containing matches
* `-p` `--pattern <pat>` provide a pattern (equivalent to `bp '\(<pat>)'`)
* `-P` `--pattern-string <pat>` provide a string pattern (equivalent to `bp '<pat>'`, but may be useful if `'<pat>'` begins with a '-')
* `-r` `--replace <replacement>` replace the input pattern with the given replacement
* `-r` `--replace <replacement>` replace the input pattern with the given replacement
* `-c` `--context <N>` change how many lines of context are printed (`0`: no context, `all`: the whole file, `<N>` matching lines and `<N-1>` lines before/after)
* `-g` `--grammar <grammar file>` use the specified file as a grammar
* `-g` `--grammar <grammar file>` use the specified file as a grammar
* `-G` `--git` get filenames from git
See `man ./bp.1` for more details.

5
bp.1
View File

@ -17,6 +17,7 @@ bp \- Bruce's Parsing Expression Grammar tool
[\fI-P\fR|\fI--pattern-string\fR \fI<string-pattern>\fR]
[\fI-r\fR|\fI--replace\fR \fI<replacement>\fR]
[\fI-g\fR|\fI--grammar\fR \fI<grammar file>\fR]
[\fI-G\fR|\fI--git\fR]
[\fI-c\fR|\fI--conntext\fR \fI<N>\fR]
\fI<pattern\fR
[[--] \fI<input files...>\fR]
@ -50,6 +51,10 @@ Replace all occurrences of the main pattern with the given string.
.B \-g\fR, \fB--grammar \fI<grammar file>\fR
Load the grammar from the given file.
.B \-G\fR, \fB--git\fR
Use \fBgit\fR to get a list of files. Remaining file arguments (if any) are
passed to \fBgit --ls-files\fR instead of treated as literal files.
.B \-c\fR, \fB--context \fI<N>\fR
The number of lines of context to print. If \fI<N>\fR is 0, print only the
exact text of the matches. If \fI<N>\fR is "all", print the entire file.

39
bp.c
View File

@ -10,6 +10,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "definitions.h"
@ -379,8 +381,8 @@ int main(int argc, char *argv[])
file_t *local_file = load_file(&loaded_files, "%s/.config/"BP_NAME"/builtins.bp", getenv("HOME"));
if (local_file) defs = load_grammar(defs, local_file);
int i, npatterns = 0;
check(argc > 1, "%s", usage);
int i, npatterns = 0, git = 0;
for (i = 1; i < argc; i++) {
if (streq(argv[i], "--")) {
++i;
@ -399,6 +401,8 @@ int main(int argc, char *argv[])
mode = MODE_INPLACE;
} else if (streq(argv[i], "--confirm")) {
confirm = CONFIRM_ASK;
} else if (streq(argv[i], "--git")) {
git = 1;
} else if (streq(argv[i], "--ignore-case")) {
ignorecase = 1;
} else if (streq(argv[i], "--list-files")) {
@ -460,6 +464,7 @@ int main(int argc, char *argv[])
switch (*c) {
case 'h': goto flag_help; // -h
case 'v': verbose = 1; break; // -v
case 'G': git = 1; break; // -G
case 'e': mode = MODE_EXPLAIN; break; // -e
case 'j': mode = MODE_JSON; break; // -j
case 'I': mode = MODE_INPLACE; break; // -I
@ -512,7 +517,37 @@ int main(int argc, char *argv[])
int found = 0;
if (mode == MODE_JSON) printf("[");
if (i < argc) {
if (git) {
int fds[2];
check(pipe(fds) == 0, "Failed to create pipe");
pid_t child = fork();
check(child != -1, "Failed to fork");
if (child == 0) {
char **git_args = calloc((size_t)(2+(argc-i)+1), sizeof(char*));
int g = 0;
git_args[g++] = "git";
git_args[g++] = "ls-files";
while (i < argc) git_args[g++] = argv[i++];
dup2(fds[STDOUT_FILENO], STDOUT_FILENO);
close(fds[STDIN_FILENO]);
execvp("git", git_args);
_exit(1);
}
close(fds[STDOUT_FILENO]);
char path[PATH_MAX+2] = {0}; // path + \n + \0
while (read(fds[STDIN_FILENO], path, PATH_MAX+1) > 0) { // Iterate over chunks
for (char *nl; (nl = strchr(path, '\n')); ) { // Iterate over nl-terminated lines
*nl = '\0';
found += process_file(defs, path, pattern);
memmove(path, nl+1, sizeof(path)-(size_t)(nl+1-path));
}
}
close(fds[STDIN_FILENO]);
int status;
waitpid(child, &status, 0);
check(WIFEXITED(status) && WEXITSTATUS(status) == 0,
"`git --ls-files` failed. Do you have git installed?");
} else if (i < argc) {
// Files pass in as command line args:
for (int nfiles = 0; i < argc; nfiles++, i++) {
found += process_file(defs, argv[i], pattern);