View Source Igniter.Code.Common (igniter v0.4.8)
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.
Expands a literal value using the env at the cursor, if possible
Returns a list of zippers
to each node
that satisfies the predicate
function, or
an empty list if none are found.
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 a zipper to the left.
Moves nextwards (depth-first), until the provided predicate returns true
.
Moves a zipper to the right.
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.
Moves to the next zipper that matches the predicate.
Moves a zipper upwards.
Moves to the last node before the node that matches the predicate, going upwards.
Returns true
if the current node matches the given pattern.
Removes any nodes matching the provided pattern, until there are no matches left.
Removes all nodes matching the given predicate with the given function.
Moves the zipper all the way to the right, potentially entering a single value block.
Updates all nodes matching the given predicate with the given function.
Replaces full module names in new_code
with any aliases for that
module found in the current_code
environment.
Runs the function fun
on the subtree of the currently focused node
and
returns the updated zipper
.
Functions
@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 tofalse
.
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!")
"""
Expands the environment at the current zipper position and returns the expanded environment. Currently used for properly working with aliases.
@spec expand_alias(Sourceror.Zipper.t()) :: Sourceror.Zipper.t()
@spec expand_aliases(Sourceror.Zipper.t()) :: Sourceror.Zipper.t()
@spec expand_literal(Sourceror.Zipper.t()) :: {:ok, any()} | :error
Expands a literal value using the env at the cursor, if possible
@spec find_all(Sourceror.Zipper.t(), predicate :: (Sourceror.Zipper.t() -> 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
.
@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.
@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
@spec move_left( Sourceror.Zipper.t(), non_neg_integer() | (Sourceror.Zipper.t() -> 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.
@spec move_next(Sourceror.Zipper.t(), (Sourceror.Zipper.t() -> 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.
@spec move_right( Sourceror.Zipper.t(), non_neg_integer() | (Sourceror.Zipper.t() -> 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.
@spec move_to(Sourceror.Zipper.t(), (Sourceror.Zipper.t() -> boolean())) :: {:ok, Sourceror.Zipper.t()} | :error
@spec move_to(Sourceror.Zipper.t(), (Sourceror.Zipper.t() -> boolean())) :: {:ok, Sourceror.Zipper.t()} | :error
Moves to the next node that matches the predicate.
@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.node()
# => 10
@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
@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.
Moves to the next zipper that matches the predicate.
@spec move_upwards( Sourceror.Zipper.t(), non_neg_integer() | (Sourceror.Zipper.t() -> 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.
@spec move_upwards_until(Sourceror.Zipper.t(), (Sourceror.Zipper.t() -> boolean())) :: {:ok, Sourceror.Zipper.t()} | :error
Moves to the last node before the node that matches the predicate, going upwards.
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
@spec nodes_equal?(Sourceror.Zipper.t() | Macro.t(), Macro.t()) :: boolean()
@spec nth_right(Sourceror.Zipper.t(), non_neg_integer()) :: {:ok, Sourceror.Zipper.t()} | :error
@spec remove(Sourceror.Zipper.t(), (Sourceror.Zipper.t() -> boolean())) :: Sourceror.Zipper.t()
Removes any nodes matching the provided pattern, until there are no matches left.
@spec remove_all_matches( Sourceror.Zipper.t(), (Sourceror.Zipper.t() -> boolean()) ) :: Sourceror.Zipper.t()
Removes all nodes matching the given predicate with the given function.
Recurses until the predicate no longer returns false
@spec rightmost(Sourceror.Zipper.t()) :: Sourceror.Zipper.t()
Moves the zipper all the way to the right, potentially entering a single value block.
@spec single_child_block?(Sourceror.Zipper.t()) :: boolean()
@spec update_all_matches( Sourceror.Zipper.t(), (Sourceror.Zipper.t() -> boolean()), (Sourceror.Zipper.t() -> {: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
Replaces full module names in new_code
with any aliases for that
module found in the current_code
environment.
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.