aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bp.129
-rw-r--r--bp.1.md3
-rw-r--r--bp.c23
3 files changed, 54 insertions, 1 deletions
diff --git a/bp.1 b/bp.1
index 1e7f46e..5f1a01c 100644
--- a/bp.1
+++ b/bp.1
@@ -1,12 +1,30 @@
-.\" Automatically generated by Pandoc 3.1.8
+.\" Automatically generated by Pandoc 3.1.6
.\"
+.\" Define V font for inline verbatim, using C font in formats
+.\" that render this, and otherwise B font.
+.ie "\f[CB]x\f[]"x" \{\
+. ftr V B
+. ftr VI BI
+. ftr VB B
+. ftr VBI BI
+.\}
+.el \{\
+. ftr V CR
+. ftr VI CI
+. ftr VB CB
+. ftr VBI CBI
+.\}
.TH "BP" "1" "May 17 2021" "" ""
+.hy
.SH NAME
+.PP
bp - Bruce\[aq]s Parsing Expression Grammar tool
.SH SYNOPSIS
+.PP
\f[B]bp\f[R] [\f[I]options\&...\f[R]] \f[I]pattern\f[R] [[\f[B]--\f[R]]
\f[I]files\&...\f[R]]
.SH DESCRIPTION
+.PP
\f[B]bp\f[R] is a tool that matches parsing expression grammars using a
custom syntax.
.SH OPTIONS
@@ -32,6 +50,11 @@ Print a JSON list of the matches.
Print only the names of files containing matches instead of the matches
themselves.
.TP
+\f[B]-c\f[R], \f[B]--case\f[R]
+Perform pattern matching with case-sensitivity (the default is smart
+casing, i.e.\ case-insensitive, unless there are any uppercase letters
+present).
+.TP
\f[B]-i\f[R], \f[B]--ignore-case\f[R]
Perform pattern matching case-insensitively.
.TP
@@ -92,6 +115,7 @@ used instead.
If neither are provided, \f[B]bp\f[R] will search through all files in
the current directory and its subdirectories (recursively).
.SH STRING PATTERNS
+.PP
One of the most common use cases for pattern matching tools is matching
plain, literal strings, or strings that are primarily plain strings,
with one or two patterns.
@@ -108,6 +132,7 @@ character literal: \f[B]{\[ga]{}\f[R], the string literal:
\f[B]{\[dq]{\[dq]}\f[R], or a pair of matching curly braces using the
\f[B]braces\f[R] rule: \f[B]{braces}\f[R].
.SH PATTERNS
+.PP
\f[B]bp\f[R] patterns are based off of a combination of Parsing
Expression Grammars and regular expression syntax.
The syntax is designed to map closely to verbal descriptions of the
@@ -352,6 +377,7 @@ that also attaches a metadata tag of the same name)
\f[B]#\f[R] \f[I]comment\f[R]
A line comment, ignored by BP
.SH GRAMMAR FILES
+.PP
\f[B]bp\f[R] allows loading extra grammar files, which define patterns
which may be used for matching.
The \f[B]builtins\f[R] grammar file is loaded by default, and it defines
@@ -404,6 +430,7 @@ following command:
\f[B]bp -g c++ \[aq]{comment \[ti] \[dq]TODO\[dq]}\[aq] *.cpp\f[R]
.RE
.SH EXAMPLES
+.PP
Find files containing the literal string \[lq]foo.baz\[rq] (a string
pattern):
.RS
diff --git a/bp.1.md b/bp.1.md
index 97f12f4..7679936 100644
--- a/bp.1.md
+++ b/bp.1.md
@@ -34,6 +34,9 @@ syntax.
: Print only the names of files containing matches instead of the matches
themselves.
+`-c`, `--case`
+: Perform pattern matching with case-sensitivity (the default is smart casing, i.e. case-insensitive, unless there are any uppercase letters present).
+
`-i`, `--ignore-case`
: Perform pattern matching case-insensitively.
diff --git a/bp.c b/bp.c
index dce1d4a..68c07d0 100644
--- a/bp.c
+++ b/bp.c
@@ -40,6 +40,7 @@ static const char *usage = (
" -v --verbose print verbose debugging info\n"
" -e --explain explain the matches\n"
" -j --json print matches as a list of JSON objects\n"
+ " -c --case use case sensitivity\n"
" -i --ignore-case preform matching case-insensitively\n"
" -I --inplace modify a file in-place\n"
" -l --list-files list filenames only\n"
@@ -538,6 +539,18 @@ static int context_from_flag(const char *flag)
return (int)strtol(flag, NULL, 10);
}
+//
+// Check if any letters are uppercase
+//
+static bool any_uppercase(const char *str)
+{
+ for (; *str; ++str) {
+ if (isupper(*str))
+ return true;
+ }
+ return false;
+}
+
#define FLAG(f) (flag = get_flag(argv, f, &argv))
#define BOOLFLAG(f) get_boolflag(argv, f, &argv)
@@ -555,6 +568,8 @@ int main(int argc, char *argv[])
file_t *local_file = load_filef(&loaded_files, "%s/.config/"BP_NAME"/builtins.bp", getenv("HOME"));
if (local_file) defs = load_grammar(defs, local_file);
+ bool explicit_case_sensitivity = false;
+
++argv; // skip program name
while (argv[0]) {
if (streq(argv[0], "--")) {
@@ -577,6 +592,10 @@ int main(int argc, char *argv[])
options.git_mode = true;
} else if (BOOLFLAG("-i") || BOOLFLAG("--ignore-case")) {
options.ignorecase = true;
+ explicit_case_sensitivity = true;
+ } else if (BOOLFLAG("-c") || BOOLFLAG("--case")) {
+ options.ignorecase = false;
+ explicit_case_sensitivity = true;
} else if (BOOLFLAG("-l") || BOOLFLAG("--list-files")) {
options.mode = MODE_LISTFILES;
} else if (FLAG("-r") || FLAG("--replace")) {
@@ -601,6 +620,8 @@ int main(int argc, char *argv[])
} else if (FLAG("-w") || FLAG("--word")) {
require(asprintf(&flag, "{|}%s{|}", flag), "Could not allocate memory");
file_t *arg_file = spoof_file(&loaded_files, "<word pattern>", flag, -1);
+ if (!explicit_case_sensitivity)
+ options.ignorecase = !any_uppercase(flag);
delete(&flag);
pat_t *p = assert_pat(arg_file->start, arg_file->end, bp_stringpattern(arg_file->start, arg_file->end));
pattern = chain_together(pattern, p);
@@ -627,6 +648,8 @@ int main(int argc, char *argv[])
} else if (argv[0][0] != '-') {
if (pattern != NULL) break;
pat_t *p = assert_pat(argv[0], NULL, bp_stringpattern(argv[0], argv[0]+strlen(argv[0])));
+ if (!explicit_case_sensitivity)
+ options.ignorecase = !any_uppercase(argv[0]);
pattern = chain_together(pattern, p);
++argv;
} else {