Skip to content

std.text.search

std.text.search is the shipped v1 file-walking gateway from filesystem bytes to text processing. It walks files through a bridge-backed handle, searches line by line, and returns either a match count or the first match position.

The current implementation is intentionally smaller than the long-term search algebra: typed queries come from std.text.rex, raw queries use the bounded rex grammar, literal queries match exact bytes, and capability-bearing variants make read-path authority explicit.

Proof command:

Terminal window
cd janus
./scripts/zb test-text-search
use std.text.search as search
use std.text.rex as rex
const raw = rex.raw("\\d+")
const exact = rex.literal("call(foo)")

rex.raw builds a bounded-rex query. rex.literal treats punctuation and rex metacharacters as ordinary bytes.

pub struct SearchConfig {
ignore_git: bool,
ignore_hidden: bool,
follow_symlinks: bool,
binary_detection: bool,
max_depth: i32,
}
pub struct SearchMatch {
path: *u8,
line: u64,
column: u64,
text: *u8,
}
pub struct Walk {
_handle: usize,
}

SearchMatch.line and SearchMatch.column are 1-based. A missing first match returns zero line and column with null pointer fields.

const cfg = search.defaultConfig()
let w = search.walkWith("src", cfg)
let shallow = search.withMaxDepth(w, 2)
let include_hidden = search.respectHidden(shallow, false)

Available walk helpers:

FunctionPurpose
defaultConfig()Returns recursive defaults: respect gitignore, skip hidden files, skip binary-looking files, unlimited depth.
walk(path)Creates a default walker for a file or directory.
walkWith(path, config)Creates a walker with explicit config.
respectGitignore(w, value)Returns a walker with gitignore handling changed.
respectHidden(w, value)Returns a walker with hidden-file handling changed.
withMaxDepth(w, depth)Returns a walker with an explicit max directory depth.

follow_symlinks is carried in SearchConfig for the public contract. The v1 bridge does not follow symlinks.

let raw_count = search.searchPath("notes.txt", "\\d+")
const q = rex.literal("call(foo)")
let exact_count = search.searchPathQuery("notes.txt", q)
let first = search.searchPathFirstQuery("notes.txt", q)

Available search helpers:

FunctionPurpose
search[T](w, pattern)Counts matches for a raw bounded-rex pattern.
searchQuery[T](w, query)Counts matches for a typed raw or literal search query.
searchFirst[T](w, pattern)Returns the first raw-pattern match.
searchFirstQuery[T](w, query)Returns the first typed-query match.
searchPath(path, pattern)Creates a default walker and counts raw-pattern matches.
searchPathQuery(path, query)Creates a default walker and counts typed-query matches.
searchPathFirst(path, pattern)Creates a default walker and returns the first raw-pattern match.
searchPathFirstQuery(path, query)Creates a default walker and returns the first typed-query match.

Read-path authority can be made explicit through std.os.caps.RpathCap:

use std.os.caps as caps
use std.text.search as search
use std.text.rex as rex
const cap = caps.unsafe_forge_rpath_cap()
const q = rex.literal("TODO")
let count = search.searchPathQuery_sovereign(cap, "src", q)

The shipped capability-bearing helpers are:

  • walk_sovereign
  • walkWith_sovereign
  • searchPath_sovereign
  • searchPathQuery_sovereign
  • searchPathFirstQuery_sovereign

In production code, prefer manifest or pledge-derived capabilities. The unsafe forge helper is for smokes and explicit operator escape hatches.

The v1 surface does not yet ship:

  • typed capture structs
  • $1, $2, or named capture result fields
  • ordered parallel search
  • ripgrep’s full engine
  • streaming integration through callback or materialization operators
  • symlink traversal

Those are future layers. Today, std.text.search is the small, proven file-walking bridge over raw patterns and rex.TextQuery values.