Structural search and replace
Find and rewrite MeTTa by structure, not by text. You write a pattern as an ordinary MeTTa term; it matches wherever a form has that shape, whatever the whitespace or the names bound to the capture variables. It is the same idea as ; @suppress (suppress <pattern> …) and the lint rules: code as data, matched by the structural engine, never evaluated.
Patterns
A pattern is one well-formed form. Inside it:
$X,$Name(leading capital) captures one subterm, and reappears in the replacement. Repeating$Xrequires the same subterm both times.$$$matches a run of arguments;$$$restcaptures it for the replacement.$_matches anything without capturing.- Everything else, a symbol, number, or string, matches itself.
From the command line
bash
# Every (if True …) in a file, with its location:
metta-lsp search app.metta "(if True $T $E)"
# Rewrite each to its then-branch (prints the result; add --write to apply):
metta-lsp replace app.metta "(if True $T $E)" "$T"
# Rename a call across a file, keeping its arguments:
metta-lsp replace app.metta "(old-api $$$args)" "(new-api $$$args)" --writesearch also takes --json for tooling. replace prints the rewritten source by default and only touches the file with --write.
Programmatically
ts
import { search, replace } from "metta-ts-lsp/dsl";
search(source, "(if True $T $E)"); // → the matches, with offsets
replace(source, "(foo $X)", "(bar $X)"); // → the rewritten source stringOverlapping matches (a pattern that hits a form and a form nested inside it) are applied non-overlapping and right-to-left, so no rewrite lands inside another.