Search
mix ex_ast.search 'PATTERN' PATH [OPTIONS]
Search files for AST pattern matches. PATH can be a file, directory, or glob.
Options
| Flag | Meaning |
|---|---|
--count | Print match count only |
--limit N | Stop after N matches |
--allow-broad | Allow patterns like _ that match everything |
--inside PATTERN | Only match inside ancestors matching pattern |
--not-inside PATTERN | Reject matches inside ancestors matching pattern |
--parent PATTERN | Direct semantic parent matches pattern |
--not-parent PATTERN | Direct semantic parent does not match pattern |
--ancestor PATTERN | Any semantic ancestor matches pattern |
--not-ancestor PATTERN | No ancestor matches pattern |
--has-child PATTERN | Has a direct child matching pattern |
--not-has-child PATTERN | No direct child matches pattern |
--contains PATTERN | Has a descendant matching pattern |
--not-contains PATTERN | No descendant matches pattern |
--follows PATTERN | Previous sibling matches pattern |
--not-follows PATTERN | No previous sibling matches pattern |
--precedes PATTERN | Following sibling matches pattern |
--not-precedes PATTERN | No following sibling matches pattern |
--immediately-follows PATTERN | Immediately previous sibling matches pattern |
--immediately-precedes PATTERN | Immediately following sibling matches pattern |
--first | First sibling in parent |
--not-first | Not first sibling |
--last | Last sibling in parent |
--not-last | Not last sibling |
--nth N | Nth sibling (1-based) |
--not-nth N | Not nth sibling |
--comment TEXT | Associated comments contain TEXT |
--not-comment TEXT | No associated comments contain TEXT |
--comment-before TEXT | Comment immediately before contains TEXT |
--comment-after TEXT | Comment immediately after contains TEXT |
--comment-inside TEXT | Comment inside range contains TEXT |
--comment-inline TEXT | Inline comment on start line contains TEXT |
Comment values are substring matches. Use /.../ for regex:
mix ex_ast.search 'def _ do ... end' --comment-inside '/TODO|FIXME/'
Examples
# Find all IO.inspect calls
mix ex_ast.search 'IO.inspect(_)' lib/
# Find structs by field
mix ex_ast.search '%Step{id: "subject"}' lib/
# Only inside private functions
mix ex_ast.search --inside 'defp _ do _ end' 'Repo.get!(_, _)'
# Count matches
mix ex_ast.search --count 'dbg(_)' lib/
Replace
mix ex_ast.replace 'PATTERN' 'REPLACEMENT' PATH [OPTIONS]
Replace AST pattern matches in files. Captures from the pattern are substituted into the replacement by name.
Options
Same relationship filters as search. Additional:
| Flag | Meaning |
|---|---|
--dry-run | Preview changes without writing files |
Examples
# Remove debug calls
mix ex_ast.replace 'dbg(expr)' 'expr' lib/
# Migrate API
mix ex_ast.replace 'Repo.get!(mod, id)' 'Repo.get!(mod, id) || raise NotFoundError' lib/
# Preview without writing
mix ex_ast.replace --dry-run 'use Mix.Config' 'import Config' lib/
# Only outside tests
mix ex_ast.replace --not-inside 'test _ do _ end' 'IO.inspect(expr)' 'expr' lib/
Diff
mix ex_ast.diff FILE1 FILE2 [OPTIONS]
Syntax-aware diff between two Elixir files.
Options
| Flag | Meaning |
|---|---|
--summary | Print summary lines only |
--no-moves | Disable move detection |
--no-color | Disable colored output |
--json | Print edits as JSON |
Example output
lib/old.ex ↔ lib/new.ex
L2 UPDATE updated function def first/0
- def first, do: 1
+ def first, do: 10
L5 INSERT inserted function def fourth/0
+ def fourth, do: 4
2 edit(s)