# `PtcRunner.Lisp.Format`
[🔗](https://github.com/andreasronge/ptc_runner/blob/main/lib/ptc_runner/lisp/format.ex#L1)

Format PTC-Lisp values for human/LLM display.

Handles special Lisp types that should not expose internal implementation:
- Closures: `{:closure, params, body, env, history, metadata}` → `#fn[x y]`
- Builtins: `{:normal, fun}` etc. → `#<builtin>`
- Wrapper structs implement `String.Chars` and `Jason.Encoder` as their display string.

Works recursively, so closures nested in maps/lists are also formatted.

## Examples

    iex> PtcRunner.Lisp.Format.to_string({:closure, [{:var, :x}], nil, %{}, [], %{}})
    "#fn[x]"

    iex> PtcRunner.Lisp.Format.to_string({:normal, &Enum.map/2})
    "#<builtin>"

    iex> PtcRunner.Lisp.Format.to_string(%{a: 1})
    "%{a: 1}"

# `to_clojure`

```elixir
@spec to_clojure(
  term(),
  keyword()
) :: {String.t(), boolean()}
```

Format a Lisp value as Clojure syntax for LLM feedback.

Produces Clojure-style output that matches the syntax the LLM writes:
- Maps: `{:key value}` instead of `%{key: value}`
- Lists: `[1 2 3]` (space-separated) instead of `[1, 2, 3]`
- Keywords: `:foo` (same as Clojure)
- Strings/numbers/booleans: standard literals

Returns `{formatted_string, truncated?}` tuple.

## Options

- `:limit` - Maximum items to show in collections (default: :infinity)
- `:printable_limit` - Maximum string chars to show (default: :infinity)

## Examples

    iex> PtcRunner.Lisp.Format.to_clojure(42)
    {"42", false}

    iex> PtcRunner.Lisp.Format.to_clojure([1, 2, 3])
    {"[1 2 3]", false}

    iex> PtcRunner.Lisp.Format.to_clojure(%{id: 101, count: 45})
    {"{:count 45 :id 101}", false}

    iex> PtcRunner.Lisp.Format.to_clojure(%{"name" => "Alice", "age" => 30})
    {~s({"age" 30 "name" "Alice"}), false}

    iex> PtcRunner.Lisp.Format.to_clojure({:closure, [{:var, :x}], nil, %{}, [], %{}})
    {"#fn[x]", false}

    iex> PtcRunner.Lisp.Format.to_clojure({:var, :x})
    {"#'x", false}

    iex> PtcRunner.Lisp.Format.to_clojure(nil)
    {"nil", false}

    iex> PtcRunner.Lisp.Format.to_clojure(:keyword)
    {":keyword", false}

    iex> PtcRunner.Lisp.Format.to_clojure([%{a: 1}, %{b: 2}])
    {"[{:a 1} {:b 2}]", false}

    iex> PtcRunner.Lisp.Format.to_clojure([1, 2, 3, 4, 5], limit: 2)
    {"[1 2 ...] (2/5)", true}

    iex> PtcRunner.Lisp.Format.to_clojure("very long string here", printable_limit: 10)
    {~s("very long ...") <> " (10/21 chars)", true}

    iex> {str, _} = PtcRunner.Lisp.Format.to_clojure(%{title: "Hello", _body: "secret"})
    iex> str
    ~s[{:_body "secret" :title "Hello"}]

# `to_string`

```elixir
@spec to_string(
  term(),
  keyword()
) :: String.t()
```

Format a Lisp value as a string for display.

## Options

All options are passed through to `Kernel.inspect/2` for regular values:
- `:pretty` - Use pretty-printing
- `:limit` - Maximum items to show in collections
- `:width` - Target width for pretty printing
- `:printable_limit` - Maximum string bytes to show

## Examples

    iex> PtcRunner.Lisp.Format.to_string(42)
    "42"

    iex> PtcRunner.Lisp.Format.to_string({:closure, [{:var, :x}, {:var, :y}], nil, %{}, [], %{}})
    "#fn[x y]"

    iex> PtcRunner.Lisp.Format.to_string({:var, :my_var})
    "#'my_var"

    iex> PtcRunner.Lisp.Format.to_string([1, 2, 3], limit: 2)
    "[1, 2, ...]"

    iex> PtcRunner.Lisp.Format.to_string(%{f: {:closure, [{:var, :x}], nil, %{}, [], %{}}})
    "%{f: #fn[x]}"

---

*Consult [api-reference.md](api-reference.md) for complete listing*
