# nimgrep User's manual

Theme:

- Manual
- Standard library
- Index
- Compiler docs
- Fusion docs
- devel, stable

Search:
Group by:
Source Edit

Author: | Andreas Rumpf
Version: | 1.6.0

Nimgrep is a command line tool for search and replace tasks. It can search for regex or peg patterns and can search whole directories at once. User confirmation for every single replace operation can be requested.

Nimgrep has particularly good support for Nim's eccentric style insensitivity (see option `-y` below). Apart from that it is a generic text manipulation tool.

# Installation

Compile nimgrep with the command:

    nim c -d:release tools/nimgrep.nim

And copy the executable somewhere in your `$PATH`.

# Command line switches

Usage:

- To search:

      nimgrep [options] PATTERN [(FILE/DIRECTORY)*/-]

- To replace:

      nimgrep [options] PATTERN --replace REPLACEMENT (FILE/DIRECTORY)*/-

- To list file names:

      nimgrep [options] --filenames [PATTERN] [(FILE/DIRECTORY)*]

Positional arguments, from left to right:

1. PATTERN is either Regex (default) or Peg if `--peg` is specified. PATTERN and REPLACEMENT should be skipped when `--stdin` is specified.
2. REPLACEMENT supports `$1`, `$#` notations for captured groups in PATTERN.
   Danger: `--replace` mode DOES NOT ask confirmation unless `--confirm` is specified!
3. Final arguments are a list of paths (FILE/DIRECTORY) or a standalone minus `-` or not specified (empty):
   - empty, current directory `.` is assumed (not with `--replace`)
     Note: so when no FILE/DIRECTORY/`-` is specified nimgrep does not read the pipe, but searches files in the current dir instead!
   - `-`, read buffer once from stdin: pipe or terminal input; in `--replace` mode the result is directed to stdout; it's not compatible with `--stdin`, `--filenames`, or `--confirm`

   For any given DIRECTORY nimgrep searches only its immediate files without traversing subdirectories unless `--recursive` is specified.

In replacement mode we require all 3 positional arguments to avoid damaging.

Options:

- Mode of operation:
  `--find, -f`
  find the PATTERN (default)
  `--replace, -!`
  replace the PATTERN to REPLACEMENT, rewriting the files
  `--confirm`
  confirm each occurrence/replacement; there is a chance to abort any time without touching the file
  `--filenames`
  just list filenames. Provide a PATTERN to find it in the filenames (not in the contents of a file) or run with empty pattern to just list all files:

      nimgrep --filenames               # In current dir
      nimgrep --filenames "" DIRECTORY
       # Note empty pattern "", lists all files in DIRECTORY

- Interprete patterns:
  `--peg`
  PATTERN and PAT are Peg
  `--re`
  PATTERN and PAT are regular expressions (default)
  `--rex, -x`
  use the "extended" syntax for the regular expression so that whitespace is not significant
  `--word, -w`
  matches should have word boundaries (buggy for pegs!)
  `--ignoreCase, -i`
  be case-insensitive in PATTERN and PAT
  `--ignoreStyle, -y`
  be style insensitive in PATTERN and PAT
  Note: PATTERN and patterns PAT (see below in other options) are all either Regex or Peg simultaneously and options `--rex`, `--word`, `--ignoreCase`, and `--ignoreStyle` are applied to all of them.
- File system walk:
  `--recursive, -r`
  process directories recursively
  `--follow`
  follow all symlinks when processing recursively
  `--sortTime, -s[:asc|desc]`
  order files by the last modification time (default: off): ascending (recent files go last) or descending
- Filter files (based on filesystem paths):
  Hint: Instead of `not` you can type just `n` for negative options below.
  `--ex[tensions]:EX1|EX2|...`
  only search the files with the given extension(s), empty one (`--ex`) means files with missing extension
  `--notex[tensions]:EX1|EX2|...`
  exclude files having given extension(s), use empty one to skip files with no extension (like some binary files are)
  `--fi[lename]:PAT`
  search only files whose name matches pattern PAT
  `--notfi[lename]:PAT`
  skip files whose name matches pattern PAT
  `--di[rname]:PAT`
  select files that in their path have a directory name that matches pattern PAT
  `--notdi[rname]:PAT`
  do not descend into directories whose name (not path) matches pattern PAT
  `--dirp[ath]:PAT`
  select only files whose whole relative directory path matches pattern PAT
  `--notdirp[ath]:PAT`
  skip files whose whole relative directory path matches pattern PAT
- Filter files (based on file contents):
  `--inF[ile]:PAT`
  select files containing a (not displayed) match of PAT
  `--notinF[ile]:PAT`
  skip files containing a match of PAT
  `--bin:on|off|only`
  process binary files? (detected by 0 in first 1K bytes) (default: on - binary and text files treated the same way)
  `--text, -t`
  process only text files, the same as `--bin:off`
- Filter matches:
  `--inC[ontext]:PAT`
  select only matches containing a match of PAT in their surrounding context (multiline with `-c`, `-a`, `-b`)
  `--notinC[ontext]:PAT`
  skip matches not containing a match of PAT in their surrounding context
- Represent results:
  `--nocolor`
  output will be given without any colors
  `--color[:on]`
  force color even if output is redirected (default: auto)
  `--colorTheme:THEME`
  select color THEME from `simple` (default), `bnw` (black and white), `ack`, or `gnu` (GNU grep)
  `--count`
  only print counts of matches for files that matched
  `--context:N, -c:N`
  print N lines of leading context before every match and N lines of trailing context after it (default N: 0)
  `--afterContext:N, -a:N`
  print N lines of trailing context after every match
  `--beforeContext:N, -b:N`
  print N lines of leading context before every match
  `--group, -g`
  group matches by file
  `--newLine, -l`
  display every matching line starting from a new line
  `--cols[:N]`
  limit max displayed columns/width of output lines from files by N characters, cropping overflows (default: off)
  `--cols:auto, -%`
  calculate columns from terminal width for every line
  `--onlyAscii, -@`
  display only printable ASCII Latin characters 0x20-0x7E substitutions: 0 -> ^@, 1 -> ^A, ... 0x1F -> ^_, 0x7F -> '7F, ..., 0xFF -> 'FF
- Miscellaneous:
  `--threads:N, -j:N`
  speed up search by N additional workers (default: 0, off)
  `--stdin`
  read PATTERN from stdin (to avoid the shell's confusing quoting rules) and, if `--replace` given, REPLACEMENT
  `--verbose`
  be verbose: list every processed file
  `--help, -h`
  shows this help
  `--version, -v`
  shows the version

## Path filter options

Let us assume we have file `dirA/dirB/dirC/file.nim`. Filesystem path options will match for these parts of the path:

option | matches for
--- | ---
`--[not]extensions` | `nim`
`--[not]filename` | `file.nim`
`--[not]dirname` | `dirA` and `dirB` and `dirC`
`--[not]dirpath` | `dirA/dirB/dirC`

## Combining multiple filter options together and negating them

Options for filtering can be provided multiple times so they form a list, which works as:

- positive filters `--filename`, `--dirname`, `--dirpath`, `--inContext`, `--inFile` accept files/matches if any pattern from the list is hit
- negative filters `--notfilename`, `--notdirname`, `--notdirpath`, `--notinContext`, `--notinFile` accept files/matches if no pattern from the list is hit.

In other words the same filtering option repeated many times means logical OR.

Important: Different filtering options are related by logical AND: they all must be true for a match to be accepted. E.g. `--filename:F --dirname:D1 --notdirname:D2` means `filename(F) AND dirname(D1) AND (NOT dirname(D2))`.

So negative filtering patterns are effectively related by logical OR also: `(NOT PAT1) AND (NOT PAT2) == NOT (PAT1 OR PAT2)` in pseudo-code.

That means you can always use only 1 such an option with logical OR, e.g. `--notdirname:PAT1 --notdirname:PAT2` is fully equivalent to `--notdirname:'PAT1|PAT2'`.

Note:

If you want logical AND on patterns you should compose 1 appropriate pattern, possibly combined with multi-line mode `(?s)`. E.g. to require that multi-line context of matches has occurrences of both PAT1 and PAT2 use positive lookaheads (`(?=PAT)`):

    nimgrep --inContext:'(?s)(?=.*PAT1)(?=.*PAT2)'

# Meaning of `^` and `$`

`nimgrep` PCRE engine is run in a single-line mode so `^` matches the beginning of whole input file and `$` matches the end of file (or whole input string for options like `--filename`).

Add the `(?m)` modifier to the beginning of your pattern for `^` and `$` to match the beginnings and ends of lines.

# Examples

All examples below use default PCRE Regex patterns:

- To search recursively in Nim files using style-insensitive identifiers:

      nimgrep --recursive --ext:'nim|nims' --ignoreStyle
      # short: -r --ext:'nim|nims' -y

  Note: we used `'` quotes to avoid special treatment of `|` symbol for shells like Bash

- To exclude version control directories (Git, Mercurial=hg, Subversion=svn) from the search:

      nimgrep --notdirname:'^\.git$' --notdirname:'^\.hg$' --notdirname:'^\.svn$'
      # short: --ndi:'^\.git$' --ndi:'^\.hg$' --ndi:'^\.svn$'

- To search only in paths containing the `tests` sub-directory recursively:

      nimgrep --recursive --dirname:'^tests$'
      # short: -r --di:'^tests$'
      # or using --dirpath:
      nimgrep --recursive --dirpath:'(^|/)tests($|/)'
      # short: -r --pa:'(^|/)tests($|/)'

- Nimgrep can search multi-line, e.g. to find files containing `import` and then `strutils` use pattern `'import(.|\n)*?strutils'`.