UI (fnord v0.8.82)
View SourceUser interface functions for output, logging, and user interaction.
Context Warnings for Interactive UI
Interactive UI functions (confirm/1, choose/2, prompt/1) can cause deadlocks
when called from certain contexts and must be wrapped appropriately.
GenServer Callbacks
Use UI.Queue.run_from_genserver/1 to prevent deadlocks:
def handle_call(:delete_item, _from, state) do
confirmed = UI.Queue.run_from_genserver(fn ->
UI.confirm("Delete this item?")
end)
# ...
endServices.Globals.Spawn.async and Spawned Processes
Use UI.Queue.run_from_task/1 when tasks need to participate in an existing UI interaction:
task = Services.Globals.Spawn.async(fn ->
UI.Queue.run_from_task(fn ->
UI.confirm("Process this item?")
end)
end)Creating UI Components
Use UI.interact/1 to group multiple UI operations into a single atomic component:
def confirm_with_details(item) do
UI.interact(fn ->
UI.info("Item details: #{item.name}")
UI.puts("Size: #{item.size}, Modified: #{item.date}")
UI.confirm("Delete this item?")
end)
endNon-interactive functions (info/2, warn/2, error/2, puts/1, say/1) are safe
to call directly from any context.
Interactive vs Non-Interactive Functions
Interactive (require context wrappers in GenServer/Task contexts):
Non-interactive (safe to call directly from any context):
Summary
Functions
Execute a function as a single interaction unit. All UI calls within the function (puts, log, choose, prompt, etc.) will be treated as part of this interaction and execute immediately without queuing.
Functions
Execute a function as a single interaction unit. All UI calls within the function (puts, log, choose, prompt, etc.) will be treated as part of this interaction and execute immediately without queuing.
This is useful for composite TUI components that combine multiple UI elements.
@spec log_usage(AI.Model.t(), non_neg_integer() | map()) :: :ok
@spec warning_banner(binary()) :: :ok