gleam-lang / suggestions

📙 A place for ideas and feedback
26 stars 2 forks source link

Show Erlang & Elixir definitions/usage in documentation #104

Open michaeljones opened 3 years ago

michaeljones commented 3 years ago

As mentioned on discord, it might be an idea to have some way of displaying how to call Gleam functions from Erlang & Elixir and other languages that Gleam ends up targeting (work is underway to target JavaScript.)

The benefit here would be to maximise how approachable Gleam is from these languages.

A potential downside is if the types in Erlang or Elixir are complex or overly verbose to expose. Especially if they are impractically verbose for some reason.

There might also be consideration for any Gleam functions that are wrapping Erlang functions. There might be times when it is better to point Erlang developers to the underlying Erlang function than to have them access it through a shim compiled from Gleam.

Ideally the definitions/access would be automatically generated by the compiler using modules that understood the target languages and the mapping from Gleam. It would be less ideal to burden Gleam project maintainers with manually maintaining the definitions.

I don't fully understand the whole thing but if it is signed off as a good idea then I'd be happy to start to explore it.

lpil commented 3 years ago

A great suggestion!

When doing this I think we should be careful to ensure this documentation for other languages doesn't obscure the docs for Gleam. Ideally it would be hidden by default but easy to discover.

michaeljones commented 3 years ago

I'm happy to play around with some ideas. I guess my first two would be:

  1. Some kind of toggle in the top bar that allows you to switch language and that changes all entries on that page from Gleam syntax to Elixir, Erlang, etc. It would default to Gleam.

    • Pro: Easy to view whole module from the perspective of a single language and have a consistent overview
    • Con: You loose site of the Gleam definitions if you switch to a language which might be annoying if you want the Gleam view and the specific language view of a particular thing for some reason.
  2. Some kind of "expander" arrow next to each entries and if you click it then definitions for all compatible languages "slide out" from under the Gleam definition and sit below it.

    • Pro: See Gleam plus other languages so you can keep the Gleam definitions in mind.
    • Con: Might get busy if there are many languages that are compatible.
    • Con: If you look at a function and then need to cross-reference a type or another function then you'll need to expand those too.
  3. A mix of the two where the top level toggle defaults to empty but if you select an alternative language then it shows those definitions along side/underneath the Gleam definitions.

    • Pro: Less cluttered than showing all languages
    • Pro: The viewer is presumably only interested in at most one other language and probably is interested in the original Gleam definitions.
    • Con: Might still be a bit cluttered.

I guess it depends on what we think the mindset of the people using this will be. Would they come with a pure, say, Elixir mindset and be happy seeing all the definitions in Elixir and nothing of the Gleam. Or should they always be interested in the Gleam side. Or are we interested in making sure that the Gleam definitions are always visible to increase people's familiarity with them.

Probably over thinking but good to explore stuff.

lpil commented 3 years ago

I think 2 with data structure definitions could be a good balance between ease of implementation and UX. We should use a HTML5 details/summary element with a bit of styling.

michaeljones commented 3 years ago

Cool, I'm quite keen to progress as far as possible without writing any code so I think the next step might be to look for codepen.io examples or jQuery plugin demos or React component demos that illustrate the kind of feel that we're looking for.

It also occurred to me to ask if you have any strong feelings about use of Javascript? We could try to leverage the "checkbox hack" (https://css-tricks.com/the-checkbox-hack/) for a zero JS approach if you feel the docs should operate as well as possible without JS. Otherwise I assume the emphasis should be on keeping it light. So some kind of vanilla JS approach where possible?

Finally, I curious how you feel about outputting Erlang typespecs into the compiled output? That would make it easier to document perhaps? The Erlang & Elixir type signatures could reference the types that are already output to the files. Or perhaps we just output them to the documentation and not worry about the source files. As mentioned, it isn't all clear in my head so I'm sure there are lots of pros & cons that I'm not aware of. I'm currently looking at the compiled output of the gleam/result module and can't see a Result type declaration anywhere (which is understandable.)

michaeljones commented 3 years ago

I'm sure there is plenty more to find but this is a smooth no-JS slide down animation: https://codepen.io/surjithctly/pen/pLDwe

lpil commented 3 years ago

Given the limited time we have I would be interested in taking the route that is simplest from ab implementation and maintenance point of view. As such I would probably say let's avoid using any animations or search and as much as possible leverage standard HTML5 features, for example using a details element if we need a a section that can toggle open and closed rather than we implement this feature in javascript or CSS.

The most important thing for now is that we get the content right and it is usable, later if we successfully attract more people to to the Gleam world we can then work on making it extra fancy.

Being efficient with our time will be pay off while we've no one working full time on Gleam.

lpil commented 3 years ago

Finally, I curious how you feel about outputting Erlang typespecs into the compiled output?

There is actually an issue for this here https://github.com/gleam-lang/gleam/issues/632

michaeljones commented 3 years ago

Thanks, sorry, I should have discussed the details element which you indicated before. I had in my mind that it takes up space even when collapsed so I wasn't sure how to go about it but maybe I was thinking about it wrong. It seems that it requires a <details> tag that has a nested <summary> tag and then more content below that. Are you thinking that we put the current Gleam definition in the <summary> tag and then have the other definitions below so you can click on the Gleam definition to see the rest?

michaeljones commented 3 years ago

Details seems to work nicely.

    <details>
        <summary><pre>pub fn cookie_defaults(scheme: Scheme) -&gt; CookieAttributes</pre></summary>
        <pre>gleam@http:cookie_defaults(Scheme) -&gt; CookieAttributes</pre>
        <pre>:'gleam@http'.cookie_defaults(Scheme) :: t.CookieAttributes</pre>
    </details>

With additional CSS:

::marker {
    content: "";
}

Which hides the details/expander arrow (which looks neater but raises issues.)

Gives this normal looking entry:

image

Which when clicked on, expands to:

image

(Not sure either of the Erlang or Elixir entries are valid but hopefully they are passable.)

Which leaves questions:

  1. How do we make the Gleam definition look like it is clickable/expandable?
  2. How do we label the expanded entries with their target language for those that are familiar?
lpil commented 3 years ago

I feel people would probably only want to view one of extra languages available, could they have the ability to open just one?

I think I would want there to be a little unfairly unassuming link that says "elixir syntax" or something on each item in the module to open the section. I don't think it's obvious that clicking on the the function would open documentation for Erlang and Elixir users, so having that word would help.

michaeljones commented 3 years ago

I think I'm struggling to picture what you're thinking of. This:

    <pre>pub fn cookie_defaults(scheme: Scheme) -&gt; CookieAttributes</pre>
    <details>
        <summary>Erlang syntax</summary>
        <pre>gleam@http:cookie_defaults(Scheme) -&gt; CookieAttributes</pre>
    </details>
    <details>
        <summary>Elixir syntax</summary>
        <pre>:'gleam@http'.cookie_defaults(Scheme) :: CookieAttributes</pre>
    </details>

Gives us:

image

And:

image

Something more like that?

I'm not sure how to expand only one of the languages unless they are separate <details> blocks and if they are separate then they are going to take up more space.

I guess they could also be placed below the main description of the function as kind of footnotes for each function.

lpil commented 3 years ago

I like the idea of having them as footnotes below the description. That sounds good

On Fri, 27 Nov 2020, 21:19 Michael Jones, notifications@github.com wrote:

I think I'm struggling to picture what you're thinking of. This:

<pre>pub fn cookie_defaults(scheme: Scheme) -&gt; CookieAttributes</pre>
<details>
    <summary>Erlang syntax</summary>
    <pre>gleam@http:cookie_defaults(Scheme) -&gt; CookieAttributes</pre>
</details>
<details>
    <summary>Elixir syntax</summary>
    <pre>:'gleam@http'.cookie_defaults(Scheme) :: CookieAttributes</pre>
</details>

Gives us:

[image: image] https://user-images.githubusercontent.com/5390/100484859-f1654a00-30f5-11eb-9003-9e101554b426.png

And:

[image: image] https://user-images.githubusercontent.com/5390/100484868-fcb87580-30f5-11eb-9881-4ae881defdb2.png

Something more like that?

I'm not sure how to expand only one of the languages unless they are separate

blocks and if they are separate then they are going to take up more space.

I guess they could also be placed below the main description of the function as kind of footnotes for each function.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/gleam-lang/suggestions/issues/104#issuecomment-734991966, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABOZVBVYBIM3WNFLLJAWAHDSSAJVVANCNFSM4UBOWI6A .

michaeljones commented 3 years ago

Cool, that makes sense. We can work towards that.

How do you think the Erlang & Elixir entries should look? I'm concerned that we need to show the importing of the module or prefix everything with the module. eg. would the Elixir example look like:

:'gleam@http'.cookie_defaults(:'gleam@http'.Scheme) :: :'gleam@http'.CookieAttributes

Or

alias :'gleam@http' as Http
Http.cookie_defaults(Http.Scheme) :: Http.CookieAttributes

Or something like that? I've realised that I'm getting rusty with my Elixir having had a few months off and only 6 months experience to begin with. I've no idea what the Erlang might look like.

Or perhaps we show the module imports separately and then show all examples without prefixes?

lpil commented 3 years ago

I think showing them with the prefix may be the way to go? I could see an argument either way. Using the prefix would be closer to how we will show the Erlang syntax as they rarely alias modules.

I'm not sure how we show records etc, :'gleam@http'.Scheme isn't valid.

Can Elixir atoms not have unquoted @s? Huh.

michaeljones commented 3 years ago

Can Elixir atoms not have unquoted @s? Huh.

Didn't think to test. It seems they can :) Sorry for the unnecessary complexity.

lpil commented 3 years ago

Maybe we could do something like this for showing terms as we don't have term typespecs yet

-spec gleam@http:cookie_defaults(Scheme) :: CookieAttributes
  when
    Scheme :: term(), % gleam/http.Scheme
    CookieAttributes :: term(). % gleam/http.CookieAttributes
@spec :'gleam@http'.cookie_defaults(scheme) :: cookie_attributes
  when [
    scheme: term(), # gleam/http.Scheme
    cookie_attributes: term() # gleam/http.CookieAttributes
  ]
michaeljones commented 3 years ago

Certainly possible. Would it make sense to push this back until after we're generating typespecs in the output files? I don't know how you see the priorities or the difficulties of the typespec stuff.

It would also be really interesting to explore output Typescript types at some point in the future. Presumably as a separate but neighbouring mode to the JS output.

lpil commented 3 years ago

I don't think anyone is working on that and the majority of the code would probably be shared no matter which way round we do it. If anyone finds either feature more interesting that won't can be done first.

Feel free to open a a ticket to discuss typescript etc :)

michaeljones commented 3 years ago

As you might tell from my comment on the other issue, I'm quite tempted to give the typespec generation a go first. I'll switch my attention to that and we'll see where we are at the end of it.