# `Narabe.Position`
[🔗](https://github.com/hattoriai/narabe/blob/v0.1.0/lib/narabe/position.ex#L1)

Position keys: a text per item that sorts between its neighbours, so
that moving an item writes that one row, and two people moving at once
both land.

    iex> Narabe.Position.between(nil, nil)
    "a0"
    iex> Narabe.Position.between("a0", nil)
    "a1"
    iex> Narabe.Position.between("a0", "a1")
    "a0V"
    iex> Narabe.Position.between(nil, "a0")
    "Zz"

It is fractional indexing, as rocicorp's `fractional-indexing` (CC0):
base 62 (`0-9A-Za-z`), compared byte by byte. A key is an integer part
(a head letter that says its length, then digits) and a fraction that
never ends in `0`. Keys after the last count up (`"a1"`, `"a2"`, …,
`"b00"`), keys before the first count down, and a key between two close
ones grows a fraction. The browser's twin (`assets/src/position.ts`) gives
the same keys, held to the same answers by one fixture.

## In the database

Keys compare byte by byte, which is not every database's default:

  * Postgres: the column needs `COLLATE "C"` (`Narabe.Migration.position/2`
    adds it); a text column in a locale's collation sorts `"a"` and `"B"`
    the other way.
  * MySQL: a binary collation (`utf8mb4_bin`).
  * SQLite: its default (`BINARY`) is right.

Two moves into the same gap at the same moment get the same key: order
by the key, then by id (`Narabe.Ecto.ordered/2`), and the order is the
same on every screen. Keys grow only when items keep landing in the same
gap; `Narabe.Ecto.rebalance/3` spreads a list's keys out again.

# `t`

```elixir
@type t() :: String.t()
```

A position key.

# `between`

```elixir
@spec between(t() | nil, t() | nil) :: t()
```

A key between `a` and `b`; `nil` is the start or the end.

Raises `ArgumentError` when `a` is not before `b`, or either is not a key.

# `between_many`

```elixir
@spec between_many(t() | nil, t() | nil, non_neg_integer()) :: [t()]
```

`n` keys between `a` and `b`, in order, spread so that none grows long:
for several items moved at once, or a list's keys written anew.

    iex> Narabe.Position.between_many(nil, nil, 3)
    ["a0", "a1", "a2"]
    iex> Narabe.Position.between_many("a0", "a1", 3)
    ["a0G", "a0V", "a0l"]

# `valid?`

```elixir
@spec valid?(term()) :: boolean()
```

Whether a text is a position key.

    iex> Narabe.Position.valid?("a0V")
    true
    iex> Narabe.Position.valid?("a0V0")
    false

---

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