Igniter.Code.Common (igniter v0.2.0)
General purpose utilities for working with Sourceror.Zipper
.
Summary
Functions
Adds the provided code to the zipper.
Expands the environment at the current zipper position and returns the expanded environment. Currently used for properly working with aliases.
Enters a block, and moves to the first child, or returns the zipper unmodified.
Enters a block with a single child, and moves to that child, or returns the zipper unmodified
Moves right in the zipper, until the provided predicate returns true
.
Moves to the next node that matches the predicate.
Matches and moves to the location of a __cursor__
in provided source code.
Moves to the cursor that matches the provided pattern or one of the provided patterns, in the current scope.
Moves to a do block for the current call.
Moves to the next node that matches the given pattern.
Returns true
if the current node matches the given pattern.
Moves the zipper right n times, returning :error
if it can't move that many times.
Runs the function fun
on the subtree of the currently focused node
and
returns the updated zipper
.
Functions
add_code(zipper, new_code, placement \\ :after)
@spec add_code(Sourceror.Zipper.t(), String.t() | Macro.t(), :after | :before) :: Sourceror.Zipper.t()
Adds the provided code to the zipper.
Use placement
to determine if the code goes :after
or :before
the current node.
Example:
existing_zipper = """
IO.inspect("Hello, world!")
"""
|> Sourceror.parse_string!()
|> Sourceror.Zipper.zip()
new_code = """
IO.inspect("Goodbye, world!")
"""
existing_zipper
|> Igniter.Common.add_code(new_code)
|> Sourceror.Zipper.root()
|> Sourceror.to_string()
Which will produce
"""
IO.inspect("Hello, world!")
IO.inspect("Goodbye, world!")
"""
current_env(zipper)
Expands the environment at the current zipper position and returns the expanded environment. Currently used for properly working with aliases.
expand_aliases(zipper)
@spec expand_aliases(Sourceror.Zipper.t()) :: Sourceror.Zipper.t()
maybe_move_to_block(zipper)
@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(zipper)
@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_right(zipper, pred)
@spec move_right(Sourceror.Zipper.t(), (Sourceror.Zipper.t() -> boolean())) :: {:ok, Sourceror.Zipper.t()} | :error
Moves right in the zipper, until the provided predicate returns true
.
Returns :error
if the end is reached without finding a match.
move_to(zipper, pred)
@spec move_to(Sourceror.Zipper.t(), (Sourceror.Zipper.tree() -> Sourceror.Zipper.t())) :: {:ok, Sourceror.Zipper.t()} | :error
Moves to the next node that matches the predicate.
move_to_cursor(zipper, pattern)
@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:
zipper =
"""
if true do
10
end
"""
|> Sourceror.Zipper.zip()
pattern =
"""
if __ do
__cursor__
end
"""
zipper
|> Igniter.Code.Common.move_to_cursor(pattern)
|> Zipper.subtree()
|> Zipper.node()
# => 10
move_to_cursor_match_in_scope(zipper, patterns)
@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(zipper)
@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:
foo do
10
end
You would get a zipper back at 10
.
Moves to the next node that matches the given pattern.
Returns true
if the current node matches the given pattern.
Examples:
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?(left, right)
@spec nodes_equal?(Sourceror.Zipper.t() | Macro.t(), Macro.t()) :: boolean()
nth_right(zipper, n)
@spec nth_right(Sourceror.Zipper.t(), non_neg_integer()) :: {:ok, Sourceror.Zipper.t()} | :error
Moves the zipper right n times, returning :error
if it can't move that many times.
replace_code(zipper, code)
use_aliases(new_code, current_code)
within(top_zipper, fun)
Runs the function fun
on the subtree of the currently focused node
and
returns the updated zipper
.
fun
must return {:ok, zipper} or :error
, which may be positioned at the top of the subtree.