Search and replace Elixir code by AST pattern.
Patterns are valid Elixir syntax:
- Variables (
name,expr) capture matched nodes _and_nameare wildcards- Structs/maps match partially
- Pipes are normalized (
data |> Enum.map(f)matchesEnum.map(data, f)) - Everything else matches literally
Options
:inside— only match nodes inside an ancestor matching this pattern:not_inside— reject nodes inside an ancestor matching this pattern
Examples
# Find all IO.inspect calls
ExAST.search("lib/**/*.ex", "IO.inspect(_)")
# Find IO.inspect only inside test blocks
ExAST.search("test/", "IO.inspect(_)", inside: "test _ do _ end")
# Replace dbg with the expression itself
ExAST.replace("lib/**/*.ex", "dbg(expr)", "expr")
# Match piped and direct calls interchangeably
ExAST.search("lib/", "Enum.map(_, _)") # also finds `data |> Enum.map(f)`
Summary
Types
@type match() :: %{ file: String.t(), line: pos_integer(), source: String.t(), captures: ExAST.Pattern.captures() }
Functions
@spec replace(String.t() | [String.t()], String.t(), String.t(), keyword()) :: [ {String.t(), pos_integer()} ]
Replaces AST pattern matches in files.
Options:
:dry_run— return changes without writing (default:false):inside— only replace inside ancestors matching this pattern:not_inside— skip replacements inside ancestors matching this pattern
Returns a list of {file, count} tuples for modified files.
Searches files for AST pattern matches.
Returns a list of match maps with :file, :line, :source, and :captures.
Accepts :inside and :not_inside options to filter by context.