mix ex_ast.search 'PATTERN' PATH [OPTIONS]

Search files for AST pattern matches. PATH can be a file, directory, or glob.

Options

FlagMeaning
--countPrint match count only
--limit NStop after N matches
--allow-broadAllow patterns like _ that match everything
--inside PATTERNOnly match inside ancestors matching pattern
--not-inside PATTERNReject matches inside ancestors matching pattern
--parent PATTERNDirect semantic parent matches pattern
--not-parent PATTERNDirect semantic parent does not match pattern
--ancestor PATTERNAny semantic ancestor matches pattern
--not-ancestor PATTERNNo ancestor matches pattern
--has-child PATTERNHas a direct child matching pattern
--not-has-child PATTERNNo direct child matches pattern
--contains PATTERNHas a descendant matching pattern
--not-contains PATTERNNo descendant matches pattern
--follows PATTERNPrevious sibling matches pattern
--not-follows PATTERNNo previous sibling matches pattern
--precedes PATTERNFollowing sibling matches pattern
--not-precedes PATTERNNo following sibling matches pattern
--immediately-follows PATTERNImmediately previous sibling matches pattern
--immediately-precedes PATTERNImmediately following sibling matches pattern
--firstFirst sibling in parent
--not-firstNot first sibling
--lastLast sibling in parent
--not-lastNot last sibling
--nth NNth sibling (1-based)
--not-nth NNot nth sibling
--comment TEXTAssociated comments contain TEXT
--not-comment TEXTNo associated comments contain TEXT
--comment-before TEXTComment immediately before contains TEXT
--comment-after TEXTComment immediately after contains TEXT
--comment-inside TEXTComment inside range contains TEXT
--comment-inline TEXTInline 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:

FlagMeaning
--dry-runPreview 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

FlagMeaning
--summaryPrint summary lines only
--no-movesDisable move detection
--no-colorDisable colored output
--jsonPrint 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)