Yex.StickyIndex (y_ex v0.8.0)

View Source

A sticky index provides position references that are unaffected by document changes, based on the Yjs model. It maintains its relative position when placed before or after specific characters or elements.

Features

  • Stable position references unaffected by document changes
  • Compatible with shared types like Text, Array, and XML
  • Maintains relative positions after insert/delete operations
  • Ideal for tracking cursor positions and text selections

Usage

Numeric indices are unsuitable for tracking user selections because their positions change when content is inserted or deleted. Sticky indices provide stable references that maintain their relative positions through such changes:

iex> alias Yex.{StickyIndex, Doc, Text}
iex> doc = Doc.new()
iex> txt = Doc.get_text(doc, "text")
iex> Doc.transaction(doc, fn ->
...>  Text.insert(txt, 0, "abc")
...>  # => 'abc'
...>  # Create position tracker (marked as . in comments)
...>  pos = StickyIndex.new(txt, 2, :after)
...>  # => 'ab.c'
...>
...>  # Modify text
...>  Text.insert(txt, 1, "def")
...>  # => 'adefb.c'
...>  Text.delete(txt, 4, 1)
...>  # => 'adef.c'
...>
...>  # Get current offset index
...>  {:ok, a} = StickyIndex.get_offset(pos)
...>  # => 4
...>  assert a.index == 4
...> end)

Summary

Types

shared_type()

@type shared_type() ::
  %Yex.Array{doc: term(), reference: term()}
  | %Yex.Text{doc: term(), reference: term()}
  | %Yex.XmlElement{doc: term(), reference: term()}
  | %Yex.XmlText{doc: term(), reference: term()}
  | %Yex.XmlFragment{doc: term(), reference: term()}

t()

@type t() :: %Yex.StickyIndex{
  assoc: :before | :after,
  doc: Yex.Doc.t(),
  reference: reference()
}

Functions

get_offset(sticky_index)

@spec get_offset(t()) :: {:ok, %{index: integer(), assoc: :before | :after}} | :error

new(shared_type, index, assoc)

@spec new(shared_type(), integer(), :before | :after) :: t()