Skip to content

Commit

Permalink
Add Zipper.find_value/3 (#161)
Browse files Browse the repository at this point in the history
  • Loading branch information
doorgan authored Jul 24, 2024
1 parent ccdcaf9 commit e41e035
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
18 changes: 18 additions & 0 deletions lib/sourceror/zipper.ex
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,24 @@ defmodule Sourceror.Zipper do
end
end

@spec find_value(t, (tree -> any)) :: any | nil
def find_value(%Z{} = zipper, direction \\ :next, fun)
when direction in [:next, :prev] and is_function(fun, 1) do
do_find_value(zipper, move(direction), fun)
end

defp do_find_value(nil, _move, _fun), do: nil

defp do_find_value(%Z{node: tree} = zipper, move, fun) do
result = fun.(tree)

if result do
result
else
zipper |> move.() |> do_find_value(move, fun)
end
end

defp move(:next), do: &next/1
defp move(:prev), do: &prev/1

Expand Down
60 changes: 60 additions & 0 deletions test/zipper_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,66 @@ defmodule SourcerorTest.ZipperTest do
end
end

describe "find_value/3" do
test "finds a zipper and returns the value" do
zipper = Z.zip([1, [2, [3, 4], 5]])

assert Z.find_value(zipper, fn
4 -> 4
_ -> false
end) == 4

assert Z.find_value(zipper, :next, fn
4 -> 4
_ -> false
end) == 4
end

test "returns nil if nothing was found" do
zipper = Z.zip([1, [2, [3, 4], 5]])

assert Z.find_value(zipper, fn
9 -> 9
_ -> false
end) == nil

assert Z.find_value(zipper, :prev, fn
9 -> 9
_ -> false
end) == nil
end

test "finds a zipper with a predicate in direction :prev" do
zipper =
[1, [2, [3, 4], 5]]
|> Z.zip()
|> Z.next()
|> Z.next()
|> Z.next()
|> Z.next()

assert Z.find_value(zipper, :prev, fn
2 -> 2
_ -> false
end) == 2
end

test "retruns nil if nothing was found in direction :prev" do
zipper =
[1, [2, [3, 4], 5]]
|> Z.zip()
|> Z.next()
|> Z.next()
|> Z.next()
|> Z.next()

assert Z.find_value(zipper, :prev, fn
9 -> 9
_ -> false
end) == nil
end
end

describe "subtree/1" do
test "returns a new zipper isolated on the focused of the parent zipper" do
zipper =
Expand Down

0 comments on commit e41e035

Please sign in to comment.