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

General purpose utilities for working with `Sourceror.Zipper`.

# `add_code`

```elixir
@spec add_code(Sourceror.Zipper.t(), String.t() | Macro.t(), [opt]) ::
  Sourceror.Zipper.t()
when opt: {:placement, :after | :before} | {:expand_env?, boolean()}
```

Adds the provided code to the zipper.

## Options

- `:placement` - `:after` | `:before`. Determines if the code goes `:after` or `:before` the current node. Defaults to `:after`.
- `:expand_env?` - boolean. Whether or not to read the current file to use it's aliases for added code. Defaults to `true`. This option is a no-op on Elixir < 1.17.

## Example:

    iex> existing_zipper = Igniter.Code.Common.parse_to_zipper!("""
    ...> IO.puts("abc")
    ...> """)
    ...>
    ...> existing_zipper
    ...> |> Igniter.Code.Common.add_code("""
    ...> IO.puts("Goodbye, world!")
    ...> """, after: true)
    ...> |> Sourceror.Zipper.root()
    ...> |> Sourceror.to_string()
    "IO.puts(\"abc\")
    IO.puts(\"Goodbye, world!\")"

# `add_comment`

# `current_env`

Expands the environment at the current zipper position and returns the
expanded environment. Currently used for properly working with aliases.

# `expand_alias`

```elixir
@spec expand_alias(Sourceror.Zipper.t()) :: Sourceror.Zipper.t()
```

# `expand_aliases`

```elixir
@spec expand_aliases(Sourceror.Zipper.t()) :: Sourceror.Zipper.t()
```

# `expand_literal`

```elixir
@spec expand_literal(Sourceror.Zipper.t()) :: {:ok, any()} | :error
```

Expands a literal value using the env at the cursor, if possible

# `extendable_block?`

# `find_all`

```elixir
@spec find_all(Sourceror.Zipper.t(), predicate :: (Sourceror.Zipper.t() -&gt; boolean())) ::
  [
    Sourceror.Zipper.t()
  ]
```

Returns a list of `zippers` to each `node` that satisfies the `predicate` function, or
an empty list if none are found.

The optional second parameters specifies the `direction`, defaults to
`:next`.

# `maybe_move_to_block`

```elixir
@spec maybe_move_to_block(Sourceror.Zipper.t()) :: Sourceror.Zipper.t()
```

Enters a block, and moves to the first child, or returns the zipper unmodified.

# `maybe_move_to_single_child_block`

```elixir
@spec maybe_move_to_single_child_block(Sourceror.Zipper.t()) :: Sourceror.Zipper.t()
```

Enters a block with a single child, and moves to that child,
or returns the zipper unmodified

# `move_left`

```elixir
@spec move_left(
  Sourceror.Zipper.t(),
  non_neg_integer() | (Sourceror.Zipper.t() -&gt; boolean())
) ::
  {:ok, Sourceror.Zipper.t()} | :error
```

Moves a zipper to the left.

If the second argument is a predicate function, it will be called on the zipper and then
move leftwards until the predicate returns `true`. This function will automatically enter
and exit blocks.

If the second argument is a non-negative integer, it will move left that many times if
possible, returning `:error` otherwise.

# `move_next`

```elixir
@spec move_next(Sourceror.Zipper.t(), (Sourceror.Zipper.t() -&gt; boolean())) ::
  {:ok, Sourceror.Zipper.t()} | :error
```

Moves nextwards (depth-first), until the provided predicate returns `true`.

Returns `:error` if the end is reached without finding a match.

# `move_right`

```elixir
@spec move_right(
  Sourceror.Zipper.t(),
  non_neg_integer() | (Sourceror.Zipper.t() -&gt; boolean())
) ::
  {:ok, Sourceror.Zipper.t()} | :error
```

Moves a zipper to the right.

If the second argument is a predicate function, it will be called on the zipper and then
move rightwards until the predicate returns `true`. This function will automatically enter
and exit blocks.

If the second argument is a non-negative integer, it will move right that many times if
possible, returning `:error` otherwise.

# `move_to`

```elixir
@spec move_to(Sourceror.Zipper.t(), (Sourceror.Zipper.t() -&gt; boolean())) ::
  {:ok, Sourceror.Zipper.t()} | :error
@spec move_to(Sourceror.Zipper.t(), (Sourceror.Zipper.t() -&gt; boolean())) ::
  {:ok, Sourceror.Zipper.t()} | :error
```

Moves to the first node that matches the predicate.

# `move_to_cursor`

```elixir
@spec move_to_cursor(Sourceror.Zipper.t(), Sourceror.Zipper.t() | String.t()) ::
  {:ok, Sourceror.Zipper.t()} | :error
```

Matches and moves to the location of a `__cursor__` in provided source code.

Use `__cursor__()` to match a cursor in the provided source code. Use `__` to skip any code at a point.

For example:

```elixir
zipper =
  """
  if true do
    10
  end
  """
  |> Sourceror.parse_string!()
  |> Sourceror.Zipper.zip()

pattern =
  """
  if __ do
    __cursor__()
  end
  """

{:ok, zipper} = Igniter.Code.Common.move_to_cursor(zipper, pattern)
Sourceror.Zipper.node(zipper)
# => {:__block__,
#     [
#       trailing_comments: [],
#       leading_comments: [],
#       end_of_expression: [newlines: 1, line: 2, column: 5],
#       token: "10",
#       line: 2,
#       column: 3
#     ], ~c"
"}
```

# `move_to_cursor_match_in_scope`

```elixir
@spec move_to_cursor_match_in_scope(Sourceror.Zipper.t(), String.t() | [String.t()]) ::
  {:ok, Sourceror.Zipper.t()} | :error
```

Moves to the cursor that matches the provided pattern or one of the provided patterns, in the current scope.

See `move_to_cursor/2` for an example of a pattern

# `move_to_do_block`

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

Moves to a do block for the current call.

For example, at a node like:

```elixir
foo do
  10
end
```

You would get a zipper back at `10`.

# `move_to_last`

```elixir
@spec move_to_last(Sourceror.Zipper.t(), (Sourceror.Zipper.t() -&gt; boolean())) ::
  {:ok, Sourceror.Zipper.t()} | :error
```

Moves to the last node that matches the predicate.

Similar to `move_to/2` but it doesn't stop at the first match,
for example a zipper for the following code:

```elixir
port = 4000
port = 4001
```

With a match for `port = _` as `{:=, _, [{:port, _, _}, _]}`,
will return the second `port` variable.

# `move_to_pattern`
*macro* 

Moves to the next node that matches the given pattern.

# `move_to_zipper`

Moves to the next zipper that matches the predicate.

# `move_upwards`

```elixir
@spec move_upwards(
  Sourceror.Zipper.t(),
  non_neg_integer() | (Sourceror.Zipper.t() -&gt; boolean())
) ::
  {:ok, Sourceror.Zipper.t()} | :error
```

Moves a zipper upwards.

If the second argument is a predicate function, it will be called on the zipper and then
move upwards until the predicate returns `true`.

If the second argument is a non-negative integer, it will move upwards that many times if
possible, returning `:error` otherwise.

# `move_upwards_until`

```elixir
@spec move_upwards_until(Sourceror.Zipper.t(), (Sourceror.Zipper.t() -&gt; boolean())) ::
  {:ok, Sourceror.Zipper.t()} | :error
```

Moves to the last node before the node that matches the predicate, going upwards.

# `node_matches_pattern?`
*macro* 

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

## Examples:

```elixir
list_zipper =
  "[1, 2, 3]"
  |> Sourceror.parse_string!()
  |> Sourceror.Zipper.zip()

Common.node_matches_pattern?(list_zipper, value when is_list(value)) # true
```

# `nodes_equal?`

```elixir
@spec nodes_equal?(Sourceror.Zipper.t() | Macro.t(), Macro.t()) :: boolean()
```

# `nth_right`

> This function is deprecated. Use `move_right/2` instead, passing an integer as the second argument..

```elixir
@spec nth_right(Sourceror.Zipper.t(), non_neg_integer()) ::
  {:ok, Sourceror.Zipper.t()} | :error
```

# `parse_to_zipper!`

# `remove`

```elixir
@spec remove(Sourceror.Zipper.t(), (Sourceror.Zipper.t() -&gt; boolean())) ::
  Sourceror.Zipper.t()
```

Removes any nodes matching the provided pattern, until there are no matches left.

# `remove_all_matches`

```elixir
@spec remove_all_matches(
  Sourceror.Zipper.t(),
  (Sourceror.Zipper.t() -&gt; boolean())
) :: Sourceror.Zipper.t()
```

Removes all nodes matching the given predicate with the given function.

Recurses until the predicate no longer returns false

# `replace_code`

Replaces code with new code.

# `rightmost`

```elixir
@spec rightmost(Sourceror.Zipper.t()) :: Sourceror.Zipper.t()
```

Moves the zipper all the way to the right, potentially entering a single value block.

# `single_child_block?`

```elixir
@spec single_child_block?(Sourceror.Zipper.t()) :: boolean()
```

# `update_all_matches`

```elixir
@spec update_all_matches(
  Sourceror.Zipper.t(),
  (Sourceror.Zipper.t() -&gt; boolean()),
  (Sourceror.Zipper.t() -&gt;
     {:ok, Sourceror.Zipper.t() | {:code, term()}} | {:warning | :error, term()})
) :: {:ok, Sourceror.Zipper.t()} | {:warning | :error, term()}
```

Updates all nodes matching the given predicate with the given function.

Recurses until the predicate no longer returns false

# `use_aliases`

Replaces full module names in `new_code` with any aliases for that
module found in the `current_code` environment.

This function is a no-op on Elixir < 1.17.

# `variable?`

```elixir
@spec variable?(zipper :: Sourceror.Zipper.t(), name :: atom()) :: boolean()
```

Returns true if the node represents a variable with the given name

# `variable_assignment?`

```elixir
@spec variable_assignment?(zipper :: Sourceror.Zipper.t(), name :: atom()) ::
  boolean()
```

Returns true if the node represents a variable assignment

# `within`

Runs the function `fun` on the subtree of the currently focused `node` and
returns the updated `zipper`.

`fun` must return {:ok, zipper} or `:error`, `{:error, error}` or `{:warning, warn}`, which may be positioned at the top of the subtree.

---

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