Packages
nous
0.13.3
0.17.0
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.17
0.12.16
0.12.15
0.12.14
0.12.13
0.12.12
0.12.11
0.12.9
0.12.7
0.12.6
0.12.5
0.12.3
0.12.2
0.12.0
0.11.3
0.11.0
0.10.1
0.10.0
0.9.0
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.5.0
AI agent framework for Elixir with multi-provider LLM support
Current section
Files
Jump to
Current section
Files
lib/nous/json.ex
defmodule Nous.JSON do
@moduledoc false
@doc """
Encode data to pretty-printed JSON string.
"""
@spec pretty_encode!(term()) :: String.t()
def pretty_encode!(data) do
data |> JSON.encode!() |> pretty_print()
end
defp pretty_print(json) when is_binary(json) do
json
|> String.graphemes()
|> do_pretty(0, false, [])
|> Enum.reverse()
|> IO.iodata_to_binary()
end
defp do_pretty([], _indent, _in_string, acc), do: acc
defp do_pretty(["\\" | [next | rest]], indent, true, acc),
do: do_pretty(rest, indent, true, [next, "\\" | acc])
defp do_pretty(["\"" | rest], indent, in_string, acc),
do: do_pretty(rest, indent, !in_string, ["\"" | acc])
defp do_pretty([char | rest], indent, true, acc),
do: do_pretty(rest, indent, true, [char | acc])
defp do_pretty(["{" | rest], indent, false, acc),
do: open_bracket(rest, indent, "{", acc)
defp do_pretty(["[" | rest], indent, false, acc),
do: open_bracket(rest, indent, "[", acc)
defp do_pretty(["}" | rest], indent, false, acc),
do: close_bracket(rest, indent, "}", acc)
defp do_pretty(["]" | rest], indent, false, acc),
do: close_bracket(rest, indent, "]", acc)
defp do_pretty(["," | rest], indent, false, acc),
do: do_pretty(rest, indent, false, [pad(indent), "\n", "," | acc])
defp do_pretty([":" | rest], indent, false, acc),
do: do_pretty(rest, indent, false, [" ", ":" | acc])
defp do_pretty([" " | rest], indent, false, acc),
do: do_pretty(rest, indent, false, acc)
defp do_pretty([char | rest], indent, false, acc),
do: do_pretty(rest, indent, false, [char | acc])
defp open_bracket(rest, indent, bracket, acc) do
# Peek ahead to check for empty container
trimmed = Enum.drop_while(rest, &(&1 == " "))
case trimmed do
[close | _] when close in ["}", "]"] ->
do_pretty(trimmed, indent, false, [bracket | acc])
_ ->
new_indent = indent + 1
do_pretty(rest, new_indent, false, [pad(new_indent), "\n", bracket | acc])
end
end
defp close_bracket(rest, indent, bracket, acc) do
new_indent = max(indent - 1, 0)
do_pretty(rest, new_indent, false, [bracket, pad(new_indent), "\n" | acc])
end
defp pad(level), do: String.duplicate(" ", level)
end