230609.4 · ee85b713aa84e0050a3b36030000778ccfd4882f
Renamed executable from hg to hgrep (to avoid Mercurial conflict)
reading declarations
@@ -37,7 +37,7 @@ message(STATUS ${HYPERSCAN_LIBRARY}) # ————————————————————————————— # create target for main binary # —————————————————————————————-add_executable(hg+add_executable(hgrep src/compiler.cpp src/cpu_features.cpp src/is_binary.cpp@@ -51,9 +51,9 @@ add_executable(hg src/search_options.cpp src/size_to_bytes.cpp src/trim_whitespace.cpp)-target_compile_features(hg PUBLIC cxx_std_17)-target_include_directories(hg PRIVATE include)-target_link_libraries(hg PRIVATE+target_compile_features(hgrep PUBLIC cxx_std_17)+target_include_directories(hgrep PRIVATE include)+target_link_libraries(hgrep PRIVATE argparse::argparse unofficial::concurrentqueue::concurrentqueue unofficial::git2::libgit2package@@ -61,5 +61,5 @@ target_link_libraries(hg PRIVATE ${HYPERSCAN_LIBRARY} ) -install(TARGETS hg+install(TARGETS hgrep DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
@@ -53,13 +53,13 @@ The following tests compare the performance of `hypergrep` against: | Regex | Line Count | ag | ugrep | ripgrep | hypergrep | | :---| ---:| ---:| ---:| ---:| ---:|-| Count number of times Holmes did something<br/>`hg -c 'Holmes did \w'` | 27 | n/a | 1.820 | 1.022 | **0.696** |-| Literal with Regex Suffix<br/>`hg -nw 'Sherlock [A-Z]\w+' en.txt` | 7882 | n/a | 1.812 | 1.509 | **0.803** |-| Simple Literal<br/>`hg -nw 'Sherlock Holmes' en.txt` | 7653 | 15.764 | 1.888 | 1.524 | **0.658** |-| Simple Literal (case insensitive)<br/>`hg -inw 'Sherlock Holmes' en.txt` | 7871 | 15.599 | 6.945 | 2.162 | **0.650** |-| Alternation of Literals<br/>`hg -n 'Sherlock Holmes\|John Watson\|Irene Adler\|Inspector Lestrade\|Professor Moriarty' en.txt` | 10078 | n/a | 6.886 | 1.836 | **0.689** |-| Alternation of Literals (case insensitive)<br/>`hg -in 'Sherlock Holmes\|John Watson\|Irene Adler\|Inspector Lestrade\|Professor Moriarty' en.txt` | 10333 | n/a | 7.029 | 3.940 | **0.770** |-| Words surrounding a literal string<br/>`hg -n '\w+[\x20]+Holmes[\x20]+\w+' en.txt` | 5020 | n/a | 6m 11s | 1.523 | **0.638** |+| Count number of times Holmes did something<br/>`hgrep -c 'Holmes did \w'` | 27 | n/a | 1.820 | 1.022 | **0.696** |+| Literal with Regex Suffix<br/>`hgrep -nw 'Sherlock [A-Z]\w+' en.txt` | 7882 | n/a | 1.812 | 1.509 | **0.803** |+| Simple Literal<br/>`hgrep -nw 'Sherlock Holmes' en.txt` | 7653 | 15.764 | 1.888 | 1.524 | **0.658** |+| Simple Literal (case insensitive)<br/>`hgrep -inw 'Sherlock Holmes' en.txt` | 7871 | 15.599 | 6.945 | 2.162 | **0.650** |+| Alternation of Literals<br/>`hgrep -n 'Sherlock Holmes\|John Watson\|Irene Adler\|Inspector Lestrade\|Professor Moriarty' en.txt` | 10078 | n/a | 6.886 | 1.836 | **0.689** |+| Alternation of Literals (case insensitive)<br/>`hgrep -in 'Sherlock Holmes\|John Watson\|Irene Adler\|Inspector Lestrade\|Professor Moriarty' en.txt` | 10333 | n/a | 7.029 | 3.940 | **0.770** |+| Words surrounding a literal string<br/>`hgrep -n '\w+[\x20]+Holmes[\x20]+\w+' en.txt` | 5020 | n/a | 6m 11s | 1.523 | **0.638** | ### Git Repository Search: `torvalds/linux` @@ -67,11 +67,11 @@ The following searches are performed on the entire [Linux kernel source tree](ht | Regex | Line Count | ag | ugrep | ripgrep | hypergrep | | :---| ---:| ---:| ---:| ---:| ---:|-| Simple Literal<br/>`hg -nw 'PM_RESUME'` | 9 | 2.807 | 0.316 | 0.147 | 0.140 |-| Simple Literal (case insensitive)<br/>`hg -niw 'PM_RESUME'` | 39 | 2.904 | 0.435 | 0.149 | 0.141 |-| Regex with Literal Suffix<br/>`hg -nw '[A-Z]+_SUSPEND'` | 536 | 3.080 | 1.452 | 0.148 | 0.143 |-| Alternation of four literals<br/>`hg -nw '(ERR_SYS\|PME_TURN_OFF\|LINK_REQ_RST\|CFG_BME_EVT)'` | 16 | 3.085 | 0.410 | 0.153 | 0.146 |-| Unicode Greek<br/>`hg -n '\p{Greek}'` | 111 | 3.762 | 0.484 | 0.345 | **0.146** |+| Simple Literal<br/>`hgrep -nw 'PM_RESUME'` | 9 | 2.807 | 0.316 | 0.147 | 0.140 |+| Simple Literal (case insensitive)<br/>`hgrep -niw 'PM_RESUME'` | 39 | 2.904 | 0.435 | 0.149 | 0.141 |+| Regex with Literal Suffix<br/>`hgrep -nw '[A-Z]+_SUSPEND'` | 536 | 3.080 | 1.452 | 0.148 | 0.143 |+| Alternation of four literals<br/>`hgrep -nw '(ERR_SYS\|PME_TURN_OFF\|LINK_REQ_RST\|CFG_BME_EVT)'` | 16 | 3.085 | 0.410 | 0.153 | 0.146 |+| Unicode Greek<br/>`hgrep -n '\p{Greek}'` | 111 | 3.762 | 0.484 | 0.345 | **0.146** | ### Git Repository Search: `apple/swift` @@ -79,10 +79,10 @@ The following searches are performed on the entire [Apple Swift source tree](htt | Regex | Line Count | ag | ugrep | ripgrep | hypergrep | | :---| ---:| ---:| ---:| ---:| ---:|-| Function/Struct/Enum declaration followed by a valid identifier and opening parenthesis<br/>`hg -n '(func\|struct\|enum)\s+[A-Za-z_][A-Za-z0-9_]*\s*\('` | 59026 | 1.148 | 0.954 | 0.154 | **0.090** |-| Words starting with alphabetic characters followed by at least 2 digits<br/>`hg -nw '[A-Za-z]+\d{2,}'` | 127858 | 1.169 | 1.238 | 0.156 | **0.095** |-| Workd starting with Uppercase letter, followed by alpha-numeric chars and/or underscores <br/>`hg -nw '[A-Z][a-zA-Z0-9_]*'` | 2012372 | 3.131 | 2.598 | 0.550 | **0.482** |-| Guard let statement followed by valid identifier<br/>`hg -n 'guard\s+let\s+[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*\w+'` | 839 | 0.828 | 0.174 | 0.054 | 0.047 |+| Function/Struct/Enum declaration followed by a valid identifier and opening parenthesis<br/>`hgrep -n '(func\|struct\|enum)\s+[A-Za-z_][A-Za-z0-9_]*\s*\('` | 59026 | 1.148 | 0.954 | 0.154 | **0.090** |+| Words starting with alphabetic characters followed by at least 2 digits<br/>`hgrep -nw '[A-Za-z]+\d{2,}'` | 127858 | 1.169 | 1.238 | 0.156 | **0.095** |+| Workd starting with Uppercase letter, followed by alpha-numeric chars and/or underscores <br/>`hgrep -nw '[A-Z][a-zA-Z0-9_]*'` | 2012372 | 3.131 | 2.598 | 0.550 | **0.482** |+| Guard let statement followed by valid identifier<br/>`hgrep -n 'guard\s+let\s+[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*\w+'` | 839 | 0.828 | 0.174 | 0.054 | 0.047 | ### Directory Search: `/usr` @@ -90,12 +90,12 @@ The following searches are performed on the `/usr` directory. | Regex | Line Count | ag | ugrep | ripgrep | hypergrep | | :---| ---:| ---:| ---:| ---:| ---:|-| Any HTTPS or FTP URL<br/>`hg "(https?\|ftp)://[^\s/$.?#].[^\s]*"` | 13682 | 4.597 | 2.894 | 0.305 | **0.171** |-| Any IPv4 IP address<br/>`hg -w "(?:\d{1,3}\.){3}\d{1,3}"` | 12643 | 4.727 | 2.340 | 0.324 | **0.166** |-| Any E-mail address<br/>`hg -w "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}"` | 47509 | 5.477 | 37.209 | 0.494 | **0.220** |-| Any valid date `MM/DD/YYYY`<br/>`hg "(0[1-9]\|1[0-2])/(0[1-9]\|[12]\d\|3[01])/(19\|20)\d{2}"` | 116 | 4.239 | 1.827 | 0.251 | **0.163** |-| Count the number of HEX values<br/>`hg -cw "(?:0x)?[0-9A-Fa-f]+"` | 68042 | 5.765 | 28.691 | 1.439 | **0.611** |-| Search any C/C++ for a literal<br/>`hg --filter "\.(c\|cpp\|h\|hpp)$" test` | 7355 | n/a | 0.505 | 0.118 | **0.079** | +| Any HTTPS or FTP URL<br/>`hgrep "(https?\|ftp)://[^\s/$.?#].[^\s]*"` | 13682 | 4.597 | 2.894 | 0.305 | **0.171** |+| Any IPv4 IP address<br/>`hgrep -w "(?:\d{1,3}\.){3}\d{1,3}"` | 12643 | 4.727 | 2.340 | 0.324 | **0.166** |+| Any E-mail address<br/>`hgrep -w "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}"` | 47509 | 5.477 | 37.209 | 0.494 | **0.220** |+| Any valid date `MM/DD/YYYY`<br/>`hgrep "(0[1-9]\|1[0-2])/(0[1-9]\|[12]\d\|3[01])/(19\|20)\d{2}"` | 116 | 4.239 | 1.827 | 0.251 | **0.163** |+| Count the number of HEX values<br/>`hgrep -cw "(?:0x)?[0-9A-Fa-f]+"` | 68042 | 5.765 | 28.691 | 1.439 | **0.611** |+| Search any C/C++ for a literal<br/>`hgrep --filter "\.(c\|cpp\|h\|hpp)$" test` | 7355 | n/a | 0.505 | 0.118 | **0.079** | ## Build
@@ -219,7 +219,7 @@ Running in the `/usr` directory and searching for any shared library, here's the | --- | --- | --- | | `find . -name "*.so" \| wc -l` | 1851 | 0.293 | | `rg -g "*.so" --files \| wc -l` | 1621 | 0.082 |-| `hg --filter '\.so$' --files \| wc -l` | 1621 | **0.043** |+| `hgrep --filter '\.so$' --files \| wc -l` | 1621 | **0.043** | ### Negating the Filter @@ -254,7 +254,7 @@ NOTE in the following example: 1. `ls` command shows all the files and directories in the current path - Note the `build/` folder 2. `git ls-files` shows all the files in the git index and the working tree-3. `hg --files` output is very similar to `git ls-files` except that hidden files are ignored. +3. `hgrep --files` output is very similar to `git ls-files` except that hidden files are ignored. `hypergrep` prefers this approach of iterating the git index rather than loading the `.gitignore` file and checking every single file and subdirectory against a potentially long list of ignore rules. @@ -267,12 +267,12 @@ NOTE If you don't like that `hypergrep` treats git repositories differently, and # Usage ```bash-hg [OPTIONS] PATTERN [PATH ...]-hg [OPTIONS] -e PATTERN ... [PATH ...]-hg [OPTIONS] -f PATTERNFILE ... [PATH ...]-hg [OPTIONS] --files [PATH ...]-hg [OPTIONS] --help-hg [OPTIONS] --version+hgrep [OPTIONS] PATTERN [PATH ...]+hgrep [OPTIONS] -e PATTERN ... [PATH ...]+hgrep [OPTIONS] -f PATTERNFILE ... [PATH ...]+hgrep [OPTIONS] --files [PATH ...]+hgrep [OPTIONS] --help+hgrep [OPTIONS] --version ``` # Options@@ -283,10 +283,10 @@ hg [OPTIONS] --version | `--column` | Show column numbers (1-based). This only shows the column numbers for the first match on each line. | | `-c, --count` | This flag suppresses normal output and shows the number of lines that match the given pattern for each file searched | | `--count-matches` | This flag suppresses normal output and shows the number of individual matches of the given pattern for each file searched | -| `-e, --regexp <PATTERN>...` | A pattern to search for. This option can be provided multiple times, where all patterns given are searched. Lines matching at least one of the provided patterns are printed, e.g.,<br/><br/>`hg -e 'myFunctionCall' -e 'myErrorCallback'`<br/><br/>will search for any occurrence of either of the patterns. |+| `-e, --regexp <PATTERN>...` | A pattern to search for. This option can be provided multiple times, where all patterns given are searched. Lines matching at least one of the provided patterns are printed, e.g.,<br/><br/>`hgrep -e 'myFunctionCall' -e 'myErrorCallback'`<br/><br/>will search for any occurrence of either of the patterns. | | `-f, --files <PATTERNFILE>...` | Search for patterns from the given file, with one pattern per line. When this flag is used multiple times or in combination with the `-e/---regexp` flag, then all patterns provided are searched. | | `--files` | Print each file that would be searched without actually performing the search |-| `--filter <FILTERPATTERN>` | Filter paths based on a regex pattern, e.g.,<br/><br/>`hg --filter '(include\|src)/.*\.(c\|cpp\|h\|hpp)$'`<br/><br/>will search C/C++ files in the any `*/include/*` and `*/src/*` paths.<br/><br/>A filter can be negated by prefixing the pattern with !, e.g.,<br/><br/>`hg --filter '!\.html$'`<br/><br/>will search any files that are not HTML files. |+| `--filter <FILTERPATTERN>` | Filter paths based on a regex pattern, e.g.,<br/><br/>`hgrep --filter '(include\|src)/.*\.(c\|cpp\|h\|hpp)$'`<br/><br/>will search C/C++ files in the any `*/include/*` and `*/src/*` paths.<br/><br/>A filter can be negated by prefixing the pattern with !, e.g.,<br/><br/>`hgrep --filter '!\.html$'`<br/><br/>will search any files that are not HTML files. | | `-F, --fixed-strings` | Treat the pattern as a literal string instead of a regex. Special regex meta characters such as `.(){}*+` do not need to be escaped. | | `-h, --help` | Display help message. | | `--hidden` | Search hidden files and directories. By default, hidden files and directories are skipped. A file or directory is considered hidden if its base name starts with a dot character (`'.'`). |@@ -297,7 +297,7 @@ hg [OPTIONS] --version | `-I, --no-filename` | Never print the file path with the matched lines. This is the default when searching one file or stdin. | | `-l, --files-with-matches` | Print the paths with at least one match and suppress match contents. | | `-M, --max-columns <NUM>` | Don't print lines longer than this limit in bytes. Longer lines are omitted, and only the number of matches in that line is printed. |-| `--max-filesize <NUM+SUFFIX?>` | Ignore files above a certain size. The input accepts suffixes of form `K`, `M` or `G`. If no suffix is provided the input is treated as bytes e.g.,<br/><br/>`hg --max-filesize 50K`<br/><br/>will search any files under `50KB` in size. |+| `--max-filesize <NUM+SUFFIX?>` | Ignore files above a certain size. The input accepts suffixes of form `K`, `M` or `G`. If no suffix is provided the input is treated as bytes e.g.,<br/><br/>`hgrep --max-filesize 50K`<br/><br/>will search any files under `50KB` in size. | | `-n, --line-number` | Show line numbers (1-based). This is enabled by defauled when searching in a terminal. | | `-N, --no-line-number` | Suppress line numbers. This is enabled by default when not searching in a terminal. | | `-o, --only-matching` | Print only matched parts of a matching line, with each such part on a separate output line. |
include/hypergrep/constants.hpp
@@ -1,7 +1,7 @@ #pragma once #include <string_view> -constexpr static inline std::string_view NAME = "hg";+constexpr static inline std::string_view NAME = "hgrep"; constexpr static inline std::string_view DESCRIPTION = "Recursively search directories for a regex pattern"; constexpr static inline std::string_view VERSION = "0.1.1";
@@ -28,21 +28,21 @@ void print_description_line(std::string_view line) { fmt::print(" {}\n", line); } -void print_synopsis_1() { fmt::print(" hg [OPTIONS] PATTERN [PATH ...]\n"); }+void print_synopsis_1() { fmt::print(" hgrep [OPTIONS] PATTERN [PATH ...]\n"); } void print_synopsis_2() {- fmt::print(" hg [OPTIONS] -e PATTERN ... [PATH ...]\n");+ fmt::print(" hgrep [OPTIONS] -e PATTERN ... [PATH ...]\n"); } void print_synopsis_3() {- fmt::print(" hg [OPTIONS] -f PATTERNFILE ... [PATH ...]\n");+ fmt::print(" hgrep [OPTIONS] -f PATTERNFILE ... [PATH ...]\n"); } -void print_synopsis_4() { fmt::print(" hg [OPTIONS] --files [PATH ...]\n"); }+void print_synopsis_4() { fmt::print(" hgrep [OPTIONS] --files [PATH ...]\n"); } -void print_synopsis_5() { fmt::print(" hg [OPTIONS] --help\n"); }+void print_synopsis_5() { fmt::print(" hgrep [OPTIONS] --help\n"); } -void print_synopsis_6() { fmt::print(" hg [OPTIONS] --version\n"); }+void print_synopsis_6() { fmt::print(" hgrep [OPTIONS] --version\n"); } void print_help() { const auto is_stdout = isatty(STDOUT_FILENO) == 1;@@ -122,7 +122,7 @@ void print_help() { "where all patterns given are searched. Lines matching at least one"); print_description_line("of the provided patterns are printed, e.g.,\n"); print_option_name(is_stdout,- " hg -e 'myFunctionCall' -e 'myErrorCallback'\n");+ " hgrep -e 'myFunctionCall' -e 'myErrorCallback'\n"); print_description_line( "will search for any occurrence of either of the patterns.\n"); @@ -145,12 +145,12 @@ void print_help() { print_option_name(is_stdout, "--filter", "<FILTER_PATTERN>"); print_description_line("Filter paths based on a regex pattern, e.g.,\n"); print_option_name(- is_stdout, " hg --filter '(include|src)/.*\\.(c|cpp|h|hpp)$'\n");+ is_stdout, " hgrep --filter '(include|src)/.*\\.(c|cpp|h|hpp)$'\n"); print_description_line( "will search C/C++ files in the any */include/* and */src/* paths.\n"); print_description_line( "A filter can be negated by prefixing the pattern with !, e.g.,\n");- print_option_name(is_stdout, " hg --filter '!\\.html$'\n");+ print_option_name(is_stdout, " hgrep --filter '!\\.html$'\n"); print_description_line("will search any files that are not HTML files.\n"); // Fixed Strings@@ -237,7 +237,7 @@ void print_help() { print_description_line( "form K, M or G. If no suffix is provided the input is treated as bytes"); print_description_line("e.g.,\n");- print_option_name(is_stdout, " hg --max-filesize 50K\n");+ print_option_name(is_stdout, " hgrep --max-filesize 50K\n"); print_description_line("will search any files under 50KB in size.\n"); // Line Number