What took you way too long to figure out?

Browsers don’t create the html standard, at least not directly. Also completely natively implemented form controls are a nightmare to customize. We’re only just seeing browsers adopt a styleable select from work comming out of GitHub - openui/open-ui: Maintain an open standard for UI and promote its adherence and adoption. · GitHub

Multiple select is imo even harder, because it’s not just that it’s not customizable, but also that multiple select is plain old bad UI in the first place. And while there are alternatives I personally don’t consider any of those universally good.

OpenUI however does truely seem to be able to make progress happen looking at the things they proposed that turned into standards.

I have only one such problem that’s scalable to the universe size! Just think that for years you have written macros that generates some functions/macros and documented the generated code inside quote do … end block and then you realize that you can simply use @callback attribute for documentation purposes (like for example Ecto.Repo is doing). :thinking:

This was because the behaviours I remembered were pigeonholed for 3rd-party modules and not for the code you generate. I’m still in a process of rewriting all related projects. :sweat_smile:


That’s said the best topic is of course the never ending story:

How to center a div?

I recommend to watch:

2 Likes

The best way for a looooong time which worked from the very beginning was <td align=center valign=middle> :smiley:

2 Likes

Here is a list of keyboard shortcuts available in the IEx/erl shells:

Found in this Erlang Forum post while I was scrounging for some unrelated info.

There’s some neat stuff in there. e.g. Ctrl + ] can be used to auto-close the ), ], and } brackets.

8 Likes

I’ve always avoided using the default log level :debug during development since I find that Ecto Repo calls produce too much logger spam.

I recently learned about the Ecto.Repo :log option, and finally got around to making it customizable:

config/runtime.exs

config :your_app, YourApp.Repo,
  log: System.get_env("REPO_LOG", "debug") |> String.to_existing_atom()

Now, I can just start an IEx shell with REPO_LOG=false iex -S mix and get debug logs without being swamped by Repo debug logs!

I used to just run :info logs by default during development, but this simple trick is likely to make debug logging a lot more pleasant for me to use.

6 Likes

I used IO.puts() for too long before discovering dbg().

2 Likes

I still use IO.inspect after pipes because the majority of the time I only want to see the final output. I wish there was a way to configure dbg to default to not doing this with an inline option to turn it on. Maybe there is? :thinking: I have not found it.

EDIT: And speaking of things that took me way too long to figure out, not only did I just learn about dbg(binding()) while taking another look through the docs for anything related to my problem stated above, I learned that it is “very common” to do so! Oh boy! It hurts extra because I have used binding() several times, just never thought to use it in every day debugging.

4 Likes

There isn’t one I guess — Macro.dbg/3 matches on the |> AST node and always expands it, and the options only control printing. But you can flip the default yourself: dbg resolves its backend at compile time from config :elixir, :dbg_callback, {Mod, :fun, []}, and Macro.dbg/3 is public precisely so custom backends can fall back to it. So: match {:|>, _, _}, emit a plain IO.inspect with Macro.to_string(code) as label, and delegate everything else to Macro.dbg/3 — with a steps: true option to opt back into the full expansion. Two gotchas: the options come in as AST, not values, and the backend module must already be compiled when the dbg call sites are, so it’s cleanest as a separate dep. Also, since 1.17 the IEx pry backend is opt-in via --dbg pry, so a custom callback survives a plain iex -S mix.

2 Likes
|> tap(&dbg/1)

That’s what I use when I want dbg in a pipeline without inspecting every step

5 Likes

Oh that’s a neat trick, not not really any easier to type than IO.inspect. It’s more of a muscle memory issue, though. I also have my own little plugin to add auto-add debug statements and of course it adds complexity when I have to change what the actual output is.

Fair, I just like the syntax highlighting of dbg

1 Like

Thanks a lot. I knew then() but not tap(). Good trick, good to know.

Well, there’s a TIL for me. I have this mapped to my i register in Vim:

|> IO.inspect(label: "\nfixme1\n", syntax_colors: IO.ANSI.syntax_colors())

But I will definitely look into your method, which seems much simpler.

1 Like

Because of my (stupid?) aversion to certain kinds of spacing in code, I was using an obnoxious \ with with:

  with \
    {:ok, thing} <- get_thing(x),
    {:ok, modified_thing} <- modify_thing(thing)
  do
    # ...
  else
    # ...
  end

instead of the more typical:

  with {:ok, thing} <- get_thing(x),
       {:ok, modified_thing} <- modify_thing(thing) do
    # ...

But then I happened across the fact in the documentation that you can simply use brackets (which is honoured by auto-formatting, with line breaks when the line with clauses doesn’t fit in one line):

  with(
    {:ok, thing} <- get_thing(x),
    {:ok, modified_thing} <- modify_thing(thing)
  ) do

As with any other function or macro call in Elixir, explicit parens can also be used around the arguments before the do-end block
Kernel.SpecialForms — Elixir v1.20.3

4 Likes