Tokens

Token grid rendering for all three selection modes (gap, word, span).

Selection Helpers

Determine token visual state based on selection mode and position.

# Gap mode: no tokens selected
assert _is_token_selected(0, "gap", 0, 0) is False
assert _is_token_selected(5, "gap", 5, 5) is False

# Word mode: only anchor token
assert _is_token_selected(3, "word", 3, 3) is True
assert _is_token_selected(2, "word", 3, 3) is False

# Span mode: range inclusive
assert _is_token_selected(3, "span", 2, 5) is True
assert _is_token_selected(2, "span", 2, 5) is True
assert _is_token_selected(5, "span", 2, 5) is True
assert _is_token_selected(1, "span", 2, 5) is False
assert _is_token_selected(6, "span", 2, 5) is False
# Reversed anchor/focus
assert _is_token_selected(3, "span", 5, 2) is True

print("_is_token_selected tests passed!")
_is_token_selected tests passed!

Caret Indicator

Token Rendering


render_token


def render_token(
    token:Token, # token to render
    config:TokenSelectorConfig, # config for this instance
    ids:TokenSelectorHtmlIds, # HTML IDs
    state:Optional=None, # current state for highlighting
    style_callback:Optional=None, # (TokenRenderContext) -> str for extra CSS
    read_only:bool=False, # disable interaction
)->Any: # Span element for this token

Render a single interactive word token.

from cjm_fasthtml_token_selector.core.config import _reset_prefix_counter

_reset_prefix_counter()
cfg = TokenSelectorConfig(prefix="test")
test_ids = TokenSelectorHtmlIds(prefix="test")
t = Token("hello", 0)
s = TokenSelectorState(anchor=0, focus=0, word_count=5)

# Basic render
el = render_token(t, cfg, test_ids, s)
assert el is not None
print("render_token basic test passed!")

# Read-only: no onclick
el_ro = render_token(t, cfg, test_ids, s, read_only=True)
assert el_ro is not None
print("render_token read_only test passed!")
render_token basic test passed!
render_token read_only test passed!

End Token


render_end_token


def render_end_token(
    config:TokenSelectorConfig, # config for this instance
    ids:TokenSelectorHtmlIds, # HTML IDs
    state:Optional=None, # current state
    read_only:bool=False, # disable interaction
)->Any: # end sentinel Span element

Render the end-of-text sentinel token.

_reset_prefix_counter()
cfg = TokenSelectorConfig(prefix="test")
test_ids = TokenSelectorHtmlIds(prefix="test")
s = TokenSelectorState(anchor=5, focus=5, word_count=5)

el = render_end_token(cfg, test_ids, s)
assert el is not None
print("render_end_token test passed!")
render_end_token test passed!

Token Grid


render_token_grid


def render_token_grid(
    tokens:List, # token list to render
    config:TokenSelectorConfig, # config for this instance
    ids:TokenSelectorHtmlIds, # HTML IDs
    state:Optional=None, # current state for highlighting
    style_callback:Optional=None, # (TokenRenderContext) -> str for extra CSS
    read_only:bool=False, # disable all interaction
)->Any: # Div containing the complete token grid

Render the full interactive token grid.

from cjm_fasthtml_token_selector.helpers.tokenizer import tokenize

_reset_prefix_counter()
cfg = TokenSelectorConfig(prefix="test")
test_ids = TokenSelectorHtmlIds(prefix="test")
tokens = tokenize("the quick brown fox")
s = TokenSelectorState(anchor=2, focus=2, word_count=4)

grid = render_token_grid(tokens, cfg, test_ids, s)
assert grid is not None
print("render_token_grid test passed!")

# Read-only
grid_ro = render_token_grid(tokens, cfg, test_ids, read_only=True)
assert grid_ro is not None
print("render_token_grid read_only test passed!")

# Word mode
cfg_word = TokenSelectorConfig(prefix="test-w", selection_mode="word")
ids_word = TokenSelectorHtmlIds(prefix="test-w")
s_word = TokenSelectorState(anchor=1, focus=1, word_count=4)
grid_word = render_token_grid(tokens, cfg_word, ids_word, s_word)
assert grid_word is not None
print("render_token_grid word mode test passed!")

# Span mode
cfg_span = TokenSelectorConfig(prefix="test-s", selection_mode="span")
ids_span = TokenSelectorHtmlIds(prefix="test-s")
s_span = TokenSelectorState(anchor=1, focus=3, word_count=4)
grid_span = render_token_grid(tokens, cfg_span, ids_span, s_span)
assert grid_span is not None
print("render_token_grid span mode test passed!")
render_token_grid test passed!
render_token_grid read_only test passed!
render_token_grid word mode test passed!
render_token_grid span mode test passed!