diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2021-01-17 09:21:58 -0800 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2021-01-17 09:21:58 -0800 |
| commit | 58af933f4e70e2b85b11ca05c799fce226ed1821 (patch) | |
| tree | f3043d1aec783ed74cf494c9b2d371f197a2a674 | |
| parent | 05b9b0ff9775bf5e63c1cc018f57f6a9ff910a58 (diff) | |
Added --git/-G
| -rw-r--r-- | README.md | 5 | ||||
| -rw-r--r-- | bp.1 | 5 | ||||
| -rw-r--r-- | bp.c | 39 |
3 files changed, 45 insertions, 4 deletions
@@ -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. @@ -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. @@ -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); |
