-
-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor Zipper
to use a struct
#98
Conversation
Any thoughts on how I'm wondering if we should use the
|
@zachallaun these options sound good to me! |
lib/sourceror/zipper.ex
Outdated
|
||
defp inspect(:as_code, zipper, opts) do | ||
code = Sourceror.to_algebra(zipper.node, Map.to_list(opts)) | ||
nest(concat(["#Zipper<node:", code, ">"]), 1) |> format(opts.width) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An early comment:
We probably want to use something a little more coplex here to ensure better fit, like Nx does to print the tensors
https://github.com/elixir-nx/nx/blob/0af36df37f6b7582e242a9aa19748fb6a5e12dcd/nx/lib/nx/tensor.ex#L241-L248
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, for sure -- I had to stop work on this early and was just committing what I had :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’d like to revisit Inspect
later today.
I’ve been back and forth a lot on how to clearly surface useful information about “where you are” in the Zipper when displaying :as_ast
or :as_code
. The simplest thing is to just only show the current node, like
# :as_ast
#Sourceror.Zipper<
{:def, [], [...]}
>
# :as_code
#Sourceror.Zipper<
def foo do
:bar
end
>
But there are other potentially useful things to indicate that would normally be visible by looking at the path a bit:
- do we have ancestors/are we at the root?
- do we have siblings?
Spitballing a bit:
# :as_ast
#Sourceror.Zipper<
#root
{:def, [], [...]}
>
#Sourceror.Zipper<
#...
{:def, [], [...]}
#...
>
# :as_code
#Sourceror.Zipper<
#root
def foo do
:bar
end
>
# all potentially valid:
#Sourceror.Zipper<
#...
def foo do
:bar
end
#...
>
#Sourceror.Zipper<
def foo do
:bar
end
#...
>
#Sourceror.Zipper<
#...
def foo do
:bar
end
>
#Sourceror.Zipper<
def foo do
:bar
end
>
Is it obvious what the #root
and #...
indicate here? I was writing out an explanation, but realized that a better "test" would be whether it is self-evident. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went ahead and implemented it this way for now -- curious for your feedback when you have time!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One issue I found with :as_code
-- there are situations where what's being formatted is a section of the AST that you can get to via the Zipper but isn't really valid AST, so the formatting you get is a bit weird/unexpected:
iex(22)> IEx.configure(inspect: [custom_options: [zipper: :as_code]])
:ok
iex(23)> "Foo.Bar.baz()" |> Code.string_to_quoted!() |> Z.zip()
#Sourceror.Zipper<
#root
Foo.Bar.baz()
>
iex(24)> "Foo.Bar.baz()" |> Code.string_to_quoted!() |> Z.zip() |> Z.next()
#Sourceror.Zipper<
Foo.Bar . :baz
>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:as_code
can also be a bit weird when you're dealing with Sourceror AST, which wraps literals in :__block__
tuples:
iex(5)> "1 + 2" |> Sourceror.parse_string!() |> Z.zip()
#Sourceror.Zipper<
#root
1 + 2
>
iex(6)> "1 + 2" |> Sourceror.parse_string!() |> Z.zip() |> Z.next()
#Sourceror.Zipper<
1
#...
>
iex(7)> "1 + 2" |> Sourceror.parse_string!() |> Z.zip() |> Z.next() |> Z.next()
#Sourceror.Zipper<
1
>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think #root
and #...
are ok, but we might want to use a different color with IO.ANSI
to make it clear it's a zipper formatting thing, and not an actual comment in the original code. We can use a greyish color for this
I wouldn't worry too much about a perfect representation of invalid ast; I think there are many disparate ways in which you can reach them, and this is a debugging utility so it shouldn't be too probolematic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea! I looked into this initially but there wasn't a default "faint/subdued" color in :syntax_colors
, which are used with Inspect.Algebra.color/3
. We can add an arbitrary one though:
opts = Map.update!(opts, :syntax_colors, &Keyword.put_new(&1, :zipper_internal, :light_black))
...
color("#root", :zipper_internal, opts)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lib/sourceror/zipper.ex
Outdated
end | ||
|
||
defp inspect(:raw, zipper, opts) do | ||
Inspect.Map.inspect(zipper, "Zipper", [%{field: :node}, %{field: :path}], opts) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to do something else here; doesn't work on Elixir 1.12.3.
144ced4
to
c0a9ae8
Compare
@doorgan I still need to update the multi-alias expansion example guide, but I think this is otherwise ready to review! |
A couple thoughts:
With the multiple inspect options, it's kinda cumbersome to switch between them. Like if you just want your existing logging/etc. to always show a zipper in What if we had a public iex> Sourceror.Zipper.Inspect.default_option()
:as_ast
iex> Sourceror.Zipper.Inspect.default_option(:as_code)
:ok |
I went ahead and implemented the suggestions I made above & updated the guides! One note: I updated the guides using Livebook locally, but until a release is cut, you'll need to modify the Mix.install([
# :sourceror
{:sourceror, path: Path.expand("../", __DIR__)}
]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Three cheers for the updated documentation too! 💜
Thank you for taking the time to implement this!
💚 💙 💜 💛 ❤️ |
Implements #96
TODO:
Inspect
for zippers