201221.1 · 214138a44870c64c2926b059b7323f648bbe1e53
released 3.1.1
reading declarations
@@ -4601,7 +4601,7 @@ in markdown: - ugrep 3.1.0 December 14, 2020 UGREP(1)+ ugrep 3.1.1 December 21, 2020 UGREP(1) 🔝 [Back to table of contents](#toc)
@@ -1,4 +1,4 @@-.TH UGREP "1" "December 14, 2020" "ugrep 3.1.0" "User Commands"+.TH UGREP "1" "December 21, 2020" "ugrep 3.1.1" "User Commands" .SH NAME \fBugrep\fR, \fBug\fR -- file pattern searcher .SH SYNOPSIS
@@ -252,14 +252,21 @@ class CNF { // anchor a pattern, when specified with -w or -x static void anchor(std::string& pattern) {+ // -G requires \( \) instead of ( )+ const char *xleft = flag_basic_regexp ? "^\\(" : "^(";+ const char *xright = flag_basic_regexp ? "\\)$" : ")$";+ const char *wleft = flag_basic_regexp ? "\\<\\(" : "\\<(";+ const char *wright = flag_basic_regexp ? "\\)\\>" : ")\\>";++ // patterns that start with ^ or end with $ are already anchored if (!pattern.empty() && (pattern.front() == '^' || pattern.back() == '$')) { if (!flag_line_regexp && flag_word_regexp) { if (pattern.front() != '^')- pattern.insert(0, "\\<(");+ pattern.insert(0, wleft); else if (pattern.back() != '$')- pattern.append(")\\>");+ pattern.append(wright); } // enable -Y to match empty@@ -268,14 +275,14 @@ class CNF { else if (flag_line_regexp) { if (!pattern.empty())- pattern.insert(0, "^(").append(")$");+ pattern.insert(0, xleft).append(xright); else pattern.assign("^$"); } else if (flag_word_regexp) { if (!pattern.empty())- pattern.insert(0, "\\<(").append(")\\>");+ pattern.insert(0, wleft).append(wright); } }
@@ -814,7 +814,7 @@ void Output::format(const char *format, const char *pathname, const std::string& } } -// output formatted match with options --format, --format-open, --format-close+// output formatted match with options -v --format void Output::format_invert(const char *format, const char *pathname, const std::string& partname, size_t matches, size_t lineno, size_t offset, const char *ptr, size_t size, bool next) { size_t len = 0;
@@ -400,6 +400,7 @@ void Query::draw() } } +// view one row of text by drawing it on screen void Query::view(int row) { Screen::normal();
@@ -46,6 +46,9 @@ // max collective length of ANSI CSI escape sequences collected when skipping lead text with skip>0 #define SCREEN_MAX_CODELEN 256 +// enable to interpret backspace (CTRL-H), not recommended because search results may not match what is shown+// #define WITH_BACKSPACE+ // emit ANSI SGR CSI sequence with one numeric parameter void Screen::CSI(int code, int num) {@@ -513,6 +516,13 @@ void Screen::put(int row, int col, const char *text, size_t size, int skip, int ++text; break; +#ifdef WITH_BACKSPACE+ case '\b':+ ++num;+ ++text;+ break;+#endif+ case '\t': num -= 1 + (~(cols - num) & 7); ++text;@@ -554,7 +564,7 @@ void Screen::put(int row, int col, const char *text, size_t size, int skip, int num -= width; if (num < 0) {- // cut a double wide character in half?+ // cut a double wide character that does not fit in half if (width == 2 && num == -1) { put(' ');@@ -587,6 +597,20 @@ void Screen::put(int row, int col, const char *text, size_t size, int skip, int { int tab; +#ifdef WITH_BACKSPACE+ case '\b':+ if (ptr > text)+ {+ const char *p = ptr;+ while (p > text && (*--p & 0xc0) == 0x80)+ continue;+ put(text, p - text);+ ++len;+ }+ text = ++ptr;+ break;+#endif+ case '\t': put(text, ptr - text); tab = 1 + (~(cols - len) & 7);@@ -693,6 +717,7 @@ void Screen::put(int row, int col, const char *text, size_t size, int skip, int } else if (wc <= 0x1f) {+ // display CTRL character put(text, ptr - text); if (*ptr == '\0' && nulls > 0) {@@ -710,6 +735,7 @@ void Screen::put(int row, int col, const char *text, size_t size, int skip, int } else if (wc == 0x7f) {+ // display control character 0x7f put(text, ptr - text); invert(); put("^?", 2);
@@ -67,7 +67,7 @@ After this, you may want to test ugrep and install it (optional): */ // ugrep version-#define UGREP_VERSION "3.1.0"+#define UGREP_VERSION "3.1.1" // disable mmap because mmap is almost always slower than the file reading speed improvements since 3.0.0 #define WITH_NO_MMAP@@ -6033,11 +6033,17 @@ void ugrep() // remove the ending '|' from the |-concatenated regexes in the regex string regex.pop_back(); + // -G requires \( \) instead of ( )+ const char *xleft = flag_basic_regexp ? "^\\(" : "^(";+ const char *xright = flag_basic_regexp ? "\\)$" : ")$";+ const char *wleft = flag_basic_regexp ? "\\<\\(" : "\\<(";+ const char *wright = flag_basic_regexp ? "\\)\\>" : ")\\>";+ // -x or -w: if no PATTERN is specified, then apply -x or -w to -f FILE patterns if (line_regexp)- regex.insert(0, "^(").append(")$"); // make the regex line-anchored+ regex.insert(0, xleft).append(xright); // make the regex line-anchored else if (word_regexp)- regex.insert(0, "\\<(").append(")\\>"); // make the regex word-anchored+ regex.insert(0, wleft).append(wright); // make the regex word-anchored } // --match: adjust color highlighting to show matches as selected lines without color
@@ -102,8 +102,12 @@ for PAT in '' 'Hello' '\w+\s+\S+' '\S\n\S' 'nomatch' ; do $UG -U -Fx "$PAT" Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt > "out/$FN-Fx.out" if [ "$PAT" == '\w+\s+\S+' ]; then $UG -U -G '\w\+\s\+\S\+' Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt > "out/$FN-G.out"+ $UG -U -Gw '\w\+\s\+\S\+' Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt > "out/$FN-Gw.out"+ $UG -U -Gx '\w\+\s\+\S\+' Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt > "out/$FN-Gx.out" else $UG -U -G "$PAT" Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt > "out/$FN-G.out"+ $UG -U -Gw "$PAT" Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt > "out/$FN-Gw.out"+ $UG -U -Gx "$PAT" Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt > "out/$FN-Gx.out" fi $UG -U -IP "$PAT" Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt > "out/$FN-IP.out" $UG -U -IPw "$PAT" Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt > "out/$FN-IPw.out"
@@ -0,0 +1,15 @@+[1;35mHello.bat[m[1;36m:[m[m#!/bin/sh[m+[1;35mHello.bat[m[1;36m:[m[mecho "Hello World!"[m+[mBinary file[1;35m Hello.class[m matches+[1;35mHello.java[m[1;36m:[m[mimport java.lang.*;[m+[1;35mHello.java[m[1;36m:[m[m[m+[1;35mHello.java[m[1;36m:[m[mpublic class Hello // prints a Hello World! greeting[m+[1;35mHello.java[m[1;36m:[m[m{ public static void main(String[] arg)[m+[1;35mHello.java[m[1;36m:[m[m { System.out.println("Hello World!");[m+[1;35mHello.java[m[1;36m:[m[m }[m+[1;35mHello.java[m[1;36m:[m[m}[m+[1;35mHello.pdf[m[1;36m:[m[m%PDF-1.3[m+[mBinary file[1;35m Hello.pdf[m matches+[1;35mHello.sh[m[1;36m:[m[m#!/bin/sh[m+[1;35mHello.sh[m[1;36m:[m[mecho "Hello World!"[m+[1;35mHello.txt[m[1;36m:[m[mHello[m
@@ -0,0 +1 @@+[1;35mHello.java[m[1;36m:[m[m[1;4;32m[m
@@ -0,0 +1,7 @@+[1;35mHello.bat[m[1;36m:[mecho "[m[1;4;32mHello[m World!"[m+[mBinary file[1;35m Hello.class[m matches+[1;35mHello.java[m[1;36m:[mpublic class [m[1;4;32mHello[m // prints a [m[1;4;32mHello[m World! greeting[m+[1;35mHello.java[m[1;36m:[m { System.out.println("[m[1;4;32mHello[m World!");[m+[1;35mHello.pdf[m[1;36m:[m([m[1;4;32mHello[m)[m+[1;35mHello.sh[m[1;36m:[mecho "[m[1;4;32mHello[m World!"[m+[1;35mHello.txt[m[1;36m:[m[m[1;4;32mHello[m
@@ -0,0 +1 @@+[1;35mHello.txt[m[1;36m:[m[m[1;4;32mHello[m
@@ -0,0 +1 @@+[mBinary file[1;35m Hello.pdf[m matches
tests/out/Hello_nomatch-Gw.out
tests/out/Hello_nomatch-Gx.out
tests/out/Hello_wsS-Gw.out
@@ -0,0 +1,12 @@+[1;35mHello.bat[m[1;36m:[m#!/bin/[m[1;4;32msh[m+[1;35mHello.bat[m[1;36m|[m[1;4;32mecho[m "[m[1;4;32mHello World[m!"[m+[mBinary file[1;35m Hello.class[m matches+[1;35mHello.java[m[1;36m:[m[m[1;4;32mimport java.lang[m.*;[m+[1;35mHello.java[m[1;36m:[m[m[1;4;32mpublic class[m Hello // [m[1;4;32mprints a[m [m[1;4;32mHello World[m! greeting[m+[1;35mHello.java[m[1;36m:[m{ [m[1;4;32mpublic static[m [m[1;4;32mvoid main(String[m[] arg)[m+[1;35mHello.java[m[1;36m:[m { System.out.println("[m[1;4;32mHello World[m!");[m+[1;35mHello.pdf[m[1;36m:[m[m[1;4;32m4 0[m obj[m+[1;35mHello.pdf[m[1;36m:[m<< /[m[1;4;32mLength 5[m [m[1;4;32m0 R[m /[m[1;4;32mFilter /FlateDecode[m >>[m+[mBinary file[1;35m Hello.pdf[m matches+[1;35mHello.sh[m[1;36m:[m#!/bin/[m[1;4;32msh[m+[1;35mHello.sh[m[1;36m|[m[1;4;32mecho[m "[m[1;4;32mHello World[m!"[m
tests/out/Hello_wsS-Gx.out
@@ -0,0 +1,2 @@+[1;35mHello.java[m[1;36m:[m[m[1;4;32mimport java.lang.*;[m+[mBinary file[1;35m Hello.pdf[m matches
@@ -217,10 +217,22 @@ for PAT in '' 'Hello' '\w+\s+\S+' '\S\n\S' 'nomatch' ; do $UG -U -G '\w\+\s\+\S\+' Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt \ | $DIFF "out/$FN-G.out" \ || ERR "-G '$PAT' Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt"+ $UG -U -Gw '\w\+\s\+\S\+' Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt \+ | $DIFF "out/$FN-Gw.out" \+ || ERR "-Gw '$PAT' Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt"+ $UG -U -Gx '\w\+\s\+\S\+' Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt \+ | $DIFF "out/$FN-Gx.out" \+ || ERR "-Gx '$PAT' Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt" else $UG -U -G "$PAT" Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt \ | $DIFF "out/$FN-G.out" \ || ERR "-G '$PAT' Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt"+ $UG -U -Gw "$PAT" Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt \+ | $DIFF "out/$FN-Gw.out" \+ || ERR "-Gw '$PAT' Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt"+ $UG -U -Gx "$PAT" Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt \+ | $DIFF "out/$FN-Gx.out" \+ || ERR "-Gx '$PAT' Hello.bat Hello.class Hello.java Hello.pdf Hello.sh Hello.txt" fi if [ "$have_pcre2" == yes ] || [ "$have_boost_regex" == yes ]; then printf .