@ 260915.5

201117.1 · fbfb136aa5edb486ebd205a51106043827ea48e1

released 3.0.5

reading declarations

README.md

@@ -263,9 +263,9 @@ Build `ugrep` on Unix-like systems with colors enabled by default:     $ ./build.sh  This builds the `ugrep` executable in the `ugrep/src` directory with-`./configure --enable-color` and `make -j`, verified with `make test`.  When-all tests pass, the `ugrep` executable is copied to `ugrep/bin/ugrep` and-the symlink `ugrep/bin/ug -> ugrep/bin/ugrep` is added for the `ug` command.+`./configure` and `make -j`, verified with `make test`.  When all tests pass,+the `ugrep` executable is copied to `ugrep/bin/ugrep` and the symlink+`ugrep/bin/ug -> ugrep/bin/ugrep` is added for the `ug` command.  Note that `ug` is the same as `ugrep` but also loads the configuration file .ugrep when present in the working directory or home directory.  This means@@ -278,10 +278,10 @@ To build `ugrep` with specific hard defaults enabled, such as a pager:  Choices for hard defaults include: -- `--enable-color` colorize output to terminals (this is the default) - `--enable-hidden` search hidden files and directories - `--enable-pager` use a pager to display output on terminals - `--enable-pretty` colorize output to terminals and add filename headings+- `--disable-auto-color` disable automatic colors, requires ugrep option `--color=auto` to show colors - `--disable-mmap` disable memory mapped files - `--with-grep-path` the default `-f` path if `GREP_PATH` is not defined - `--with-grep-colors` the default colors if `GREP_COLORS` is not defined@@ -1509,19 +1509,16 @@ Same as `sed -n '/begin/,/end/p'`: to match all lines between a line containing             Print NUM lines of leading context before matching lines.  Places             a --group-separator between contiguous groups of matches.  See also             options -A, -C, and -y.-    -C[NUM], --context[=NUM]+    -C NUM, --context=NUM             Print NUM lines of leading and trailing context surrounding each-            match.  The default is 2 and is equivalent to -A 2 -B 2.  Places-            a --group-separator between contiguous groups of matches.-            No whitespace may be given between -C and its argument NUM.+            match.  Places a --group-separator between contiguous groups of+            matches. See also options -A, -B, and -y.     -y, --any-line             Any matching or non-matching line is output.  Non-matching lines             are output with the `-' separator as context of the matching lines.             See also options -A, -B, and -C. -To display 2 lines of context before and after a matching line (note that `-C2`-should not be specified as `-C 2` as per GNU/BSD grep exception that ugrep-obeys, because `-C` specifies 3 lines of context by default):+To display two lines of context before and after a matching line:      ugrep -C2 'FIXME' myfile.cpp @@ -3245,8 +3242,8 @@ in markdown:            ugrep, ug -- file pattern searcher      SYNOPSIS-           ugrep [OPTIONS] [-A NUM] [-B NUM] [-C[NUM]] [PATTERN] [-f FILE]-                 [-e PATTERN] [-N PATTERN] [-t TYPES] [-J [NUM]] [--sort[=KEY]]+           ugrep [OPTIONS] [-A NUM] [-B NUM] [-C NUM] [-y] [-Q|PATTERN] [-f FILE]+                 [-e PATTERN] [-N PATTERN] [-t TYPES] [-g GLOBS] [--sort[=KEY]]                  [--color[=WHEN]|--colour[=WHEN]] [--pager[=COMMAND]] [FILE ...]      DESCRIPTION@@ -3264,19 +3261,25 @@ in markdown:            is ASCII, UTF-8, or raw binary.  An input encoding format may be speci-            fied with option --encoding. -           If  no  FILE  arguments are specified and standard input is read from a-           terminal, recursive searches are performed as if -R is  specified.   To+           The ug command is equivalent to ugrep --config to load the default con-+           figuration file, which allows for customization, see CONFIGURATION.++           If no FILE arguments are specified and standard input is  read  from  a+           terminal,  recursive  searches are performed as if -R is specified.  To            force reading from standard input, specify `-' as a FILE argument. -           Directories  specified as FILE arguments are searched without recursing+           Directories specified as FILE arguments are searched without  recursing            into subdirectories, unless -R, -r, or -2...-9 is specified.             Hidden files and directories are ignored in recursive searches.  Option-           -.  (--hidden)  includes  hidden  files  and  directories  in recursive+           -. (--hidden)  includes  hidden  files  and  directories  in  recursive            searches. -           The ug command is equivalent to ugrep --config to load the default con--           figuration file, which allows for customization, see CONFIGURATION.+           A  query interface is opened with -Q (--query) to interactively specify+           search patterns and view search results.  Note that a PATTERN  argument+           should not be specified in this case.++           For help, --help WHAT displays help on options related to WHAT.             The following options are available: @@ -3320,41 +3323,40 @@ in markdown:            --break                   Adds a line break between results from different files. -           -C[NUM], --context[=NUM]+           -C NUM, --context=NUM                   Print NUM lines of leading and trailing context surrounding each-                  match.  The default is 2 and is equivalent to -A 2 -B 2.  Places-                  a  --group-separator  between  contiguous groups of matches.  No-                  whitespace may be given between -C and its argument NUM.+                  match.  Places a --group-separator between contiguous groups  of+                  matches.  See also options -A, -B, and -y.             -c, --count-                  Only a count of selected lines is written  to  standard  output.+                  Only  a  count  of selected lines is written to standard output.                   If -o or -u is specified, counts the number of patterns matched.                   If -v is specified, counts the number of non-matching lines.             --color[=WHEN], --colour[=WHEN]-                  Mark up the matching text with  the  expression  stored  in  the-                  GREP_COLOR  or  GREP_COLORS  environment  variable.  WHEN can be+                  Mark  up  the  matching  text  with the expression stored in the+                  GREP_COLOR or GREP_COLORS environment  variable.   WHEN  can  be                   `never', `always', or `auto', where `auto' marks up matches only                   when output on a terminal.  The default is `auto'.             --colors=COLORS, --colours=COLORS                   Use COLORS to mark up text.  COLORS is a colon-separated list of-                  one or more parameters `sl='  (selected  line),  `cx='  (context-                  line),  `mt='  (matched  text),  `ms='  (match  selected), `mc='-                  (match context), `fn=' (file name), `ln=' (line  number),  `cn='+                  one  or  more  parameters  `sl=' (selected line), `cx=' (context+                  line), `mt='  (matched  text),  `ms='  (match  selected),  `mc='+                  (match  context),  `fn=' (file name), `ln=' (line number), `cn='                   (column number), `bn=' (byte offset), `se=' (separator).  Param--                  eter values are ANSI SGR color codes or `k' (black), `r'  (red),-                  `g'  (green),  `y'  (yellow),  `b'  (blue),  `m'  (magenta), `c'+                  eter  values are ANSI SGR color codes or `k' (black), `r' (red),+                  `g' (green),  `y'  (yellow),  `b'  (blue),  `m'  (magenta),  `c'                   (cyan), `w' (white).  Upper case specifies background colors.  A-                  `+'  qualifies a color as bright.  A foreground and a background-                  color may be combined with font  properties  `n'  (normal),  `f'+                  `+' qualifies a color as bright.  A foreground and a  background+                  color  may  be  combined  with font properties `n' (normal), `f'                   (faint), `h' (highlight), `i' (invert), `u' (underline).  Selec-                   tively overrides GREP_COLORS.             --config[=FILE], ---[FILE]-                  Use configuration FILE.  The  default  FILE  is  `.ugrep'.   The-                  working  directory  is  checked  first  for  FILE, then the home-                  directory.  The options specified in the configuration FILE  are+                  Use  configuration  FILE.   The  default  FILE is `.ugrep'.  The+                  working directory is checked  first  for  FILE,  then  the  home+                  directory.   The options specified in the configuration FILE are                   parsed first, followed by the remaining options specified on the                   command line. @@ -3363,133 +3365,133 @@ in markdown:             --cpp  Output file matches in C++.  See also options --format and -u. -           --csv  Output file matches in CSV.  If -H, -n, -k, or -b is  specified,+           --csv  Output  file matches in CSV.  If -H, -n, -k, or -b is specified,                   additional values are output.  See also options --format and -u.             -D ACTION, --devices=ACTION-                  If an input file is a device, FIFO  or  socket,  use  ACTION  to-                  process  it.   By  default,  ACTION  is `skip', which means that+                  If  an  input  file  is  a device, FIFO or socket, use ACTION to+                  process it.  By default, ACTION  is  `skip',  which  means  that                   devices are silently skipped.  If ACTION is `read', devices read                   just as if they were ordinary files.             -d ACTION, --directories=ACTION-                  If  an  input file is a directory, use ACTION to process it.  By-                  default, ACTION  is  `skip',  i.e.,  silently  skip  directories+                  If an input file is a directory, use ACTION to process  it.   By+                  default,  ACTION  is  `skip',  i.e.,  silently  skip directories                   unless specified on the command line.  If ACTION is `read', warn-                  when directories are read as input.   If  ACTION  is  `recurse',+                  when  directories  are  read  as input.  If ACTION is `recurse',                   read all files under each directory, recursively, following sym--                  bolic links only if they are  on  the  command  line.   This  is-                  equivalent   to   the   -r   option.   If  ACTION  is  `derefer-+                  bolic  links  only  if  they  are  on the command line.  This is+                  equivalent  to  the  -r  option.    If   ACTION   is   `derefer-                   ence-recurse', read all files under each directory, recursively,-                  following  symbolic links.  This is equivalent to the -R option.+                  following symbolic links.  This is equivalent to the -R  option.             --depth=[MIN,][MAX], -1, -2 ... -9, --10, --11 ...-                  Restrict recursive searches from MIN  to  MAX  directory  levels-                  deep,  where  -1 (--depth=1) searches the specified path without-                  recursing into subdirectories.  Note that -3 -5,  -3-5,  or  -35-                  searches  3  to  5  levels  deep.  Enables -R if -R or -r is not+                  Restrict  recursive  searches  from  MIN to MAX directory levels+                  deep, where -1 (--depth=1) searches the specified  path  without+                  recursing  into  subdirectories.   Note that -3 -5, -3-5, or -35+                  searches 3 to 5 levels deep.  Enables -R if  -R  or  -r  is  not                   specified.             -E, --extended-regexp-                  Interpret patterns as extended regular expressions (EREs).  This+                  Interpret  patterns as extended regular expressions (EREs). This                   is the default.             -e PATTERN, --regexp=PATTERN-                  Specify  a PATTERN used during the search of the input: an input-                  line is selected if it matches any of  the  specified  patterns.+                  Specify a PATTERN used during the search of the input: an  input+                  line  is  selected  if it matches any of the specified patterns.                   Note that longer patterns take precedence over shorter patterns.-                  This option is most useful when multiple -e options are used  to-                  specify  multiple  patterns,  when  a pattern begins with a dash-                  (`-'), to specify a pattern after option -f or  after  the  FILE+                  This  option is most useful when multiple -e options are used to+                  specify multiple patterns, when a pattern  begins  with  a  dash+                  (`-'),  to  specify  a pattern after option -f or after the FILE                   arguments.             --encoding=ENCODING-                  The  encoding  format  of  the  input,  where  ENCODING  can be:-                  `binary', `ASCII', `UTF-8',  `UTF-16',  `UTF-16BE',  `UTF-16LE',-                  `UTF-32',   `UTF-32BE',   `UTF-32LE',   `LATIN1',  `ISO-8859-1',+                  The encoding  format  of  the  input,  where  ENCODING  can  be:+                  `binary',  `ASCII',  `UTF-8',  `UTF-16', `UTF-16BE', `UTF-16LE',+                  `UTF-32',  `UTF-32BE',   `UTF-32LE',   `LATIN1',   `ISO-8859-1',                   `ISO-8869-2',    `ISO-8869-3',    `ISO-8869-4',    `ISO-8869-5',                   `ISO-8869-6',    `ISO-8869-7',    `ISO-8869-8',    `ISO-8869-9',-                  `ISO-8869-10',  `ISO-8869-11',   `ISO-8869-13',   `ISO-8869-14',-                  `ISO-8869-15',   `ISO-8869-16',   `MAC',  `MACROMAN',  `EBCDIC',-                  `CP437',  `CP850',  `CP858',   `CP1250',   `CP1251',   `CP1252',+                  `ISO-8869-10',   `ISO-8869-11',   `ISO-8869-13',  `ISO-8869-14',+                  `ISO-8869-15',  `ISO-8869-16',  `MAC',   `MACROMAN',   `EBCDIC',+                  `CP437',   `CP850',   `CP858',   `CP1250',  `CP1251',  `CP1252',                   `CP1253',  `CP1254',  `CP1255',  `CP1256',  `CP1257',  `CP1258',                   `KOI8-R', `KOI8-U', `KOI8-RU'.             --exclude=GLOB                   Skip files whose name matches GLOB using wildcard matching, same                   as -g ^GLOB.  GLOB can use **, *, ?, and [...] as wildcards, and-                  \ to quote a wildcard or backslash  character  literally.   When-                  GLOB  contains  a  `/',  full  pathnames are matched.  Otherwise-                  basenames are matched.  When GLOB ends with a  `/',  directories-                  are  excluded as if --exclude-dir is specified.  Otherwise files-                  are excluded.  Note that --exclude patterns take  priority  over-                  --include  patterns.   GLOB  should  be  quoted to prevent shell+                  \  to  quote  a wildcard or backslash character literally.  When+                  GLOB contains a `/',  full  pathnames  are  matched.   Otherwise+                  basenames  are  matched.  When GLOB ends with a `/', directories+                  are excluded as if --exclude-dir is specified.  Otherwise  files+                  are  excluded.   Note that --exclude patterns take priority over+                  --include patterns.  GLOB should  be  quoted  to  prevent  shell                   globbing.  This option may be repeated.             --exclude-dir=GLOB-                  Exclude directories  whose  name  matches  GLOB  from  recursive-                  searches.   GLOB can use **, *, ?, and [...] as wildcards, and \+                  Exclude  directories  whose  name  matches  GLOB  from recursive+                  searches.  GLOB can use **, *, ?, and [...] as wildcards, and  \                   to quote a wildcard or backslash character literally.  When GLOB                   contains a `/', full pathnames are matched.  Otherwise basenames-                  are matched.  Note that  --exclude-dir  patterns  take  priority-                  over  --include-dir  patterns.  GLOB should be quoted to prevent+                  are  matched.   Note  that  --exclude-dir patterns take priority+                  over --include-dir patterns.  GLOB should be quoted  to  prevent                   shell globbing.  This option may be repeated.             --exclude-from=FILE-                  Read the globs from FILE and skip files  and  directories  whose+                  Read  the  globs  from FILE and skip files and directories whose                   name matches one or more globs (as if specified by --exclude and-                  --exclude-dir).  Lines starting with a `#' and  empty  lines  in-                  FILE  are  ignored.  When FILE is a `-', standard input is read.+                  --exclude-dir).   Lines  starting  with a `#' and empty lines in+                  FILE are ignored.  When FILE is a `-', standard input  is  read.                   This option may be repeated.             --exclude-fs=MOUNTS-                  Exclude  file  systems  specified  by  MOUNTS   from   recursive-                  searches,  MOUNTS  is  a comma-separated list of mount points or-                  pathnames  of  directories   on   file   systems.    Note   that-                  --exclude-fs  mounts  take  priority  over  --include-fs mounts.+                  Exclude   file   systems  specified  by  MOUNTS  from  recursive+                  searches, MOUNTS is a comma-separated list of  mount  points  or+                  pathnames   of   directories   on   file   systems.   Note  that+                  --exclude-fs mounts  take  priority  over  --include-fs  mounts.                   This option may be repeated.             -F, --fixed-strings-                  Interpret pattern as a set of fixed strings, separated  by  new--                  lines,  any  of which is to be matched.  This makes ugrep behave-                  as fgrep.  If a PATTERN is specified, or -e PATTERN or  -N  PAT--                  TERN,  then  this  option  does not apply to -f FILE patterns to+                  Interpret  pattern  as a set of fixed strings, separated by new-+                  lines, any of which is to be matched.  This makes  ugrep  behave+                  as  fgrep.   If a PATTERN is specified, or -e PATTERN or -N PAT-+                  TERN, then this option does not apply to  -f  FILE  patterns  to                   allow -f FILE patterns to narrow or widen the PATTERN search.             -f FILE, --file=FILE-                  Read newline-separated patterns from FILE.  White space in  pat-+                  Read  newline-separated patterns from FILE.  White space in pat-                   terns is significant.  Empty lines in FILE are ignored.  If FILE-                  does not exist, the GREP_PATH environment variable  is  used  as-                  path   to   FILE.    If   that   fails,   looks   for   FILE  in-                  /usr/local/share/ugrep/patterns.  When FILE is a  `-',  standard+                  does  not  exist,  the GREP_PATH environment variable is used as+                  path  to   FILE.    If   that   fails,   looks   for   FILE   in+                  /usr/local/share/ugrep/patterns.   When  FILE is a `-', standard                   input is read.  Empty files contain no patterns; thus nothing is                   matched.  This option may be repeated.             --filter=COMMANDS                   Filter files through the specified COMMANDS first before search-                   ing.   COMMANDS  is  a  comma-separated  list  of  `exts:command-                  [option ...]', where `exts' is a comma-separated list  of  file--                  name  extensions  and `command' is a filter utility.  The filter-                  utility should read from standard input and  write  to  standard+                  [option  ...]',  where `exts' is a comma-separated list of file-+                  name extensions and `command' is a filter utility.   The  filter+                  utility  should  read  from standard input and write to standard                   output.  Files matching one of `exts' are filtered.  When `exts'                   is `*', files with non-matching extensions are filtered.  One or-                  more  `option'  separated by spacing may be specified, which are-                  passed verbatim to the command.  A `%' as `option' expands  into-                  the  pathname to search.  For example, --filter='pdf:pdftotext %-                  -' searches PDF files.  The `%' expands into a `-' when  search--                  ing  standard input.  Option --label=.ext may be used to specify+                  more `option' separated by spacing may be specified,  which  are+                  passed  verbatim to the command.  A `%' as `option' expands into+                  the pathname to search.  For example, --filter='pdf:pdftotext  %+                  -'  searches PDF files.  The `%' expands into a `-' when search-+                  ing standard input.  Option --label=.ext may be used to  specify                   extension `ext' when searching standard input.             --filter-magic-label=LABEL:MAGIC-                  Associate LABEL with files whose signature "magic  bytes"  match-                  the  MAGIC  regex  pattern.   Only  files  that have no filename-                  extension are labeled, unless +LABEL is specified.   When  LABEL-                  matches  an extension specified in --filter=COMMANDS, the corre-+                  Associate  LABEL  with files whose signature "magic bytes" match+                  the MAGIC regex pattern.   Only  files  that  have  no  filename+                  extension  are  labeled, unless +LABEL is specified.  When LABEL+                  matches an extension specified in --filter=COMMANDS, the  corre-                   sponding command is invoked.  This option may be repeated.             --format=FORMAT-                  Output   FORMAT-formatted   matches.    For   example    `--for--                  mat=%f:%n:%O%~'  outputs  matching lines `%O' with filename `%f`+                  Output    FORMAT-formatted   matches.    For   example   `--for-+                  mat=%f:%n:%O%~' outputs matching lines `%O' with  filename  `%f`                   and line number `%n' followed by a newline `%~'. See `man ugrep'                   section FORMAT. @@ -3501,15 +3503,15 @@ in markdown:                   behave as traditional grep.             -g GLOBS, --glob=GLOBS-                  Search only files whose name matches the  specified  comma-sepa-+                  Search  only  files whose name matches the specified comma-sepa-                   rated list of GLOBS, same as --include='glob' for each `glob' in-                  GLOBS.  When a `glob' is preceded by a `!' or a `^', skip  files-                  whose  name  matches  `glob',  same  as  --exclude='glob'.  When-                  `glob' contains a `/', full pathnames  are  matched.   Otherwise+                  GLOBS.   When a `glob' is preceded by a `!' or a `^', skip files+                  whose name  matches  `glob',  same  as  --exclude='glob'.   When+                  `glob'  contains  a  `/', full pathnames are matched.  Otherwise                   basenames are matched.  When `glob' ends with a `/', directories-                  are    matched,     same     as     --include-dir='glob'     and-                  --exclude-dir='glob'.   This  option  may be repeated and may be-                  combined with options -M, -O and  -t  to  expand  the  recursive+                  are     matched,     same     as     --include-dir='glob'    and+                  --exclude-dir='glob'.  This option may be repeated  and  may  be+                  combined  with  options  -M,  -O  and -t to expand the recursive                   search.             --group-separator[=SEP]@@ -3517,12 +3519,12 @@ in markdown:                   The default is a double hyphen (`--').             -H, --with-filename-                  Always print the  filename  with  output  lines.   This  is  the+                  Always  print  the  filename  with  output  lines.   This is the                   default when there is more than one file to search.             -h, --no-filename-                  Never  print  filenames  with output lines.  This is the default-                  when there is only one file (or only standard input) to  search.+                  Never print filenames with output lines.  This  is  the  default+                  when  there is only one file (or only standard input) to search.             --heading, -+                   Group matches per file.  Adds a heading and a line break between@@ -3532,76 +3534,76 @@ in markdown:                   Display a help message, specifically on WHAT when specified.             --hexdump=[1-8][b][c][h]-                  Output matches in 1 to 8 columns of 8 hexadecimal  octets.   The-                  default  is 2 columns or 16 octets per line.  Option `b' removes-                  all space breaks, `c' removes  the  character  column,  and  `h'-                  removes  the  hex spacing.  Enables -X if -W or -X is not speci-+                  Output  matches  in 1 to 8 columns of 8 hexadecimal octets.  The+                  default is 2 columns or 16 octets per line.  Option `b'  removes+                  all  space  breaks,  `c'  removes  the character column, and `h'+                  removes the hex spacing.  Enables -X if -W or -X is  not  speci-                   fied.             --hidden, -.                   Search hidden files and directories.             -I, --ignore-binary-                  Ignore matches in binary files.  This option  is  equivalent  to+                  Ignore  matches  in  binary files.  This option is equivalent to                   the --binary-files=without-match option.             -i, --ignore-case-                  Perform  case  insensitive  matching.  By default, ugrep is case+                  Perform case insensitive matching.  By default,  ugrep  is  case                   sensitive.  This option applies to ASCII letters only.             --ignore-files[=FILE]-                  Ignore files and directories matching the  globs  in  each  FILE-                  that  is encountered in recursive searches.  The default FILE is-                  `.gitignore'.  Matching files and  directories  located  in  the-                  directory  of  a  FILE's  location  and in directories below are-                  ignored   by   temporarily   overriding   the   --exclude    and-                  --exclude-dir  globs.  Files and directories that are explicitly-                  specified as command line arguments  are  never  ignored.   This+                  Ignore  files  and  directories  matching the globs in each FILE+                  that is encountered in recursive searches.  The default FILE  is+                  `.gitignore'.   Matching  files  and  directories located in the+                  directory of a FILE's location  and  in  directories  below  are+                  ignored    by   temporarily   overriding   the   --exclude   and+                  --exclude-dir globs.  Files and directories that are  explicitly+                  specified  as  command  line  arguments are never ignored.  This                   option may be repeated.             --include=GLOB-                  Search  only files whose name matches GLOB using wildcard match-+                  Search only files whose name matches GLOB using wildcard  match-                   ing, same as -g GLOB.  GLOB can use **, *, ?, and [...] as wild--                  cards,  and  \ to quote a wildcard or backslash character liter--                  ally.  When GLOB contains a `/',  full  pathnames  are  matched.-                  Otherwise  basenames  are  matched.   When GLOB ends with a `/',+                  cards, and \ to quote a wildcard or backslash  character  liter-+                  ally.   When  GLOB  contains  a `/', full pathnames are matched.+                  Otherwise basenames are matched.  When GLOB  ends  with  a  `/',                   directories are included as if --include-dir is specified.  Oth--                  erwise  files  are  included.  Note that --exclude patterns take+                  erwise files are included.  Note that  --exclude  patterns  take                   priority over --include patterns.  GLOB should be quoted to pre-                   vent shell globbing.  This option may be repeated.             --include-dir=GLOB-                  Only  directories whose name matches GLOB are included in recur--                  sive searches.  GLOB can use **, *, ?, and [...]  as  wildcards,-                  and  \  to  quote  a  wildcard or backslash character literally.+                  Only directories whose name matches GLOB are included in  recur-+                  sive  searches.   GLOB can use **, *, ?, and [...] as wildcards,+                  and \ to quote a  wildcard  or  backslash  character  literally.                   When GLOB contains a `/', full pathnames are matched.  Otherwise-                  basenames  are  matched.   Note that --exclude-dir patterns take-                  priority over --include-dir patterns.  GLOB should be quoted  to+                  basenames are matched.  Note that  --exclude-dir  patterns  take+                  priority  over --include-dir patterns.  GLOB should be quoted to                   prevent shell globbing.  This option may be repeated.             --include-from=FILE-                  Read  the  globs from FILE and search only files and directories-                  whose name matches  one  or  more  globs  (as  if  specified  by-                  --include  and  --include-dir).   Lines  starting with a `#' and-                  empty lines in FILE are ignored.  When FILE is a  `-',  standard+                  Read the globs from FILE and search only files  and  directories+                  whose  name  matches  one  or  more  globs  (as  if specified by+                  --include and --include-dir).  Lines starting  with  a  `#'  and+                  empty  lines  in FILE are ignored.  When FILE is a `-', standard                   input is read.  This option may be repeated.             --include-fs=MOUNTS-                  Only  file systems specified by MOUNTS are included in recursive-                  searches.  MOUNTS is a comma-separated list of mount  points  or-                  pathnames   of  directories  on  file  systems.   --include-fs=.-                  restricts recursive searches to the file system of  the  working-                  directory  only.   Note  that  --exclude-fs mounts take priority+                  Only file systems specified by MOUNTS are included in  recursive+                  searches.   MOUNTS  is a comma-separated list of mount points or+                  pathnames  of  directories  on  file  systems.    --include-fs=.+                  restricts  recursive  searches to the file system of the working+                  directory only.  Note that  --exclude-fs  mounts  take  priority                   over --include-fs mounts.  This option may be repeated.             -J NUM, --jobs=NUM-                  Specifies the number of threads spawned  to  search  files.   By-                  default  an optimum number of threads is spawned to search files-                  simultaneously.  -J1 disables threading: files are  searched  in+                  Specifies  the  number  of  threads spawned to search files.  By+                  default an optimum number of threads is spawned to search  files+                  simultaneously.   -J1  disables threading: files are searched in                   the same order as specified.             -j, --smart-case-                  Perform  case  insensitive matching unless a pattern contains an+                  Perform case insensitive matching unless a pattern  contains  an                   upper case letter.  This option applies to ASCII letters only.             --json Output file matches in JSON.  If -H, -n, -k, or -b is specified,@@ -3611,39 +3613,39 @@ in markdown:                   Start searching at line FIRST, stop at line LAST when specified.             -k, --column-number-                  The  column number of a matched pattern is displayed in front of-                  the respective matched line, starting at  column  1.   Tabs  are+                  The column number of a matched pattern is displayed in front  of+                  the  respective  matched  line,  starting at column 1.  Tabs are                   expanded when columns are counted, see also option --tabs.             -L, --files-without-match-                  Only  the names of files not containing selected lines are writ--                  ten to standard output.  Pathnames  are  listed  once  per  file+                  Only the names of files not containing selected lines are  writ-+                  ten  to  standard  output.   Pathnames  are listed once per file                   searched.   If  the  standard  input  is  searched,  the  string                   ``(standard input)'' is written.             -l, --files-with-matches                   Only the names of files containing selected lines are written to-                  standard  output.   ugrep  will only search a file until a match-                  has been found,  making  searches  potentially  less  expensive.-                  Pathnames  are  listed  once per file searched.  If the standard+                  standard output.  ugrep will only search a file  until  a  match+                  has  been  found,  making  searches  potentially less expensive.+                  Pathnames are listed once per file searched.   If  the  standard                   input is searched, the string ``(standard input)'' is written.             --label=LABEL-                  Displays the LABEL value when input is read from standard  input-                  where  a file name would normally be printed in the output.  The+                  Displays  the LABEL value when input is read from standard input+                  where a file name would normally be printed in the output.   The                   default value is `(standard input)'.             --line-buffered                   Force output to be line buffered instead of block buffered.             -M MAGIC, --file-magic=MAGIC-                  Only files matching the signature pattern  MAGIC  are  searched.-                  The  signature "magic bytes" at the start of a file are compared-                  to the MAGIC regex pattern.  When matching,  the  file  will  be-                  searched.   When MAGIC is preceded by a `!' or a `^', skip files+                  Only  files  matching  the signature pattern MAGIC are searched.+                  The signature "magic bytes" at the start of a file are  compared+                  to  the  MAGIC  regex  pattern.  When matching, the file will be+                  searched.  When MAGIC is preceded by a `!' or a `^', skip  files                   with matching MAGIC signatures.  This option may be repeated and-                  may  be  combined  with  options -O and -t to expand the search.-                  Every file on the search path is read,  making  searches  poten-+                  may be combined with options -O and -t  to  expand  the  search.+                  Every  file  on  the search path is read, making searches poten-                   tially more expensive.             -m NUM, --max-count=NUM@@ -3653,93 +3655,93 @@ in markdown:                   Match all input.  Same as specifying an empty pattern to search.             --max-files=NUM-                  Restrict the number of files matched to NUM.  Note  that  --sort-                  or  -J1  may  be  specified  to  produce replicable results.  If+                  Restrict  the  number of files matched to NUM.  Note that --sort+                  or -J1 may be  specified  to  produce  replicable  results.   If                   --sort is specified, the number of threads spawned is limited to                   NUM.             --mmap[=MAX]-                  Use  memory  maps  to search files.  By default, memory maps are-                  used under certain conditions to improve performance.  When  MAX+                  Use memory maps to search files.  By default,  memory  maps  are+                  used  under certain conditions to improve performance.  When MAX                   is specified, use up to MAX mmap memory per thread.             -N PATTERN, --neg-regexp=PATTERN-                  Specify  a negative PATTERN used during the search of the input:-                  an input line is selected only if it matches any of  the  speci--                  fied  patterns  unless  a  subpattern  of  PATTERN.   Same as -e-                  (?^PATTERN).  Negative PATTERN matches are  essentially  removed-                  before  any  other  patterns are matched.  Note that longer pat-+                  Specify a negative PATTERN used during the search of the  input:+                  an  input  line is selected only if it matches any of the speci-+                  fied patterns unless  a  subpattern  of  PATTERN.   Same  as  -e+                  (?^PATTERN).   Negative  PATTERN matches are essentially removed+                  before any other patterns are matched.  Note  that  longer  pat-                   terns take precedence over shorter patterns.  This option may be                   repeated.             -n, --line-number-                  Each  output line is preceded by its relative line number in the-                  file, starting at line 1.  The line number counter is reset  for+                  Each output line is preceded by its relative line number in  the+                  file,  starting at line 1.  The line number counter is reset for                   each file processed. -           --not  Specifies  that  the following one or more -e PATTERN should not-                  match selected lines, where --not -e  PATTERN  is  the  same  as-                  specifying  -N  '.*PATTERN.*'  but  optimized to improve perfor-+           --not  Specifies that the following one or more -e PATTERN  should  not+                  match  selected  lines,  where  --not  -e PATTERN is the same as+                  specifying -N '.*PATTERN.*' but  optimized  to  improve  perfor-                   mance.             --no-group-separator-                  Removes the group separator line from  the  output  for  context+                  Removes  the  group  separator  line from the output for context                   options -A, -B, and -C.             -O EXTENSIONS, --file-extension=EXTENSIONS-                  Search  only files whose filename extensions match the specified-                  comma-separated list of EXTENSIONS,  same  as  --include='*.ext'-                  for  each  `ext'  in EXTENSIONS.  When an `ext' is preceded by a-                  `!' or a `^',  skip  files  whose  filename  extensions  matches-                  `ext',  same  as --exclude='*.ext'.  This option may be repeated-                  and may be combined with options -g, -M and  -t  to  expand  the+                  Search only files whose filename extensions match the  specified+                  comma-separated  list  of  EXTENSIONS, same as --include='*.ext'+                  for each `ext' in EXTENSIONS.  When an `ext' is  preceded  by  a+                  `!'  or  a  `^',  skip  files  whose filename extensions matches+                  `ext', same as --exclude='*.ext'.  This option may  be  repeated+                  and  may  be  combined  with options -g, -M and -t to expand the                   recursive search.             -o, --only-matching-                  Print  only  the  matching  part  of lines.  When multiple lines-                  match, the line numbers with option -n are displayed  using  `|'-                  as  the  field separator for each additional line matched by the-                  pattern.  If -u is specified, ungroups multiple matches  on  the-                  same  line.  This option cannot be combined with options -A, -B,+                  Print only the matching part  of  lines.   When  multiple  lines+                  match,  the  line numbers with option -n are displayed using `|'+                  as the field separator for each additional line matched  by  the+                  pattern.   If  -u is specified, ungroups multiple matches on the+                  same line.  This option cannot be combined with options -A,  -B,                   -C, -v, and -y.             --only-line-number                   The line number of the matching line in the file is output with--                  out  displaying the match.  The line number counter is reset for+                  out displaying the match.  The line number counter is reset  for                   each file processed.             -P, --perl-regexp                   Interpret PATTERN as a Perl regular expression using PCRE2.             -p, --no-dereference-                  If -R or -r is specified, no symbolic links are  followed,  even+                  If  -R  or -r is specified, no symbolic links are followed, even                   when they are specified on the command line.             --pager[=COMMAND]-                  When  output  is  sent  to  the  terminal,  uses COMMAND to page-                  through the output.  The default COMMAND is `less -R'.   Enables+                  When output is sent  to  the  terminal,  uses  COMMAND  to  page+                  through  the output.  The default COMMAND is `less -R'.  Enables                   --heading and --line-buffered.             --pretty-                  When  output  is sent to a terminal, enables --color, --heading,+                  When output is sent to a terminal, enables  --color,  --heading,                   -n, --sort and -T when not explicitly disabled or set.             -Q[DELAY], --query[=DELAY]-                  Query mode: user  interface  to  perform  interactive  searches.-                  This  mode requires an ANSI capable terminal.  An optional DELAY-                  argument may be specified to reduce  or  increase  the  response+                  Query  mode:  user  interface  to  perform interactive searches.+                  This mode requires an ANSI capable terminal.  An optional  DELAY+                  argument  may  be  specified  to reduce or increase the response                   time to execute searches after the last key press, in increments-                  of 100ms, where the default is 5 (0.5s  delay).   No  whitespace-                  may  be  given  between -Q and its argument DELAY.  Initial pat--                  terns may be specified with -e PATTERN, i.e. a PATTERN  argument+                  of  100ms,  where  the default is 5 (0.5s delay).  No whitespace+                  may be given between -Q and its argument  DELAY.   Initial  pat-+                  terns  may be specified with -e PATTERN, i.e. a PATTERN argument                   requires option -e.  Press F1 or CTRL-Z to view the help screen.                   Press F2 or CTRL-Y to invoke an editor to edit the file shown on-                  screen.   The  editor  is  taken  from  the environment variable-                  GREP_EDIT if defined, or EDITOR.  Press  Tab  and  Shift-Tab  to-                  navigate  directories  and  to  select  a file to search.  Press-                  Enter to select lines to output.  Press ALT-l for option  -l  to-                  list  files,  ALT-n  for  -n,  etc.  Non-option commands include-                  ALT-] to increase  fuzziness  and  ALT-}  to  increase  context.+                  screen.  The editor  is  taken  from  the  environment  variable+                  GREP_EDIT  if  defined,  or  EDITOR.  Press Tab and Shift-Tab to+                  navigate directories and to select  a  file  to  search.   Press+                  Enter  to  select lines to output.  Press ALT-l for option -l to+                  list files, ALT-n for  -n,  etc.   Non-option  commands  include+                  ALT-]  to  increase  fuzziness  and  ALT-}  to increase context.                   Press F1 or CTRL-Z for more information.  Enables --heading.             -q, --quiet, --silent@@ -3747,23 +3749,23 @@ in markdown:                   match has been found.             -R, --dereference-recursive-                  Recursively read all files under  each  directory.   Follow  all-                  symbolic  links,  unlike  -r.   When -J1 is specified, files are+                  Recursively  read  all  files  under each directory.  Follow all+                  symbolic links, unlike -r.  When -J1  is  specified,  files  are                   searched in the same order as specified.  Note that when no FILE-                  arguments  are  specified  and  input  is  read from a terminal,+                  arguments are specified and  input  is  read  from  a  terminal,                   recursive searches are performed as if -R is specified.             -r, --recursive-                  Recursively read all files under each directory, following  sym--                  bolic  links  only if they are on the command line.  When -J1 is+                  Recursively  read all files under each directory, following sym-+                  bolic links only if they are on the command line.  When  -J1  is                   specified, files are searched in the same order as specified.             -S, --dereference-                  If -r is specified, all symbolic links are  followed,  like  -R.+                  If  -r  is  specified, all symbolic links are followed, like -R.                   The default is not to follow symbolic links.             -s, --no-messages-                  Silent  mode: nonexistent and unreadable files are ignored, i.e.+                  Silent mode: nonexistent and unreadable files are ignored,  i.e.                   their error messages are suppressed.             --save-config[=FILE]@@ -3771,53 +3773,53 @@ in markdown:                   is a `-', write the configuration to standard output.             --separator[=SEP]-                  Use  SEP as field separator between file name, line number, col-+                  Use SEP as field separator between file name, line number,  col-                   umn number, byte offset, and the matched line.  The default is a                   colon (`:').             --sort[=KEY]-                  Displays  matching files in the order specified by KEY in recur-+                  Displays matching files in the order specified by KEY in  recur-                   sive searches.  KEY can be `name' to sort by pathname (default),-                  `best'  to sort by best match with option -Z (sort by best match-                  requires two passes over the input files),  `size'  to  sort  by+                  `best' to sort by best match with option -Z (sort by best  match+                  requires  two  passes  over  the input files), `size' to sort by                   file size, `used' to sort by last access time, `changed' to sort-                  by last modification time, and `created'  to  sort  by  creation-                  time.   Sorting  is  reversed  with  `rname',  `rbest', `rsize',-                  `rused', `rchanged', or `rcreated'.  Archive  contents  are  not-                  sorted.   Subdirectories are sorted and displayed after matching-                  files.  FILE arguments are searched in the same order as  speci-+                  by  last  modification  time,  and `created' to sort by creation+                  time.  Sorting  is  reversed  with  `rname',  `rbest',  `rsize',+                  `rused',  `rchanged',  or  `rcreated'.  Archive contents are not+                  sorted.  Subdirectories are sorted and displayed after  matching+                  files.   FILE arguments are searched in the same order as speci-                   fied.  Normally ugrep displays matches in no particular order to                   improve performance.             --stats-                  Display statistics  on  the  number  of  files  and  directories+                  Display  statistics  on  the  number  of  files  and directories                   searched, and the inclusion and exclusion constraints applied.             -T, --initial-tab-                  Add  a  tab space to separate the file name, line number, column+                  Add a tab space to separate the file name, line  number,  column                   number, and byte offset with the matched line.             -t TYPES, --file-type=TYPES-                  Search only files associated with TYPES, a comma-separated  list-                  of  file types.  Each file type corresponds to a set of filename+                  Search  only files associated with TYPES, a comma-separated list+                  of file types.  Each file type corresponds to a set of  filename                   extensions passed to option -O.  For capitalized file types, the                   search is expanded to include files with matching file signature                   magic bytes, as if passed to option -M.  When a type is preceded-                  by  a  `!' or a `^', excludes files of the specified type.  This-                  option may be repeated.  The possible file types can  be  (where-                  -tlist  displays a detailed list): `actionscript', `ada', `asm',-                  `asp', `aspx', `autoconf', `automake',  `awk',  `Awk',  `basic',+                  by a `!' or a `^', excludes files of the specified  type.   This+                  option  may  be repeated.  The possible file types can be (where+                  -tlist displays a detailed list): `actionscript', `ada',  `asm',+                  `asp',  `aspx',  `autoconf',  `automake', `awk', `Awk', `basic',                   `batch', `bison', `c', `c++', `clojure', `csharp', `css', `csv',-                  `dart', `Dart', `delphi',  `elisp',  `elixir',  `erlang',  `for--                  tran',  `gif',  `Gif', `go', `groovy', `gsp', `haskell', `html',-                  `jade', `java', `jpeg', `Jpeg', `js',  `json',  `jsp',  `julia',-                  `kotlin',  `less',  `lex',  `lisp',  `lua', `m4', `make', `mark--                  down', `matlab',  `node',  `Node',  `objc',  `objc++',  `ocaml',-                  `parrot',  `pascal', `pdf', `Pdf', `perl', `Perl', `php', `Php',-                  `png', `Png', `prolog', `python', `Python', `r',  `rpm',  `Rpm',-                  `rst',  `rtf', `Rtf', `ruby', `Ruby', `rust', `scala', `scheme',-                  `shell', `Shell', `smalltalk',  `sql',  `svg',  `swift',  `tcl',-                  `tex',  `text',  `tiff',  `Tiff', `tt', `typescript', `verilog',+                  `dart',  `Dart',  `delphi',  `elisp',  `elixir', `erlang', `for-+                  tran', `gif', `Gif', `go', `groovy', `gsp',  `haskell',  `html',+                  `jade',  `java',  `jpeg',  `Jpeg', `js', `json', `jsp', `julia',+                  `kotlin', `less', `lex', `lisp',  `lua',  `m4',  `make',  `mark-+                  down',  `matlab',  `node',  `Node',  `objc',  `objc++', `ocaml',+                  `parrot', `pascal', `pdf', `Pdf', `perl', `Perl', `php',  `Php',+                  `png',  `Png',  `prolog', `python', `Python', `r', `rpm', `Rpm',+                  `rst', `rtf', `Rtf', `ruby', `Ruby', `rust', `scala',  `scheme',+                  `shell',  `Shell',  `smalltalk',  `sql',  `svg', `swift', `tcl',+                  `tex', `text', `tiff', `Tiff',  `tt',  `typescript',  `verilog',                   `vhdl', `vim', `xml', `Xml', `yacc', `yaml'.             --tabs[=NUM]@@ -3825,17 +3827,17 @@ in markdown:                   of NUM may be 1, 2, 4, or 8.  The default tab size is 8.             --tag[=TAG[,END]]-                  Disables  colors to mark up matches with TAG.  END marks the end+                  Disables colors to mark up matches with TAG.  END marks the  end                   of a match if specified, otherwise TAG.  The default is `___'.             -U, --binary                   Disables Unicode matching for binary file matching, forcing PAT--                  TERN  to  match  bytes, not Unicode characters.  For example, -U-                  '\xa3' matches byte A3 (hex) instead of the Unicode  code  point+                  TERN to match bytes, not Unicode characters.   For  example,  -U+                  '\xa3'  matches  byte A3 (hex) instead of the Unicode code point                   U+00A3 represented by the two-byte UTF-8 sequence C2 A3.             -u, --ungroup-                  Do  not group multiple pattern matches on the same matched line.+                  Do not group multiple pattern matches on the same matched  line.                   Output the matched line again for each additional pattern match,                   using `+' as the field separator. @@ -3843,18 +3845,18 @@ in markdown:                   Display version information and exit.             -v, --invert-match-                  Selected  lines are those not matching any of the specified pat-+                  Selected lines are those not matching any of the specified  pat-                   terns.             -W, --with-hex-                  Output binary  matches  in  hexadecimal,  leaving  text  matches+                  Output  binary  matches  in  hexadecimal,  leaving  text matches                   alone.  This option is equivalent to the --binary-files=with-hex                   option.             -w, --word-regexp-                  The PATTERN is searched for as a word (as if  surrounded  by  \<-                  and  \>).   If  a PATTERN is specified, or -e PATTERN or -N PAT--                  TERN, then this option does not apply to  -f  FILE  patterns  to+                  The  PATTERN  is  searched for as a word (as if surrounded by \<+                  and \>).  If a PATTERN is specified, or -e PATTERN  or  -N  PAT-+                  TERN,  then  this  option  does not apply to -f FILE patterns to                   allow -f FILE patterns to narrow or widen the PATTERN search.             -X, --hex@@ -3862,68 +3864,68 @@ in markdown:                   --binary-files=hex option.  See also option --hexdump.             -x, --line-regexp-                  Only input lines selected against the entire PATTERN is  consid--                  ered  to  be matching lines (as if surrounded by ^ and $).  If a-                  PATTERN is specified, or -e PATTERN or  -N  PATTERN,  then  this-                  option  does not apply to -f FILE patterns to allow -f FILE pat-+                  Only  input lines selected against the entire PATTERN is consid-+                  ered to be matching lines (as if surrounded by ^ and $).   If  a+                  PATTERN  is  specified,  or  -e PATTERN or -N PATTERN, then this+                  option does not apply to -f FILE patterns to allow -f FILE  pat-                   terns to narrow or widen the PATTERN search. -           --xml  Output file matches in XML.  If -H, -n, -k, or -b is  specified,+           --xml  Output  file matches in XML.  If -H, -n, -k, or -b is specified,                   additional values are output.  See also options --format and -u.             -Y, --empty-                  Permits empty matches.  By default, empty matches are  disabled,-                  unless  a  pattern  begins with `^' or ends with `$'.  With this-                  option, empty-matching pattern, such as x?  and  x*,  match  all+                  Permits  empty matches.  By default, empty matches are disabled,+                  unless a pattern begins with `^' or ends with  `$'.   With  this+                  option,  empty-matching  pattern,  such  as x? and x*, match all                   input, not only lines containing the character `x'.             -y, --any-line                   Any matching or non-matching line is output.  Non-matching lines-                  are output with the `-' separator as  context  of  the  matching+                  are  output  with  the  `-' separator as context of the matching                   lines.  See also options -A, -B, and -C.             -Z[MAX], --fuzzy[=MAX]                   Fuzzy  mode:  report  approximate  pattern  matches  within  MAX-                  errors.  By default, MAX is 1: one deletion, insertion  or  sub--                  stitution  is  allowed.   When  `+' and/or `-' precede MAX, only+                  errors.   By  default, MAX is 1: one deletion, insertion or sub-+                  stitution is allowed.  When `+' and/or  `-'  precede  MAX,  only                   insertions and/or deletions are allowed, respectively.  When `~'-                  precedes  MAX,  substitution  counts as one error.  For example,-                  -Z+~3 allows up to three insertions  or  substitutions,  but  no-                  deletions.   The  first character of an approximate match always-                  matches the begin  of  a  pattern.   Option  --sort=best  orders-                  matching  files  by  best  match.   No  whitespace  may be given+                  precedes MAX, substitution counts as one  error.   For  example,+                  -Z+~3  allows  up  to  three insertions or substitutions, but no+                  deletions.  The first character of an approximate  match  always+                  matches  the  begin  of  a  pattern.   Option --sort=best orders+                  matching files by  best  match.   No  whitespace  may  be  given                   between -Z and its argument.             -z, --decompress-                  Decompress files to search, when compressed.   Archives  (.cpio,-                  .pax,  .tar, and .zip) and compressed archives (e.g. .taz, .tgz,-                  .tpz, .tbz, .tbz2, .tb2, .tz2, .tlz, and .txz) are searched  and-                  matching  pathnames  of  files in archives are output in braces.-                  If -g, -O, -M, or -t is specified,  searches  files  within  ar--                  chives  whose  name matches globs, matches file name extensions,-                  matches file signature  magic  bytes,  or  matches  file  types,-                  respectively.   Supported  compression formats: gzip (.gz), com-+                  Decompress  files  to search, when compressed.  Archives (.cpio,+                  .pax, .tar, and .zip) and compressed archives (e.g. .taz,  .tgz,+                  .tpz,  .tbz, .tbz2, .tb2, .tz2, .tlz, and .txz) are searched and+                  matching pathnames of files in archives are  output  in  braces.+                  If  -g,  -O,  -M,  or -t is specified, searches files within ar-+                  chives whose name matches globs, matches file  name  extensions,+                  matches  file  signature  magic  bytes,  or  matches file types,+                  respectively.  Supported compression formats: gzip  (.gz),  com-                   press (.Z), zip, bzip2 (requires suffix .bz, .bz2, .bzip2, .tbz,-                  .tbz2,  .tb2,  .tz2),  lzma and xz (requires suffix .lzma, .tlz,+                  .tbz2, .tb2, .tz2), lzma and xz (requires  suffix  .lzma,  .tlz,                   .xz, .txz), lz4 (requires suffix .lz4).             -0, --null-                  Prints a zero-byte (NUL) after the file name.  This  option  can-                  be  used  with commands such as `find -print0' and `xargs -0' to+                  Prints  a  zero-byte (NUL) after the file name.  This option can+                  be used with commands such as `find -print0' and `xargs  -0'  to                   process arbitrary file names. -           A `--' signals the end of options; the rest of the parameters are  FILE+           A  `--' signals the end of options; the rest of the parameters are FILE            arguments, allowing filenames to begin with a `-' character.             Long options may start with `--no-' to disable, when applicable. -           The  regular expression pattern syntax is an extended form of the POSIX+           The regular expression pattern syntax is an extended form of the  POSIX            ERE syntax.  For an overview of the syntax see README.md or visit:                    https://github.com/Genivia/ugrep -           Note that `.' matches any non-newline character.  Pattern `\n'  matches-           a  newline character.  Multiple lines may be matched with patterns that+           Note  that `.' matches any non-newline character.  Pattern `\n' matches+           a newline character.  Multiple lines may be matched with patterns  that            match one or more newline characters.      EXIT STATUS@@ -3935,53 +3937,53 @@ in markdown:             >1     An error occurred. -           If -q or --quiet or --silent is used and a line is selected,  the  exit+           If  -q  or --quiet or --silent is used and a line is selected, the exit            status is 0 even if an error occurred.      CONFIGURATION-           The  ug command is intended for context-dependent interactive searching-           and is equivalent to the ugrep --config command  to  load  the  default+           The ug command is intended for context-dependent interactive  searching+           and  is  equivalent  to  the ugrep --config command to load the default            configuration file `.ugrep' when present in the working directory or in            the home directory.             A configuration file contains `NAME=VALUE' pairs per line, where `NAME`-           is  the  name  of a long option (without `--') and `=VALUE' is an argu--           ment, which is optional and may be omitted  depending  on  the  option.+           is the name of a long option (without `--') and `=VALUE'  is  an  argu-+           ment,  which  is  optional  and may be omitted depending on the option.            Empty lines and lines starting with a `#' are ignored. -           The  --config=FILE  option  and  its  abbreviated form ---FILE load the-           specified configuration file located in the working directory or,  when-           not  found,  located  in the home directory.  An error is produced when+           The --config=FILE option and its  abbreviated  form  ---FILE  load  the+           specified  configuration file located in the working directory or, when+           not found, located in the home directory.  An error  is  produced  when            FILE is not found or cannot be read. -           Command line options are parsed in the following order: the  configura--           tion  file is loaded first, followed by the remaining options and argu-+           Command  line options are parsed in the following order: the configura-+           tion file is loaded first, followed by the remaining options and  argu-            ments on the command line. -           The --save-config option saves a `.ugrep'  configuration  file  to  the-           working  directory  with  a subset of the current options.  The --save--           config=FILE option saves the configuration to FILE.  The  configuration+           The  --save-config  option  saves  a `.ugrep' configuration file to the+           working directory with a subset of the current  options.   The  --save-+           config=FILE  option saves the configuration to FILE.  The configuration            is written to standard output when FILE is a `-'.      GLOBBING-           Globbing  is  used  by options -g, --include, --include-dir, --include--           from, --exclude, --exclude-dir, --exclude-from to match  pathnames  and-           basenames  in  recursive  searches.   Glob  arguments for these options+           Globbing is used by options -g,  --include,  --include-dir,  --include-+           from,  --exclude,  --exclude-dir, --exclude-from to match pathnames and+           basenames in recursive searches.   Glob  arguments  for  these  options            should be quoted to prevent shell globbing. -           Globbing supports  gitignore  syntax  and  the  corresponding  matching-           rules.   When a glob ends in a path separator it matches directories as+           Globbing  supports  gitignore  syntax  and  the  corresponding matching+           rules.  When a glob ends in a path separator it matches directories  as            if --include-dir or --exclude-dir is specified.  When a glob contains a-           path  separator `/', the full pathname is matched.  Otherwise the base-+           path separator `/', the full pathname is matched.  Otherwise the  base-            name of a file or directory is matched.  For example, *.h matches foo.h-           and  bar/foo.h.   bar/*.h  matches  bar/foo.h  but  not  foo.h  and not-           bar/bar/foo.h.  Use a leading `/' to force /*.h to match foo.h but  not+           and bar/foo.h.   bar/*.h  matches  bar/foo.h  but  not  foo.h  and  not+           bar/bar/foo.h.   Use a leading `/' to force /*.h to match foo.h but not            bar/foo.h. -           When  a  glob  starts  with  a `^' or a `!' as in -g^GLOB, the match is+           When a glob starts with a `^' or a `!' as  in  -g^GLOB,  the  match  is            negated.  Likewise, a `!' (but not a `^') may be used with globs in the-           files  specified  --include-from, --exclude-from, and --ignore-files to-           negate the glob match.  Empty lines or lines starting with  a  `#'  are+           files specified --include-from, --exclude-from, and  --ignore-files  to+           negate  the  glob  match.  Empty lines or lines starting with a `#' are            ignored.             Glob Syntax and Conventions@@ -3996,12 +3998,12 @@ in markdown:             [!a-z] Matches one character not in the selected range of characters. -           /      When  used at the begin of a glob, matches if pathname has no /.+           /      When used at the begin of a glob, matches if pathname has no  /.                   When used at the end of a glob, matches directories only.             **/    Matches zero or more directories. -           /**    When used at the end of a glob, matches everything after the  /.+           /**    When  used at the end of a glob, matches everything after the /.             \?     Matches a ? (or any character specified after the backslash). @@ -4038,51 +4040,51 @@ in markdown:             a\?b   Matches a?b,                 but not a, b, ab, axb, a/b -           Note  that  exclude  glob patterns take priority over include glob pat--           terns  when  specified  with  options  -g,  --exclude,   --exclude-dir,+           Note that exclude glob patterns take priority over  include  glob  pat-+           terns   when  specified  with  options  -g,  --exclude,  --exclude-dir,            --include and include-dir. -           Glob  patterns specified with prefix `!' in any of the files associated-           with --include-from, --exclude-from and --ignore-files  will  negate  a-           previous  glob match.  That is, any matching file or directory excluded-           by a previous glob pattern  specified  in  the  files  associated  with-           --exclude-from  or --ignore-file will become included again.  Likewise,-           any matching file or directory included  by  a  previous  glob  pattern-           specified  in  the  files  associated  with  --include-from will become+           Glob patterns specified with prefix `!' in any of the files  associated+           with  --include-from,  --exclude-from  and --ignore-files will negate a+           previous glob match.  That is, any matching file or directory  excluded+           by  a  previous  glob  pattern  specified  in the files associated with+           --exclude-from or --ignore-file will become included again.   Likewise,+           any  matching  file  or  directory  included by a previous glob pattern+           specified in the  files  associated  with  --include-from  will  become            excluded again.      ENVIRONMENT            GREP_PATH-                  May be used to specify a file path to pattern files.   The  file-                  path  is used by option -f to open a pattern file, when the pat-+                  May  be  used to specify a file path to pattern files.  The file+                  path is used by option -f to open a pattern file, when the  pat-                   tern file does not exist.             GREP_EDITOR-                  May be used to specify an editor command to invoke  with  CTRL-Y-                  while  using  the  query UI with option -Q.  When undefined, the+                  May  be  used to specify an editor command to invoke with CTRL-Y+                  while using the query UI with option -Q.   When  undefined,  the                   command defined by EDITOR is invoked.             GREP_COLOR-                  May be used to specify ANSI SGR parameters to highlight  matches-                  when  option --color is used, e.g. 1;35;40 shows pattern matches+                  May  be used to specify ANSI SGR parameters to highlight matches+                  when option --color is used, e.g. 1;35;40 shows pattern  matches                   in bold magenta text on a black background.  Deprecated in favor                   of GREP_COLORS, but still supported.             GREP_COLORS-                  May  be used to specify ANSI SGR parameters to highlight matches-                  and other attributes when option --color is used.  Its value  is-                  a  colon-separated  list of ANSI SGR parameters that defaults to+                  May be used to specify ANSI SGR parameters to highlight  matches+                  and  other attributes when option --color is used.  Its value is+                  a colon-separated list of ANSI SGR parameters that  defaults  to                   cx=33:mt=1;31:fn=1;35:ln=1;32:cn=1;32:bn=1;32:se=36.   The  mt=,-                  ms=,  and  mc=  capabilities  of  GREP_COLORS take priority over+                  ms=, and mc= capabilities  of  GREP_COLORS  take  priority  over                   GREP_COLOR.  Option --colors takes priority over GREP_COLORS.      GREP_COLORS-           Colors are specified as string of colon-separated ANSI  SGR  parameters-           of  the  form  `what=substring', where `substring' is a semicolon-sepa--           rated list of ANSI SGR codes or `k' (black), `r'  (red),  `g'  (green),-           `y'  (yellow),  `b'  (blue),  `m'  (magenta),  `c' (cyan), `w' (white).-           Upper case specifies background colors.  A `+'  qualifies  a  color  as-           bright.   A  foreground and a background color may be combined with one+           Colors  are  specified as string of colon-separated ANSI SGR parameters+           of the form `what=substring', where `substring'  is  a  semicolon-sepa-+           rated  list  of  ANSI SGR codes or `k' (black), `r' (red), `g' (green),+           `y' (yellow), `b' (blue),  `m'  (magenta),  `c'  (cyan),  `w'  (white).+           Upper  case  specifies  background  colors.  A `+' qualifies a color as+           bright.  A foreground and a background color may be combined  with  one            or more font properties `n' (normal), `f' (faint), `h' (highlight), `i'            (invert), `u' (underline).  Substrings may be specified for: @@ -4094,10 +4096,10 @@ in markdown:             mt=    SGR substring for matching text in any matching line. -           ms=    SGR  substring  for  matching text in a selected line.  The sub-+           ms=    SGR substring for matching text in a selected  line.   The  sub-                   string mt= by default. -           mc=    SGR substring for matching text in a  context  line.   The  sub-+           mc=    SGR  substring  for  matching  text in a context line.  The sub-                   string mt= by default.             fn=    SGR substring for file names.@@ -4111,7 +4113,7 @@ in markdown:            se=    SGR substring for separators.      FORMAT-           Option  --format=FORMAT  specifies  an  output format for file matches.+           Option --format=FORMAT specifies an output  format  for  file  matches.            Fields may be used in FORMAT, which expand into the following values:             %[ARG]F@@ -4210,7 +4212,7 @@ in markdown:             %u     select unique lines only, unless option -u is used. -           %1     the  first  regex  group  capture  of the match, and so on up to+           %1     the first regex group capture of the match,  and  so  on  up  to                   group %9, same as %[1]#; requires option -P.             %[NUM]#@@ -4228,22 +4230,22 @@ in markdown:             %%     the percentage sign. -           The [ARG] part of a  field  is  optional  and  may  be  omitted.   When-           present,  the argument must be placed in [] brackets, for example %[,]F+           The  [ARG]  part  of  a  field  is  optional  and may be omitted.  When+           present, the argument must be placed in [] brackets, for example  %[,]F            to output a comma, the pathname, and a separator.             %[SEP]$ and %u are switches and do not send anything to the output. -           The separator used by %F, %H, %N, %K, %B, %S, and %G may be changed  by-           preceding  the  field  by  %[SEP]$.   When  [SEP] is not provided, this-           reverts the separator to the default separator or the separator  speci-+           The  separator used by %F, %H, %N, %K, %B, %S, and %G may be changed by+           preceding the field by %[SEP]$.   When  [SEP]  is  not  provided,  this+           reverts  the separator to the default separator or the separator speci-            fied with --separator.             Formatted output is written for each matching pattern, which means that-           a line may be output multiple times when patterns match more than  once-           on  the  same  line.   If  field  %u  is specified anywhere in a format+           a  line may be output multiple times when patterns match more than once+           on the same line.  If field  %u  is  specified  anywhere  in  a  format            string,  matching  lines  are  output  only  once,  unless  option  -u,-           --ungroup  is specified or when more than one line of input matched the+           --ungroup is specified or when more than one line of input matched  the            search pattern.             Additional formatting options:@@ -4314,7 +4316,7 @@ in markdown:                    $ ugrep -n -f c++/comments myfile.cpp -           List the lines that need fixing in a C/C++ source file by  looking  for+           List  the  lines that need fixing in a C/C++ source file by looking for            the word `FIXME' while skipping any `FIXME' in quoted strings:                    $ ugrep -e FIXME -N '"(\\.|\\\r?\n|[^\\\n"])*"' myfile.cpp@@ -4344,7 +4346,7 @@ in markdown:                    $ ugrep -z -tc++ -n FIXME project.tgz -           Recursively  find  lines with `FIXME' in C/C++ files, but do not search+           Recursively find lines with `FIXME' in C/C++ files, but do  not  search            any `bak' and `old' directories:                    $ ugrep -n FIXME -tc++ -g^bak/,^old/@@ -4354,9 +4356,9 @@ in markdown:                    $ ugrep -z -w --filter='pdf:pdftotext % -' copyright -           Match  the  binary  pattern `A3hhhhA3hh' (hex) in a binary file without-           Unicode pattern matching -U (which would otherwise match  `\xaf'  as  a-           Unicode  character  U+00A3  with UTF-8 byte sequence C2 A3) and display+           Match the binary pattern `A3hhhhA3hh' (hex) in a  binary  file  without+           Unicode  pattern  matching  -U (which would otherwise match `\xaf' as a+           Unicode character U+00A3 with UTF-8 byte sequence C2  A3)  and  display            the results in hex with -X using `less -R' as a pager:                    $ ugrep --pager -UXo '\xa3[\x00-\xff]{2}\xa3[\x00-\xff]' a.out@@ -4369,12 +4371,12 @@ in markdown:                    $ ugrep -l '' --ignore-files -           List all files containing a RPM signature, located in the `rpm'  direc-+           List  all files containing a RPM signature, located in the `rpm' direc-            tory and recursively below up to two levels deeper (3 levels total):                    $ ugrep -3 -l -tRpm '' rpm/ -           Monitor  the system log for bug reports and ungroup multiple matches on+           Monitor the system log for bug reports and ungroup multiple matches  on            a line:                    $ tail -f /var/log/system.log | ugrep -u -i -w bug@@ -4383,6 +4385,10 @@ in markdown:                    $ ugrep --encoding=MACROMAN '\w+' mac.txt +           Display options related to "fuzzy" searching:++                  $ ugrep --help fuzzy+     BUGS            Report bugs at: @@ -4390,8 +4396,8 @@ in markdown:       LICENSE-           ugrep is released under the BSD-3 license.  All parts of  the  software-           have  reasonable  copyright terms permitting free redistribution.  This+           ugrep  is  released under the BSD-3 license.  All parts of the software+           have reasonable copyright terms permitting free  redistribution.   This            includes the ability to reuse all or parts of the ugrep source tree.      SEE ALSO@@ -4399,7 +4405,7 @@ in markdown:   -    ugrep 3.0.4                    October 23, 2020                       UGREP(1)+    ugrep 3.0.5                    November 17, 2020                      UGREP(1)  🔝 [Back to table of contents](#toc) 

bin/win32/ugrep.exe

Binary file changed

bin/win64/ugrep.exe

Binary file changed

build.sh

@@ -11,8 +11,8 @@ esac echo echo "Building ugrep..." -# configure with colors enabled by default or the command arguments-OPTIONS=${@:---enable-color}+# configure with the specified command arguments+OPTIONS=$@  echo echo "./configure $OPTIONS"

configure

@@ -749,6 +749,7 @@ with_lzma with_lz4 with_grep_path with_grep_colors+enable_auto_color enable_color enable_pretty enable_pager@@ -1395,8 +1396,9 @@ Optional Features:                           do not reject slow dependency extractors   --disable-dependency-tracking                           speeds up one-time build-  --enable-color          enable colorized output by default without requiring-                          ugrep flag --color+  --disable-auto-color    disable automatic colors, otherwise colors are+                          enabled by default+  --enable-color          deprecated, use --disable-auto-color   --enable-pretty         enable pretty output by default without requiring                           ugrep flag --pretty   --enable-pager          enable the pager by default without requiring ugrep@@ -7738,19 +7740,34 @@ else $as_echo "" >&6; } fi +# Check whether --enable-auto-color was given.+if test "${enable_auto_color+set}" = set; then :+  enableval=$enable_auto_color; with_no_auto_color="yes"+else+  with_no_auto_color="no"+fi++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --disable-auto-color" >&5+$as_echo_n "checking for --disable-auto-color... " >&6; }+if test "x$with_no_auto_color" = "xno"; then+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5+$as_echo "no" >&6; }+  EXTRA_CFLAGS="-DWITH_COLOR ${EXTRA_CFLAGS}"+else+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5+$as_echo "yes" >&6; }+fi+ # Check whether --enable-color was given. if test "${enable_color+set}" = set; then :-  enableval=$enable_color; with_color="$enable_color"-else-  with_color="no"+  enableval=$enable_color; fi  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-color" >&5 $as_echo_n "checking for --enable-color... " >&6; }-if test "x$with_color" = "xyes"; then+if test "x$with_no_auto_color" = "xno"; then   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; }-  EXTRA_CFLAGS="-DWITH_COLOR ${EXTRA_CFLAGS}" else   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; }

configure.ac

@@ -102,15 +102,27 @@ else   AC_MSG_RESULT() fi +AC_ARG_ENABLE(auto-color,+  [AC_HELP_STRING([--disable-auto-color],+                  [disable automatic colors, otherwise colors are enabled by default])],+  [with_no_auto_color="yes"],+  [with_no_auto_color="no"])+AC_MSG_CHECKING(for --disable-auto-color)+if test "x$with_no_auto_color" = "xno"; then+  AC_MSG_RESULT(no)+  EXTRA_CFLAGS="-DWITH_COLOR ${EXTRA_CFLAGS}"+else+  AC_MSG_RESULT(yes)+fi+ AC_ARG_ENABLE(color,   [AC_HELP_STRING([--enable-color],-                  [enable colorized output by default without requiring ugrep flag --color])],-  [with_color="$enable_color"],-  [with_color="no"])+                  [deprecated, use --disable-auto-color])],+  [],+  []) AC_MSG_CHECKING(for --enable-color)-if test "x$with_color" = "xyes"; then+if test "x$with_no_auto_color" = "xno"; then   AC_MSG_RESULT(yes)-  EXTRA_CFLAGS="-DWITH_COLOR ${EXTRA_CFLAGS}" else   AC_MSG_RESULT(no) fi

include/reflex/input.h

@@ -357,6 +357,7 @@ class Input {       istream_(input.istream_),       size_(input.size_),       uidx_(input.uidx_),+      ulen_(input.ulen_),       utfx_(input.utfx_),       page_(input.page_)   {@@ -499,6 +500,7 @@ class Input {     istream_ = input.istream_;     size_ = input.size_;     uidx_ = input.uidx_;+    ulen_ = input.ulen_;     utfx_ = input.utfx_;     page_ = input.page_;     std::memcpy(utf8_, input.utf8_, sizeof(utf8_));@@ -651,11 +653,9 @@ class Input {     if (wstring_)     {       size_t k = n;-      if (uidx_ < sizeof(utf8_))+      if (ulen_ > 0)       {-        size_t l = 0;-        while (uidx_ + l < sizeof(utf8_) && utf8_[uidx_ + l] != '\0')-          ++l;+        size_t l = ulen_;         if (l > k)           l = k;         std::memcpy(s, utf8_ + uidx_, l);@@ -663,12 +663,13 @@ class Input {         if (k == 0)         {           uidx_ += static_cast<unsigned short>(l);+          ulen_ -= static_cast<unsigned short>(l);           if (size_ >= n)             size_ -= n;           return n;         }         s += l;-        uidx_ = sizeof(utf8_);+        ulen_ = 0;       }       wchar_t c;       while ((c = *wstring_) != L'\0' && k > 0)@@ -695,8 +696,8 @@ class Input {           }           if (k < l)           {-            utf8_[l] = '\0';             uidx_ = static_cast<unsigned short>(k);+            ulen_ = static_cast<unsigned short>(l);             std::memcpy(s, utf8_, k);             s += k;             k = 0;@@ -747,7 +748,8 @@ class Input {   void init(file_encoding_type enc = file_encoding::plain)   {     std::memset(utf8_, 0, sizeof(utf8_));-    uidx_ = sizeof(utf8_);+    uidx_ = 0;+    ulen_ = 0;     utfx_ = 0;     page_ = NULL;     if (file_ != NULL)@@ -777,8 +779,9 @@ class Input {   FILE                 *file_;    ///< FILE* input (when non-null)   std::istream         *istream_; ///< stream input (when non-null)   size_t                size_;    ///< size of the remaining input in bytes (size_ == 0 may indicate size is not set)-  char                  utf8_[8]; ///< UTF-8 normalization buffer-  unsigned short        uidx_;    ///< index in utf8_[] or >= 8 when unused+  char                  utf8_[8]; ///< UTF-8 normalization buffer, >=8 bytes+  unsigned short        uidx_;    ///< index in utf8_[]+  unsigned short        ulen_;    ///< length of data in utf8_[] or 0 if no data   file_encoding_type    utfx_;    ///< file_encoding   const unsigned short *page_;    ///< custom code page   Handler              *handler_; ///< to handle FILE* errors and non-blocking FILE* reads

lib/input.cpp

@@ -41,9 +41,9 @@  #if __cplusplus >= 201103L # include <tuple> // std::ignore-# define UNUSED(arg) std::ignore = enc+# define UNUSED(arg) std::ignore = arg #else-# define UNUSED(arg) (void)enc+# define UNUSED(arg) (void)arg #endif  #if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__)@@ -573,6 +573,25 @@ static const unsigned short codepages[38][256] =      224,   225,   226,0x0103,   228,0x0107,   230,   231,   232,   233,   234,   235,   236,   237,   238,   239,   0x0111,0x0144,   242,   243,   244,0x0151,   246,0x015B,0x0171,   249,   250,   251,   252,0x0119,0x021B,   255   },+  // Macintosh Roman to Unicode with CR to LF translation+  {+       0,     1,     2,     3,     4,     5,     6,     7,     8,     9,    10,    11,    12,0x000A,    14,    15,+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,    26,    27,    28,    29,    30,    31,+      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,    42,    43,    44,    45,    46,    47,+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,    58,    59,    60,    61,    62,    63,+      64,    65,    66,    67,    68,    69,    70,    71,    72,    73,    74,    75,    76,    77,    78,    79,+      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,    90,    91,    92,    93,    94,    95,+      96,    97,    98,    99,   100,   101,   102,   103,   104,   105,   106,   107,   108,   109,   110,   111,+     112,   113,   114,   115,   116,   117,   118,   119,   120,   121,   122,   123,   124,   125,   126,   127,+  0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,+  0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,+  0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,+  0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,+  0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,+  0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,+  0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,+  0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7+  },   // KOI8-R to Unicode   {        0,     1,     2,     3,     4,     5,     6,     7,     8,     9,    10,    11,    12,    13,    14,    15,@@ -630,25 +649,6 @@ static const unsigned short codepages[38][256] =   0x042E,0x0410,0x0411,0x0426,0x0414,0x0415,0x0424,0x0413,0x0425,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,   0x041F,0x042F,0x0420,0x0421,0x0422,0x0423,0x0416,0x0412,0x042C,0x042B,0x0417,0x0428,0x042D,0x0429,0x0427,0x042A   },-  // Macintosh Roman to Unicode with CR to LF translation-  {-       0,     1,     2,     3,     4,     5,     6,     7,     8,     9,    10,    11,    12,0x000A,    14,    15,-      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,    26,    27,    28,    29,    30,    31,-      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,    42,    43,    44,    45,    46,    47,-      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,    58,    59,    60,    61,    62,    63,-      64,    65,    66,    67,    68,    69,    70,    71,    72,    73,    74,    75,    76,    77,    78,    79,-      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,    90,    91,    92,    93,    94,    95,-      96,    97,    98,    99,   100,   101,   102,   103,   104,   105,   106,   107,   108,   109,   110,   111,-     112,   113,   114,   115,   116,   117,   118,   119,   120,   121,   122,   123,   124,   125,   126,   127,-  0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,-  0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,-  0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,-  0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,-  0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,-  0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,-  0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,-  0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7-  }, };  void Input::file_init(file_encoding_type enc)@@ -675,23 +675,22 @@ void Input::file_init(file_encoding_type enc)     // check first UTF BOM byte     if (::fread(utf8_, 1, 1, file_) == 1)     {-      utf8_[1] = '\0';-      uidx_ = 0;+      ulen_ = 1;       if (utf8_[0] == '\0' || utf8_[0] == '\xef' || utf8_[0] == '\xfe' || utf8_[0] == '\xff')       {         // check second UTF BOM byte         if (::fread(utf8_ + 1, 1, 1, file_) == 1)         {-          utf8_[2] = '\0';+          ulen_ = 2;           if (utf8_[0] == '\0' && utf8_[1] == '\0')  // UTF-32 big endian BOM 0000XXXX?           {-            if (::fread(utf8_ + 2, 2, 1, file_) == 1)+            if (::fread(&utf8_[2], 2, 1, file_) == 1)             {-              utf8_[4] = '\0';+              ulen_ = 4;               if (utf8_[2] == '\xfe' && utf8_[3] == '\xff') // UTF-32 big endian BOM 0000FEFF?               {                 size_ = 0;-                uidx_ = sizeof(utf8_);+                ulen_ = 0;                 utfx_ = file_encoding::utf32be;               }             }@@ -699,39 +698,38 @@ void Input::file_init(file_encoding_type enc)           else if (utf8_[0] == '\xfe' && utf8_[1] == '\xff') // UTF-16 big endian BOM FEFF?           {             size_ = 0;-            uidx_ = sizeof(utf8_);+            ulen_ = 0;             utfx_ = file_encoding::utf16be;           }           else if (utf8_[0] == '\xff' && utf8_[1] == '\xfe') // UTF-16 or UTF-32 little endian BOM FFFEXXXX?           {-            if (::fread(utf8_ + 2, 2, 1, file_) == 1)+            if (::fread(&utf8_[2], 2, 1, file_) == 1)             {-              utf8_[4] = '\0';               if (utf8_[2] == '\0' && utf8_[3] == '\0') // UTF-32 little endian BOM FFFE0000?               {                 size_ = 0;-                uidx_ = sizeof(utf8_);+                ulen_ = 0;                 utfx_ = file_encoding::utf32le;               }               else               {                 size_ = 0;-                utf8_[utf8(utf8_[2] | utf8_[3] << 8, utf8_)] = '\0';-                uidx_ = 0;+                uidx_ = 2;+                ulen_ = 4;                 utfx_ = file_encoding::utf16le;               }             }           }           else if (utf8_[0] == '\xef' && utf8_[1] == '\xbb') // UTF-8 BOM EFBBXX?           {-            if (::fread(utf8_ + 2, 1, 1, file_) == 1)+            if (::fread(&utf8_[2], 1, 1, file_) == 1)             {-              utf8_[3] = '\0';+              ulen_ = 3;               if (utf8_[2] == '\xbf') // UTF-8 BOM EFBBBF?               {                 if (size_ >= 3)                   size_ -= 3;-                uidx_ = sizeof(utf8_);+                ulen_ = 0;                 utfx_ = file_encoding::utf8;               }             }@@ -740,7 +738,7 @@ void Input::file_init(file_encoding_type enc)       }       break;     }-    if (feof(file_) || handler_ == NULL || (*handler_)() == 0)+    if (handler_ == NULL || feof(file_) || (*handler_)() == 0)       break;   } #if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__)@@ -755,21 +753,21 @@ void Input::file_init(file_encoding_type enc) size_t Input::file_get(char *s, size_t n) {   char *t = s;-  if (uidx_ < sizeof(utf8_))+  if (ulen_ > 0)   {-    unsigned short k = 0;-    unsigned short m = static_cast<unsigned short>(n < sizeof(utf8_) - uidx_ ? n : sizeof(utf8_) - uidx_);-    while (k < m && utf8_[uidx_ + k] != '\0')-      *t++ = utf8_[uidx_ + k++];+    size_t k = n < ulen_ ? n : ulen_;+    while (k-- > 0)+      *t++ = utf8_[uidx_++];+    k = t - s;     n -= k;     if (n == 0)     {-      uidx_ += k;+      ulen_ -= static_cast<unsigned short>(k);       if (size_ >= k)         size_ -= k;       return k;     }-    uidx_ = sizeof(utf8_);+    ulen_ = 0;   }   unsigned char buf[4];   switch (utfx_)@@ -797,8 +795,8 @@ size_t Input::file_get(char *s, size_t n)           if (n < l)           {             std::memcpy(t, utf8_, n);-            utf8_[l] = '\0';             uidx_ = static_cast<unsigned short>(n);+            ulen_ = static_cast<unsigned short>(l);             t += n;             n = 0;           }@@ -836,8 +834,8 @@ size_t Input::file_get(char *s, size_t n)           if (n < l)           {             std::memcpy(t, utf8_, n);-            utf8_[l] = '\0';             uidx_ = static_cast<unsigned short>(n);+            ulen_ = static_cast<unsigned short>(l);             t += n;             n = 0;           }@@ -867,8 +865,8 @@ size_t Input::file_get(char *s, size_t n)           if (n < l)           {             std::memcpy(t, utf8_, n);-            utf8_[l] = '\0';             uidx_ = static_cast<unsigned short>(n);+            ulen_ = static_cast<unsigned short>(l);             t += n;             n = 0;           }@@ -898,8 +896,8 @@ size_t Input::file_get(char *s, size_t n)           if (n < l)           {             std::memcpy(t, utf8_, n);-            utf8_[l] = '\0';             uidx_ = static_cast<unsigned short>(n);+            ulen_ = static_cast<unsigned short>(l);             t += n;             n = 0;           }@@ -936,7 +934,7 @@ size_t Input::file_get(char *s, size_t n)           else           {             uidx_ = 1;-            utf8_[2] = '\0';+            ulen_ = 2;           }         }       }@@ -989,8 +987,8 @@ size_t Input::file_get(char *s, size_t n)           if (n < l)           {             std::memcpy(t, utf8_, n);-            utf8_[l] = '\0';             uidx_ = static_cast<unsigned short>(n);+            ulen_ = static_cast<unsigned short>(l);             t += n;             n = 0;           }@@ -1184,7 +1182,7 @@ void Input::file_encoding(unsigned short enc, const unsigned short *page) {   if (file_ && utfx_ != enc)   {-    if (utfx_ == file_encoding::plain && uidx_ < sizeof(utf8_))+    if (utfx_ == file_encoding::plain && ulen_ > 0)     {       // translate (non-BOM) plain bytes (1 to 4 bytes) buffered in utf8_[]       unsigned char buf[sizeof(utf8_)];@@ -1195,7 +1193,7 @@ void Input::file_encoding(unsigned short enc, const unsigned short *page)       switch (enc)       {         case file_encoding::latin:-          for (unsigned short i = 0; *b != '\0'; ++i)+          while (ulen_-- > 0)           {             c1 = *b++;             if (c1 < 0x80)@@ -1203,8 +1201,8 @@ void Input::file_encoding(unsigned short enc, const unsigned short *page)             else               t += utf8(c1, t);           }-          *t = '\0';           uidx_ = 0;+          ulen_ = static_cast<unsigned short>(t - utf8_);           break;         case file_encoding::cp437:         case file_encoding::cp850:@@ -1238,7 +1236,7 @@ void Input::file_encoding(unsigned short enc, const unsigned short *page)         case file_encoding::koi8_u:         case file_encoding::koi8_ru:           page_ = codepages[enc - file_encoding::latin - 1];-          for (unsigned short i = 0; *b != '\0'; ++i)+          while (ulen_-- > 0)           {             c1 = page_[*b++];             if (c1 < 0x80)@@ -1246,14 +1244,14 @@ void Input::file_encoding(unsigned short enc, const unsigned short *page)             else               t += utf8(c1, t);           }-          *t = '\0';           uidx_ = 0;+          ulen_ = static_cast<unsigned short>(t - utf8_);           break;         case file_encoding::custom:           if (page)           {             page_ = page;-            for (unsigned short i = 0; *b != '\0'; ++i)+            while (ulen_-- > 0)             {               c1 = page_[*b++];               if (c1 < 0x80)@@ -1261,8 +1259,8 @@ void Input::file_encoding(unsigned short enc, const unsigned short *page)               else                 t += utf8(c1, t);             }-            *t = '\0';             uidx_ = 0;+            ulen_ = static_cast<unsigned short>(t - utf8_);           }           else           {@@ -1294,8 +1292,8 @@ void Input::file_encoding(unsigned short enc, const unsigned short *page)                 t += utf8(c1, t);                 t += utf8(c2, t);               }-              *t = '\0';               uidx_ = 0;+              ulen_ = static_cast<unsigned short>(t - utf8_);             }           }           break;@@ -1324,8 +1322,8 @@ void Input::file_encoding(unsigned short enc, const unsigned short *page)                 t += utf8(c1, t);                 t += utf8(c2, t);               }-              *t = '\0';               uidx_ = 0;+              ulen_ = static_cast<unsigned short>(t - utf8_);             }           }           break;@@ -1339,8 +1337,8 @@ void Input::file_encoding(unsigned short enc, const unsigned short *page)           {             c1 = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];             t += utf8(c1, t);-            *t = '\0';             uidx_ = 0;+            ulen_ = static_cast<unsigned short>(t - utf8_);           }           break;         case file_encoding::utf32le:@@ -1353,8 +1351,8 @@ void Input::file_encoding(unsigned short enc, const unsigned short *page)           {             c1 = buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24;             t += utf8(c1, t);-            *t = '\0';             uidx_ = 0;+            ulen_ = static_cast<unsigned short>(t - utf8_);           }           break;         default:

lib/pattern.cpp

@@ -721,8 +721,8 @@ void Pattern::parse3(       if (at(++loc) == '?')       {         if (++lazyidx == 0)-          error(regex_error::exceeds_limits, loc);-        lazyset.insert(lazyidx); // overflow: exceeds max 255 lazy quantifiers+          error(regex_error::exceeds_limits, loc); // overflow: exceeds max 255 lazy quantifiers+        lazyset.insert(lazyidx);         if (nullable)           lazy(lazyset, firstpos);         ++loc;@@ -784,9 +784,7 @@ void Pattern::parse3(             error(regex_error::exceeds_limits, loc); // overflow: exceeds max 255 lazy quantifiers           lazyset.insert(lazyidx);           if (nullable)-          {             lazy(lazyset, firstpos);-          }           /* CHECKED algorithmic options: 8/1 else              {              lazy(lazyset, firstpos, firstpos1);

makemake.sh

@@ -19,4 +19,4 @@ autoheader automake --add-missing --foreign autoconf automake-./configure --enable-color+./configure

man.sh

@@ -18,8 +18,8 @@ cat >> man/ugrep.1 << 'END' \fBugrep\fR, \fBug\fR -- file pattern searcher .SH SYNOPSIS .B ugrep-[\fIOPTIONS\fR] [\fB-A\fR \fINUM\fR] [\fB-B\fR \fINUM\fR] [\fB-C\fR[\fINUM\fR]] [\fIPATTERN\fR] [\fB-f\fR \fIFILE\fR]-      [\fB-e\fR \fIPATTERN\fR] [\fB-N\fR \fIPATTERN\fR] [\fB-t\fR \fITYPES\fR] [\fB-J\fR [\fINUM\fR]] [\fB--sort\fR[=\fIKEY\fR]]+[\fIOPTIONS\fR] [\fB-A\fR \fINUM\fR] [\fB-B\fR \fINUM\fR] [\fB-C \fR\fINUM\fR] [\fB-y\fR] [\fB-Q\fR|\fIPATTERN\fR] [\fB-f\fR \fIFILE\fR]+      [\fB-e\fR \fIPATTERN\fR] [\fB-N\fR \fIPATTERN\fR] [\fB-t\fR \fITYPES\fR] [\fB-g\fR \fIGLOBS\fR] [\fB--sort\fR[=\fIKEY\fR]]       [\fB--color\fR[=\fIWHEN\fR]|\fB--colour\fR[=\fIWHEN\fR]] [\fB--pager\fR[=\fICOMMAND\fR]] [\fIFILE\fR \fI...\fR] .SH DESCRIPTION The \fBugrep\fR utility searches any given input files, selecting lines that@@ -35,6 +35,9 @@ automatically normalized; otherwise, \fBugrep\fR assumes the input is ASCII, UTF-8, or raw binary.  An input encoding format may be specified with option \fB--encoding\fR. .PP+The \fBug\fR command is equivalent to \fBugrep --config\fR to load the default+configuration file, which allows for customization, see CONFIGURATION.+.PP If no \fIFILE\fR arguments are specified and standard input is read from a terminal, recursive searches are performed as if \fB-R\fR is specified.  To force reading from standard input, specify `-' as a \fIFILE\fR argument.@@ -47,8 +50,11 @@ Hidden files and directories are ignored in recursive searches.  Option \fB-.\fR (\fB--hidden\fR) includes hidden files and directories in recursive searches. .PP-The \fBug\fR command is equivalent to \fBugrep --config\fR to load the default-configuration file, which allows for customization, see CONFIGURATION.+A query interface is opened with \fB-Q\fR (\fB--query\fR) to interactively+specify search patterns and view search results.  Note that a \fIPATTERN\fR+argument should not be specified in this case.+.PP+For help, \fB--help \fIWHAT\fR displays help on options related to \fIWHAT\fR. .PP The following options are available: END@@ -517,6 +523,10 @@ $ tail -f /var/log/system.log | ugrep -u -i -w bug Display all words in a MacRoman-encoded file that has CR newlines: .IP $ ugrep --encoding=MACROMAN '\\w+' mac.txt+.PP+Display options related to "fuzzy" searching:+.IP+$ ugrep --help fuzzy .SH BUGS Report bugs at: .IP

man/ugrep.1

@@ -1,10 +1,10 @@-.TH UGREP "1" "October 23, 2020" "ugrep 3.0.4" "User Commands"+.TH UGREP "1" "November 17, 2020" "ugrep 3.0.5" "User Commands" .SH NAME \fBugrep\fR, \fBug\fR -- file pattern searcher .SH SYNOPSIS .B ugrep-[\fIOPTIONS\fR] [\fB-A\fR \fINUM\fR] [\fB-B\fR \fINUM\fR] [\fB-C\fR[\fINUM\fR]] [\fIPATTERN\fR] [\fB-f\fR \fIFILE\fR]-      [\fB-e\fR \fIPATTERN\fR] [\fB-N\fR \fIPATTERN\fR] [\fB-t\fR \fITYPES\fR] [\fB-J\fR [\fINUM\fR]] [\fB--sort\fR[=\fIKEY\fR]]+[\fIOPTIONS\fR] [\fB-A\fR \fINUM\fR] [\fB-B\fR \fINUM\fR] [\fB-C \fR\fINUM\fR] [\fB-y\fR] [\fB-Q\fR|\fIPATTERN\fR] [\fB-f\fR \fIFILE\fR]+      [\fB-e\fR \fIPATTERN\fR] [\fB-N\fR \fIPATTERN\fR] [\fB-t\fR \fITYPES\fR] [\fB-g\fR \fIGLOBS\fR] [\fB--sort\fR[=\fIKEY\fR]]       [\fB--color\fR[=\fIWHEN\fR]|\fB--colour\fR[=\fIWHEN\fR]] [\fB--pager\fR[=\fICOMMAND\fR]] [\fIFILE\fR \fI...\fR] .SH DESCRIPTION The \fBugrep\fR utility searches any given input files, selecting lines that@@ -20,6 +20,9 @@ automatically normalized; otherwise, \fBugrep\fR assumes the input is ASCII, UTF-8, or raw binary.  An input encoding format may be specified with option \fB--encoding\fR. .PP+The \fBug\fR command is equivalent to \fBugrep --config\fR to load the default+configuration file, which allows for customization, see CONFIGURATION.+.PP If no \fIFILE\fR arguments are specified and standard input is read from a terminal, recursive searches are performed as if \fB-R\fR is specified.  To force reading from standard input, specify `-' as a \fIFILE\fR argument.@@ -32,8 +35,11 @@ Hidden files and directories are ignored in recursive searches.  Option \fB-.\fR (\fB--hidden\fR) includes hidden files and directories in recursive searches. .PP-The \fBug\fR command is equivalent to \fBugrep --config\fR to load the default-configuration file, which allows for customization, see CONFIGURATION.+A query interface is opened with \fB-Q\fR (\fB--query\fR) to interactively+specify search patterns and view search results.  Note that a \fIPATTERN\fR+argument should not be specified in this case.+.PP+For help, \fB--help \fIWHAT\fR displays help on options related to \fIWHAT\fR. .PP The following options are available: .TP@@ -76,11 +82,10 @@ byte or invalid UTF.  Short options are \fB\-a\fR, \fB\-I\fR, \fB\-U\fR, \fB\-W\ \fB\-\-break\fR Adds a line break between results from different files. .TP-\fB\-C\fR[\fINUM\fR], \fB\-\-context[\fR=\fINUM\fR]+\fB\-C\fR \fINUM\fR, \fB\-\-context\fR=\fINUM\fR Print NUM lines of leading and trailing context surrounding each-match.  The default is 2 and is equivalent to \fB\-A\fR 2 \fB\-B\fR 2.  Places-a \fB\-\-group\-separator\fR between contiguous groups of matches.-No whitespace may be given between \fB\-C\fR and its argument NUM.+match.  Places a \fB\-\-group\-separator\fR between contiguous groups of+matches.  See also options \fB\-A\fR, \fB\-B\fR, and \fB\-y\fR. .TP \fB\-c\fR, \fB\-\-count\fR Only a count of selected lines is written to standard output.@@ -1092,6 +1097,10 @@ $ tail -f /var/log/system.log | ugrep -u -i -w bug Display all words in a MacRoman-encoded file that has CR newlines: .IP $ ugrep --encoding=MACROMAN '\\w+' mac.txt+.PP+Display options related to "fuzzy" searching:+.IP+$ ugrep --help fuzzy .SH BUGS Report bugs at: .IP

patterns/python/strings

@@ -1,4 +1,4 @@ '([^\\\n']|\\.)*' "([^\\\n"]|\\.)*"-'''('{0,2}([^\\']|\n)|\\.|\n)*'''-"""("{0,2}([^\\"]|\n)|\\.|\n)*"""+'''('{0,2}[^\\']|\\.|\n)*'''+"""("{0,2}[^\\"]|\\.|\n)*"""

src/ugrep.cpp

@@ -67,7 +67,7 @@ After this, you may want to test ugrep and install it (optional): */  // ugrep version-#define UGREP_VERSION "3.0.4"+#define UGREP_VERSION "3.0.5"  // disable mmap because mmap is almost always slower than the file reading speed improvements since 3.0.0 #define WITH_NO_MMAP@@ -120,28 +120,6 @@ After this, you may want to test ugrep and install it (optional):  #include <stringapiset.h> -// Convert a wide Unicode string to an UTF-8 string-std::string utf8_encode(const std::wstring &wstr)-{-  if (wstr.empty())-    return std::string();-  int size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast<int>(wstr.size()), NULL, 0, NULL, NULL);-  std::string str(size, 0);-  WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast<int>(wstr.size()), &str[0], size, NULL, NULL);-  return str;-}--// Convert a UTF-8 string to a wide Unicode String-std::wstring utf8_decode(const std::string &str)-{-  if (str.empty())-    return std::wstring();-  int size = MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast<int>(str.size()), NULL, 0);-  std::wstring wstr(size, 0);-  MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast<int>(str.size()), &wstr[0], size);-  return wstr;-}- #else  // not compiling for a windows OS@@ -557,7 +535,7 @@ void version(); void is_directory(const char *pathname); void cannot_decompress(const char *pathname, const char *message); -// open a file where - means stdin/stdout and ~ expands to home directory+// open a file where - means stdin/stdout and an initial ~ expands to home directory int fopen_smart(FILE **file, const char *filename, const char *mode) {   if (filename == NULL || *filename == '\0')@@ -570,9 +548,9 @@ int fopen_smart(FILE **file, const char *filename, const char *mode)   }    if (*filename == '~')-    return fopen_s(file, std::string(home_dir).append(filename + 1).c_str(), mode);+    return fopenw_s(file, std::string(home_dir).append(filename + 1).c_str(), mode); -  return fopen_s(file, filename, mode);+  return fopenw_s(file, filename, mode); }  // read a line from buffered input, returns true when eof@@ -1733,47 +1711,12 @@ struct Grep {         _setmode(fileno(source), _O_BINARY); #endif     }-    else-#ifdef OS_WIN-    {-      CREATEFILE2_EXTENDED_PARAMETERS params {-        sizeof(CREATEFILE2_EXTENDED_PARAMETERS),-        FILE_ATTRIBUTE_NORMAL,-        FILE_FLAG_SEQUENTIAL_SCAN,-        SECURITY_ANONYMOUS,-        NULL,-        NULL-      };-      std::wstring wpathname = utf8_decode(pathname);-      HANDLE hFile = CreateFile2(wpathname.c_str(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, &params);--      if (hFile == INVALID_HANDLE_VALUE)-        return false;--      int fd = _open_osfhandle(reinterpret_cast<intptr_t>(hFile), _O_RDONLY);--      if (fd == -1)-      { -        CloseHandle(hFile);-        return false; -      }--      file = _fdopen(fd, (flag_binary || flag_decompress ? "rb" : "r"));--      if (file == NULL)-      {-        _close(fd);-        return false;-      }-    }-#else-    if (fopen_s(&file, pathname, (flag_binary || flag_decompress ? "rb" : "r")) != 0)+    else if (fopenw_s(&file, pathname, (flag_binary || flag_decompress ? "rb" : "r")) != 0)     {       warning("cannot read", pathname);        return false;     }-#endif      // --filter: fork process to filter file, when applicable     if (!filter(file, pathname))@@ -3797,8 +3740,6 @@ void options(int argc, const char **argv)                   ;                 else if (strcmp(arg, "confirm") == 0)                   flag_confirm = true;-                else if (strcmp(arg, "context") == 0)-                  flag_after_context = flag_before_context = 2;                 else if (strncmp(arg, "context=", 8) == 0)                   flag_after_context = flag_before_context = strtopos(arg + 8, "invalid argument --context=");                 else if (strcmp(arg, "count") == 0)@@ -4242,16 +4183,13 @@ void options(int argc, const char **argv)            case 'C':             ++arg;-            if (*arg == '=' || isdigit(*arg))-            {+            if (*arg)               flag_after_context = flag_before_context = strtopos(&arg[*arg == '='], "invalid argument -C=");-              is_grouped = false;-            }+            else if (++i < argc)+              flag_after_context = flag_before_context = strtopos(argv[i], "invalid argument -C=");             else-            {-              flag_after_context = flag_before_context = 2;-              --arg;-            }+              usage("missing NUM argument for option -C");+            is_grouped = false;             break;            case 'c':@@ -6058,7 +5996,7 @@ void ugrep()   else     threads = std::min(arg_files.size() + flag_stdin, flag_jobs); -  // negative character classes do not match newlines+  // inverted character classes do not match newlines, e.g. [^x] matches anything except x and \n   reflex::convert_flag_type convert_flags = reflex::convert_flag::notnewline;    // not -U: convert regex to Unicode@@ -6483,7 +6421,7 @@ Grep::Type Grep::select(size_t level, const char *pathname, const char *basename     {       FILE *file; -      if (fopen_s(&file, pathname, (flag_binary || flag_decompress ? "rb" : "r")) != 0)+      if (fopenw_s(&file, pathname, (flag_binary || flag_decompress ? "rb" : "r")) != 0)       {         warning("cannot read", pathname);         return Type::SKIP;@@ -6671,7 +6609,7 @@ Grep::Type Grep::select(size_t level, const char *pathname, const char *basename           {             FILE *file; -            if (fopen_s(&file, pathname, (flag_binary || flag_decompress ? "rb" : "r")) != 0)+            if (fopenw_s(&file, pathname, (flag_binary || flag_decompress ? "rb" : "r")) != 0)             {               warning("cannot read", pathname);               return Type::SKIP;@@ -6828,7 +6766,7 @@ void Grep::recurse(size_t level, const char *pathname)       filename.assign(pathname).append(PATHSEPSTR).append(i);        FILE *file = NULL;-      if (fopen_s(&file, filename.c_str(), "r") == 0)+      if (fopenw_s(&file, filename.c_str(), "r") == 0)       {         if (!saved)         {@@ -9750,11 +9688,10 @@ void help(std::ostream& out)             byte or invalid UTF.  Short options are -a, -I, -U, -W, and -X.\n\     --break\n\             Adds a line break between results from different files.\n\-    -C[NUM], --context[=NUM]\n\+    -C NUM, --context=NUM\n\             Print NUM lines of leading and trailing context surrounding each\n\-            match.  The default is 2 and is equivalent to -A 2 -B 2.  Places\n\-            a --group-separator between contiguous groups of matches.\n\-            No whitespace may be given between -C and its argument NUM.\n\+            match.  Places a --group-separator between contiguous groups of\n\+            matches.  See also options -A, -B, and -y.\n\     -c, --count\n\             Only a count of selected lines is written to standard output.\n\             If -o or -u is specified, counts the number of patterns matched.\n\

src/ugrep.hpp

@@ -54,6 +54,8 @@ #include <strsafe.h> #include <string.h> #include <fcntl.h>+#include <errno.h>+#include <string>  #define STDIN_FILENO  0 #define STDOUT_FILENO 1@@ -98,6 +100,58 @@ inline int dupenv_s(char **ptr, const char *name)   return _dupenv_s(ptr, &len, name); } +// Convert a wide Unicode string to an UTF-8 string+inline std::string utf8_encode(const std::wstring &wstr)+{+  if (wstr.empty())+    return std::string();+  int size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast<int>(wstr.size()), NULL, 0, NULL, NULL);+  std::string str(size, 0);+  WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast<int>(wstr.size()), &str[0], size, NULL, NULL);+  return str;+}++// Convert a UTF-8 string to a wide Unicode String+inline std::wstring utf8_decode(const std::string &str)+{+  if (str.empty())+    return std::wstring();+  int size = MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast<int>(str.size()), NULL, 0);+  std::wstring wstr(size, 0);+  MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast<int>(str.size()), &wstr[0], size);+  return wstr;+}++// Open Unicode wide string UTF-8 encoded filename+inline int fopenw_s(FILE **file, const char *filename, const char *mode)+{+  *file = NULL;++  std::wstring wfilename = utf8_decode(filename);+  HANDLE hFile = CreateFileW(wfilename.c_str(), GENERIC_READ, FILE_SHARE_READ, SECURITY_ANONYMOUS, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);++  if (hFile == INVALID_HANDLE_VALUE)+    return errno = (GetLastError() == ERROR_ACCESS_DENIED ? EACCES : ENOENT);++  int fd = _open_osfhandle(reinterpret_cast<intptr_t>(hFile), _O_RDONLY);++  if (fd == -1)+  { +    CloseHandle(hFile);+    return errno = EINVAL; +  }++  *file = _fdopen(fd, mode);++  if (*file == NULL)+  {+    _close(fd);+    return errno;+  }++  return 0;+}+ #else  // not compiling for a windows OS@@ -139,8 +193,8 @@ inline int dupenv_s(char **ptr, const char *name)   return 0; } -// Windows-compatible fopen_s()-inline int fopen_s(FILE **file, const char *filename, const char *mode)+// Open Unicode wide string UTF-8 encoded filename+inline int fopenw_s(FILE **file, const char *filename, const char *mode) { #if defined(HAVE_F_RDAHEAD)   if (strchr(mode, 'a') == NULL && strchr(mode, 'w') == NULL)@@ -160,10 +214,10 @@ inline int fopen_s(FILE **file, const char *filename, const char *mode) // platform -- see configure.ac #if !defined(PLATFORM) # if defined(OS_WIN)-#  if defined(_WIN32)-#   define PLATFORM "WIN32"-#  elif defined(_WIN64)+#  if defined(_WIN64) #   define PLATFORM "WIN64"+#  elif defined(_WIN32)+#   define PLATFORM "WIN32" #  else #   define PLATFORM "WIN" #  endif