fceruti
How to programatically format code using plugins
I’m building a library that’s constantly re generating certain modules, building them from string templates. The generated modules include certain sigils that are nicely formatted using a custom plugin.
I need to format the string before it touches disk, because there are also file watchers, who would receive the event twice if I format as a second separate step. That’s why I can’t just call System.cmd("mix format") after creating the file.
Is there something equivalent to using Code.format_string!/2 but with the ability of passing a plugin list?
Thanks!
Marked As Solved
Marcus
If I understand right you want to format in dev mode and therefore you can access Mix. In this case you can use this:
> iex -S mix
iex(1)> {formatter, _opts} = Mix.Tasks.Format.formatter_for_file("source.ex")
{#Function<19.89531025/1 in Mix.Tasks.Format.find_formatter_for_file/2>,
[
sigils: [],
plugins: [FreedomFormatter],
trailing_comma: true,
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"],
locals_without_parens: [noop: 1]
]}
iex(2)> formatter.("""
...(2)> defmodule Foo do
...(2)> def foo do
...(2)> noop 5
...(2)> [
...(2)> 1,
...(2)> 2,
...(2)> ]
...(2)> end
...(2)> end
...(2)> """) |> IO.puts()
defmodule Foo do
def foo do
noop 5
[
1,
2,
]
end
end
:ok
The "source.ex" given to formatter_for_file does not have to be an existing file.
Also Liked
krasenyp
You can go even simpler:
def write_and_format_module(file_path, content) do
command = """
mix format - <<STDIN > #{file_path}
#{content}
STDIN
"""
{"", 0} = System.shell(command)
Logger.info("Re generated: #{file_path}")
end
fceruti
Thanks! this was it ![]()
def write_and_format_module(file_path, content) do
:ok = file_path |> Path.dirname() |> File.mkdir_p()
{formatter, _} = Mix.Tasks.Format.formatter_for_file("source.ex")
File.write(file_path, formatter.(content))
IO.puts(IO.ANSI.green() <> "* creating " <> IO.ANSI.reset() <> file_path)
end
fceruti
Last Post!
fceruti
Thanks! this was it ![]()
def write_and_format_module(file_path, content) do
:ok = file_path |> Path.dirname() |> File.mkdir_p()
{formatter, _} = Mix.Tasks.Format.formatter_for_file("source.ex")
File.write(file_path, formatter.(content))
IO.puts(IO.ANSI.green() <> "* creating " <> IO.ANSI.reset() <> file_path)
end
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









