Thanks for the proposal. I am potentially fine with adding an option to some of the code generation helpers we have, but I am not sure we need the function in standard library. A simple indent implementation could be written as:
def indent(string, indent) do indent <> String.replace(string, ~r/\r\n|\n/, & &1 <> indent) end Or even without a regex: def indent(string, indent) do indent <> String.replace(string, ["\r\n", "\n"], & &1 <> indent) end Especially because I don't see a reason to pass anything but a string. However, you will find that most indent in Elixir codebase is actually a bit different. We don't indent consecutive or trailing newlines, so we would either need to add more options. If we have an official API, now we need to support these different options, while instead you could just change the one liner to use either ~r/(\r\n|\n)+/ or ~r/(\r\n|\n)+(?!$)/ respectively for the desired results. On Thursday, January 8, 2026 at 1:52:19 AM UTC+1 [email protected] wrote: > This was common enough that it's an option in Sourceror.to_string/2 > <https://hexdocs.pm/sourceror/Sourceror.html#to_string/2> > > On Wed, Jan 7, 2026 at 9:43 PM Zach Daniel <[email protected]> wrote: > >> This is such a good idea. I do this a lot too and didn't think of it, >> especially in library code. In strong support. >> >> >> On Wed, Jan 07, 2026 at 12:22 PM, Christopher Keele <[email protected]> >> wrote: >> > *Proposal:* >>> >>> >>> 1. Add support for indenting multi-line strings via *String.indent*: >>> *defmodule String do* >>> * @type indentation ::* >>> * binary* >>> * | Inspect.Algebra.t()* >>> * | [{:spaces, non_neg_integer()}]* >>> * | [{:tabs, non_neg_integer()}]* >>> >>> * @spec indent(String.t(), indentation) :: String.t()* >>> * def indent(string, indentation)* >>> *end* >>> 2. Add support for indenting ast representations in *Macro.to_string* >>> : >>> defmodule Macro do >>> @type to_string_opt :: {:indent, String.indentation()} >>> @spec to_string(Macro.t(), [to_string_opt()]) :: String.t() >>> def to_string(string, options \\ []) >>> def to_string(string, options) >>> end >>> 3. Add support for indenting code in *Code.format_string!*: >>> defmodule Code do >>> @type format_opt :: >>> # ... | >>> {:indent, String.indentation()} >>> @spec format_string!(String.t(), [format_opt()]) :: iodata() >>> def format_string!(string, opts \\[]) >>> end >>> 4. Add support for indenting arbitrary Algebra documents in >>> *Inspect.Opts*: >>> defmodule Inspect.Opts do >>> @t new_opt :: >>> # ... | >>> {:indent, String.indentation()} >>> end >>> >>> *Motivation:* >>> >>> I often want to indent code I provide as feedback to the user in >>> exception messages in macros. I have to imagine other library authors, >>> metaprogrammers, and LS developers would benefit as well. >>> >>> I often want to compose multi-line log messages with certain passages >>> indented. I have to imagine other application developers have wanted the >>> same. >>> >>> Please share if you can think of other ways you would use this >>> functionality, or other stdlib APIs you can think of wanting indentation >>> support for! >>> >>> *Rationale:* >>> >>> I find myself re-implementing this odd job often, not just for my stated >>> use-cases here. The arguments for putting it in stlib are: >>> >>> 1. The String utility is general-purpose enough for many use-cases, >>> and so is potentially useful to many Elixir users. >>> 2. We can provide a better implementation than the naive *String.split >>> |> Kernel.<> |> Enum.join*. >>> 3. We can provide an implementation that works with Inspect.Algebra >>> documents and inspect. >>> 4. We can provide an option to *Macro.to_string* and >>> *Code.format_string!* where displaying multi-line strings is common. >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "elixir-lang-core" group. >>> >> To unsubscribe from this group and stop receiving emails from it, send an >>> email to [email protected]. >>> >> >>> To view this discussion visit >>> https://groups.google.com/d/msgid/elixir-lang-core/f9b60654-29b2-4c06-80ea-6a6fa614f9d3n%40googlegroups.com >>> >>> <https://groups.google.com/d/msgid/elixir-lang-core/f9b60654-29b2-4c06-80ea-6a6fa614f9d3n%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- >> You received this message because you are subscribed to the Google Groups >> "elixir-lang-core" group. >> > To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> To view this discussion visit >> https://groups.google.com/d/msgid/elixir-lang-core/mk4q396z.7bef578b-059a-4f47-9bbe-f8485fa3ecdc%40we.are.superhuman.com >> >> <https://groups.google.com/d/msgid/elixir-lang-core/mk4q396z.7bef578b-059a-4f47-9bbe-f8485fa3ecdc%40we.are.superhuman.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion visit https://groups.google.com/d/msgid/elixir-lang-core/3d1f996e-f1e4-4337-8459-3fc81330001dn%40googlegroups.com.
