# `Igniter.Code.Pattern`
[🔗](https://github.com/ash-project/igniter/blob/v0.8.3/lib/igniter/code/pattern.ex#L5)

Pattern-based AST navigation and rewriting powered by ExAST.

Requires `{:ex_ast, "~> 0.5"}` (included as a dependency of Igniter).

## Pattern syntax

Patterns are valid Elixir expressions:

| Syntax | Meaning |
|--------|---------|
| `_` or `_name` | Wildcard — matches any node, not captured |
| `name`, `expr` | Capture — matches any node, bound by name |
| `...` | Ellipsis — matches zero or more nodes |
| Everything else | Literal — must match exactly |

Structs and maps match partially, pipes are normalized.

## Examples

    # Move to a node matching a pattern
    {:ok, zipper} = Pattern.move_to(zipper, "Repo.get!(_, _)")

    # Ellipsis — match any arity
    {:ok, zipper} = Pattern.move_to(zipper, "Logger.info(...)")

    # Check if current node matches
    Pattern.matches?(zipper, "use GenServer")

    # Find all matching nodes
    zippers = Pattern.find_all(zipper, "Repo.get!(...)")

    # Replace with captures
    {:ok, zipper} = Pattern.replace(zipper,
      "Enum.map(list, f)", "Enum.flat_map(list, f)")

    # Replace all occurrences
    {:ok, zipper} = Pattern.replace_all(zipper,
      "Logger.debug(msg, ...)", "Logger.warning(msg, ...)")

    # Context filters
    {:ok, zipper} = Pattern.move_to(zipper,
      "Repo.get!(...)", not_inside: "test _ do _ end")

    # Inside update_elixir_file
    Igniter.update_elixir_file(igniter, path, fn zipper ->
      Pattern.replace_all(zipper,
        "Enum.map(list, f)", "Enum.flat_map(list, f)")
    end)

    # Project-level: replace across all matching files
    Pattern.replace_in_all_files(igniter,
      "Logger.debug(msg, ...)", "Logger.warning(msg, ...)")

    # ~p sigil for compile-time pattern parsing
    import Igniter.Code.Pattern
    Pattern.find_all(zipper, ~p"Repo.get!(...)")

# `pattern`

```elixir
@type pattern() :: String.t() | Macro.t()
```

# `find_all`

```elixir
@spec find_all(Sourceror.Zipper.t(), pattern(), keyword()) :: [Sourceror.Zipper.t()]
```

Returns a list of zippers, one for each node matching `pattern`.

## Options

  * `:inside` — only match inside ancestors matching this pattern
  * `:not_inside` — skip matches inside ancestors matching this pattern

# `matches?`

```elixir
@spec matches?(Sourceror.Zipper.t(), pattern()) :: boolean()
```

Returns `true` if the current node matches the pattern.

Useful as a predicate inside `Igniter.Code.Common.move_to/2`,
`find_all_matching_modules`, or similar callbacks.

## Examples

    Igniter.Code.Common.move_to(zipper, fn zipper ->
      Pattern.matches?(zipper, "use GenServer")
    end)

# `move_to`

```elixir
@spec move_to(Sourceror.Zipper.t(), pattern(), keyword()) ::
  {:ok, Sourceror.Zipper.t()} | :error
```

Moves to the first node matching `pattern`.

Returns `{:ok, zipper}` positioned at the matched node, or `:error`.

## Options

  * `:inside` — only match inside ancestors matching this pattern
  * `:not_inside` — skip matches inside ancestors matching this pattern

# `replace`

```elixir
@spec replace(Sourceror.Zipper.t(), pattern(), pattern(), keyword()) ::
  {:ok, Sourceror.Zipper.t()} | :error
```

Replaces the first node matching `pattern` with `replacement`.

Returns `{:ok, zipper}` with the modified tree, or `:error` if
no match is found.

## Options

  * `:inside` — only match inside ancestors matching this pattern
  * `:not_inside` — skip matches inside ancestors matching this pattern

# `replace_all`

```elixir
@spec replace_all(Sourceror.Zipper.t(), pattern(), pattern(), keyword()) ::
  {:ok, Sourceror.Zipper.t()} | :error
```

Replaces all nodes matching `pattern` with `replacement`.

Returns `{:ok, zipper}` with the modified tree. If no matches
are found, returns the zipper unchanged.

## Options

  * `:inside` — only match inside ancestors matching this pattern
  * `:not_inside` — skip matches inside ancestors matching this pattern

# `replace_in_all_files`

```elixir
@spec replace_in_all_files(Igniter.t(), pattern(), pattern(), keyword()) ::
  Igniter.t()
```

Replaces all nodes matching `pattern` with `replacement` across all
Elixir files in the project.

## Options

  * `:inside` — only match inside ancestors matching this pattern
  * `:not_inside` — skip matches inside ancestors matching this pattern

# `replace_in_file`

```elixir
@spec replace_in_file(Igniter.t(), String.t(), pattern(), pattern(), keyword()) ::
  Igniter.t()
```

Replaces all nodes matching `pattern` with `replacement` in a single file.

Wraps `Igniter.update_elixir_file/3` with pattern-based replacement.

## Options

  * `:inside` — only match inside ancestors matching this pattern
  * `:not_inside` — skip matches inside ancestors matching this pattern

# `sigil_p`
*macro* 

Parses a pattern string into AST at compile time.

Avoids runtime string parsing. The result can be passed
to any function in this module.

## Examples

    import Igniter.Code.Pattern

    Pattern.find_all(zipper, ~p"IO.inspect(...)")
    Pattern.replace_all(zipper, ~p"dbg(expr)", ~p"expr")

---

*Consult [api-reference.md](api-reference.md) for complete listing*
