rg
rg (ripgrep) is a fast recursive search tool that respects ignore files
by default.
This module constructs
ward.process.cmd(...)invocations; it does not parse output. consumers can usewardlib.tools.out(or their own parsing) on the:output()result.
Import
local Rg = require("wardlib.app.rg").Rg
Exit codes
rg uses exit codes that often surprise users:
- 0: at least one match was found
- 1: no matches were found
- 2: an error occurred
When you want “no matches” to be a non-failure, use wardlib.tools.out with
:allow_fail() and interpret res.code.
API
Rg.bin
Executable name or path (default: "rg").
Rg.search(pattern, paths, opts)
Builds: rg <opts...> -e <pattern>... [paths...]
pattern:string|string[]- Always emitted using
-e <pattern>(possibly repeated) to avoid ambiguity when patterns start with-.
- Always emitted using
paths:string|string[]|nil- If
nil, ripgrep searches the current directory.
- If
Rg.files(paths, opts)
Builds: rg <opts...> --files [paths...]
Rg.raw(argv, opts)
Builds: rg <opts...> <argv...>
Use this when you need an rg feature not modeled in RgOpts.
Options
RgOpts
Matching behavior:
fixed: boolean?→-F(fixed strings)ignore_case: boolean?→-ismart_case: boolean?→-Scase_sensitive: boolean?→-sword: boolean?→-wline: boolean?→-xinvert: boolean?→-v
Output / formatting:
count: boolean?→-c(count matching lines)count_matches: boolean?→--count-matchesquiet: boolean?→-qline_number: boolean?→-ncolumn: boolean?→--columnheading: boolean?→--headingno_filename: boolean?→--no-filename(mutually exclusive withwith_filename)with_filename: boolean?→--with-filename(mutually exclusive withno_filename)vimgrep: boolean?→--vimgrepjson: boolean?→--json(JSON Lines / NDJSON)
Context / limits:
after_context: number?→-A <n>before_context: number?→-B <n>context: number?→-C <n>(mutually exclusive withafter_context/before_context)max_count: number?→-m <n>threads: number?→-j <n>
Filesystem behavior:
follow: boolean?→-L(follow symlinks)hidden: boolean?→--hiddenno_ignore: boolean?→--no-ignoreno_ignore_vcs: boolean?→--no-ignore-vcs
Filtering:
glob: string|string[]?→-g <glob>(repeatable)type: string|string[]?→--type <type>(repeatable)type_not: string|string[]?→--type-not <type>(repeatable)files_with_matches: boolean?→--files-with-matchesfiles_without_match: boolean?→--files-without-match
Replacement:
replace: string?→-r <replacement>
Other:
color: boolean|string?→--color[=WHEN]- If
true, emits--color=auto. - If a string, emits
--color=<value>.
- If
extra: string[]?→ extra argv appended after modeled options
Examples
Basic search
local Rg = require("wardlib.app.rg").Rg
-- rg -F -S --hidden -g '*.lua' -g '!vendor/**' --type lua -C 2 --color=never -e TODO . src
local cmd = Rg.search("TODO", { ".", "src" }, {
fixed = true,
smart_case = true,
hidden = true,
glob = { "*.lua", "!vendor/**" },
type = "lua",
context = 2,
color = "never",
})
cmd:run()
Treat “no matches” as non-failure
local Rg = require("wardlib.app.rg").Rg
local out = require("wardlib.tools.out")
local o = out.cmd(Rg.search("needle", ".", { fixed = true }))
:label("rg search")
:allow_fail()
local res = o:res() -- access the underlying CmdResult
if res.code == 0 then
local lines = out.res(res):lines()
-- matches present
elseif res.code == 1 then
-- no matches (not an error)
else
-- res.code == 2 (or other) – treat as error
error("rg failed: " .. tostring(res.code))
end
Parse --json output (NDJSON)
local Rg = require("wardlib.app.rg").Rg
local out = require("wardlib.tools.out")
local events = out.cmd(Rg.search("TODO", ".", { json = true }))
:label("rg --json")
:json_lines()
-- events is an array of decoded JSON objects (one per line)
-- You can filter for { type = "match" } events, etc.
List files ripgrep would search
local Rg = require("wardlib.app.rg").Rg
-- rg --files .
local cmd = Rg.files(".")
cmd:run()