# `TuningFork.Strudel`
[🔗](https://github.com/jaman/tuning_fork/blob/v0.1.11/tuning_fork/lib/tuning_fork/strudel.ex#L1)

Reads a Strudel piece — the JavaScript as written at strudel.cc — into the pattern chains
this library plays.

    {:ok, chains, meta} = TuningFork.Strudel.chains(js)
    {:ok, pattern} = TuningFork.Strudel.pattern(js)

# `chain`

```elixir
@type chain() :: {non_neg_integer(), non_neg_integer(), String.t()}
```

# `meta`

```elixir
@type meta() :: %{cps: number() | nil, samples: [String.t()]}
```

# `chains`

```elixir
@spec chains(String.t()) ::
  {:ok, [chain()], meta()} | {:error, non_neg_integer(), String.t()}
```

The chains a piece plays, as `{first_line, last_line, elixir_source}` with lines counted
from zero, and what it asked for besides.

Rows come from `$:` statements, or from the last expression when there are none; a
`stack` at the top of a row is one chain per voice. `let` variables are written into every
chain that uses them. `samples(...)` is loaded on the way through and `setcps` reported in
the meta. `{:error, line, message}` for JavaScript this does not read.

# `defaults`

```elixir
@spec defaults(keyword()) :: :ok
```

Register the sample sets strudel.cc loads before any piece — its drum kit, the drum
machines and their short names, the piano, the VCSL and mridangam sets, and the part of
Dirt-Samples it keeps — in the background, once. Their files are fetched as they are
played. `chains/1` calls this, and so does `TuningFork.Kit` when asked for a bank it does
not have. `wait: true` returns once the sets are registered. Setting the application
environment `:tuning_fork, :strudel_defaults` to `false` turns it off.

# `pattern`

```elixir
@spec pattern(String.t()) :: {:ok, TuningFork.Pattern.t()} | {:error, String.t()}
```

The piece as one pattern, every chain stacked.

# `strudel?`

```elixir
@spec strudel?(String.t()) :: boolean()
```

Whether `text` reads as Strudel rather than as this library's own rows: method chains after
a call or a string, or `$:` lines, and no `|>` anywhere.

# `to_rows`

```elixir
@spec to_rows(String.t()) :: {:ok, [String.t()]} | {:error, String.t()}
```

The piece as rows of this library's source, one chain a row, for pasting into a buffer.

# `words`

```elixir
@spec words() :: [String.t()]
```

Every word this reads: the pattern and control functions, in Strudel's spelling and this library's.

---

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