AshTui.State (AshTui v0.3.1)

Copy Markdown View Source

State struct and pure navigation logic for the Ash TUI explorer.

All state transitions are pure functions: handle_key(state, key) -> state. No side effects, no processes — just data transformation.

Summary

Functions

Returns the breadcrumb trail from the navigation stack.

Returns the items for the currently active detail tab.

Processes a key press and returns the updated state.

Returns the list of items shown in the navigation panel.

Creates a new state from introspection data.

Types

t()

@type t() :: %AshTui.State{
  current_domain: AshTui.Introspection.DomainInfo.t() | nil,
  current_resource: AshTui.Introspection.ResourceInfo.t() | nil,
  current_tab: tab(),
  detail_overlay: AshTui.Introspection.AttributeInfo.t() | nil,
  detail_selected: non_neg_integer(),
  domains: [AshTui.Introspection.DomainInfo.t()],
  focus: :nav | :detail,
  nav_selected: non_neg_integer(),
  nav_stack: [{atom(), atom(), tab()}],
  search_input: reference() | nil,
  searching: boolean(),
  show_help: boolean()
}

tab()

@type tab() :: :attributes | :actions | :relationships

Functions

detail_items(state)

Returns the items for the currently active detail tab.

Examples

iex> domains = AshTui.Introspection.from_data([
...>   %{
...>     name: MyApp.Accounts,
...>     resources: [
...>       %{
...>         name: MyApp.Accounts.User,
...>         attributes: [%{name: :id, type: :uuid, primary_key?: true}],
...>         actions: [%{name: :read, type: :read, primary?: true}],
...>         relationships: []
...>       }
...>     ]
...>   }
...> ])
iex> state = AshTui.State.new(domains)
iex> [attr] = AshTui.State.detail_items(state)
iex> attr.name
:id

iex> AshTui.State.detail_items(%AshTui.State{current_resource: nil})
[]

handle_key(state, key)

@spec handle_key(t(), String.t()) :: t()

Processes a key press and returns the updated state.

Handles vim-style navigation (j/k/h/l), tab switching (tab, 1/2/3), enter/esc for selection and back-navigation, ? for help, and / for search.

Examples

iex> domains = AshTui.Introspection.from_data([
...>   %{
...>     name: MyApp.Accounts,
...>     resources: [
...>       %{
...>         name: MyApp.Accounts.User,
...>         attributes: [%{name: :id, type: :uuid, primary_key?: true}],
...>         actions: [],
...>         relationships: []
...>       }
...>     ]
...>   }
...> ])
iex> state = AshTui.State.new(domains)
iex> state = AshTui.State.handle_key(state, "?")
iex> state.show_help
true
iex> state = AshTui.State.handle_key(state, "any")
iex> state.show_help
false

iex> domains = AshTui.Introspection.from_data([
...>   %{
...>     name: MyApp.Accounts,
...>     resources: [
...>       %{
...>         name: MyApp.Accounts.User,
...>         attributes: [%{name: :id, type: :uuid, primary_key?: true}],
...>         actions: [],
...>         relationships: []
...>       }
...>     ]
...>   }
...> ])
iex> state = AshTui.State.new(domains)
iex> state = AshTui.State.handle_key(state, "l")
iex> state.focus
:detail
iex> state = AshTui.State.handle_key(state, "h")
iex> state.focus
:nav

new(domains)

@spec new([AshTui.Introspection.DomainInfo.t()]) :: t()

Creates a new state from introspection data.

Examples

iex> domains = AshTui.Introspection.from_data([
...>   %{
...>     name: MyApp.Accounts,
...>     resources: [
...>       %{
...>         name: MyApp.Accounts.User,
...>         attributes: [%{name: :id, type: :uuid, primary_key?: true}],
...>         actions: [],
...>         relationships: []
...>       }
...>     ]
...>   }
...> ])
iex> state = AshTui.State.new(domains)
iex> state.current_domain.name
MyApp.Accounts
iex> state.current_resource.name
MyApp.Accounts.User
iex> state.current_tab
:attributes

iex> state = AshTui.State.new([])
iex> state.current_domain
nil