brick-0.34.1: A declarative terminal user interface library

Brick.Forms

Description

NOTE: This API is experimental and will probably change. Please try it out! Feedback is very much appreciated, and your patience in the face of breaking API changes is also appreciated!

For a fuller introduction to this API, see the "Input Forms" section of the Brick User Guide. Also see the demonstration programs for examples of forms in action.

This module provides an input form API. This API allows you to construct an input interface based on a data type of your choice. Each input in the form corresponds to a field in your data type. This API then automatically dispatches keyboard and mouse input events to each form input field, manages rendering of the form, notifies the user when a form field's value is invalid, and stores valid inputs in your data type when possible.

This module provides the API to create forms, populate them with some basic input field types, render forms, handle form events, and create custom input field types.

A form has both a visual representation and a corresponding data structure representing the latest valid values for that form (referred to as the "state" of the form). A FormField is a single input component in the form and a FormFieldState defines the linkage between that visual input and the corresponding portion of the state represented by that visual; there may be multiple FormFields combined for a single FormFieldState (e.g. a radio button sequence).

Bear in mind that for most uses, the FormField and FormFieldState types will not be used directly. Instead, the constructors for various field types (such as editTextField) will be used instead.

Synopsis

# Data types

data Form s e n Source #

A form: a sequence of input fields that manipulate the fields of an underlying state that you choose.

Type variables are as follows:

• s - the data type of your choosing containing the values manipulated by the fields in this form.
• e - your application's event type
• n - your application's resource name type

data FormFieldState s e n where Source #

A form field state accompanied by the fields that manipulate that state. The idea is that some record field in your form state has one or more form fields that manipulate that value. This data type maps that state field (using a lens into your state) to the form input fields responsible for managing that state field, along with a current value for that state field and an optional function to control how the form inputs are rendered.

Most form fields will just have one input, such as text editors, but others, such as radio button collections, will have many, which is why this type supports more than one input corresponding to a state field.

Type variables are as follows:

• s - the data type containing the value manipulated by these form fields.
• e - your application's event type
• n - your application's resource name type

Constructors

 FormFieldState :: {..} -> FormFieldState s e n FieldsformFieldState :: bThe current state value associated with the field collection. Note that this type is existential. All form fields in the collection must validate to this type.formFieldLens :: Lens' s aA lens to extract and store a successfully-validated form input back into your form state.formFields :: [FormField a b e n]The form fields, in order, that the user will interact with to manipulate this state value.formFieldRenderHelper :: Widget n -> Widget nA helper function to augment the rendered representation of this collection of form fields. It receives the default representation and can augment it, for example, by adding a label on the left.

data FormField a b e n Source #

A form field. This represents an interactive input field in the form. Its user input is validated and thus converted into a type of your choosing.

Type variables are as follows:

• a - the type of the field in your form state that this field manipulates
• b - the form field's internal state type
• e - your application's event type
• n - your application's resource name type

Constructors

 FormField FieldsformFieldName :: nThe name identifying this form field.formFieldValidate :: b -> Maybe aA validation function converting this field's state into a value of your choosing. Nothing indicates a validation failure. For example, this might validate an Editor state value by parsing its text contents s aan integer and return Maybe Int. This is for pure avalue validation; if additional validation is required a(e.g. via IO), use this field's state value in an aexternal validation routine and use setFieldValid to afeed the result back into the form.formFieldExternallyValid :: BoolWhether the field is valid according to an external validation source. Defaults to always being True and can be set with setFieldValid. The value of this field also affects the behavior of allFieldsValid and getInvalidFields.formFieldRender :: Bool -> b -> Widget nA function to render this form field. Parameters are whether the field is currently focused, followed by the field state.formFieldHandleEvent :: BrickEvent n e -> b -> EventM n bAn event handler for this field. This receives the event and the field state and returns a new field state.

# Creating and using forms

Arguments

 :: [s -> FormFieldState s e n] The form field constructors. This is intended to be populated using the various field constructors in this module. -> s The initial form state used to populate the fields. -> Form s e n

Create a new form with the specified input fields and an initial form state. The fields are initialized from the state using their state lenses and the first form input is focused initially.

formFocus :: Form s e n -> FocusRing n Source #

The focus ring for the form, indicating which form field has input focus.

formState :: Form s e n -> s Source #

The current state of the form. Forms guarantee that only valid inputs ever get stored in the state, and that after each input event on a form field, if that field contains a valid state value then the value is immediately saved to its corresponding field in this state value using the form field's lens over s.

handleFormEvent :: Eq n => BrickEvent n e -> Form s e n -> EventM n (Form s e n) Source #

Dispatch an event to the appropriate form field and return a new form. This handles the following events in this order:

• On Tab keypresses, this changes the focus to the next field in the form.
• On Shift-Tab keypresses, this changes the focus to the previous field in the form.
• On mouse button presses (regardless of button or modifier), the focus is changed to the clicked form field and the event is forwarded to the event handler for the clicked form field.
• On Left or Up, if the currently-focused field is part of a collection (e.g. radio buttons), the previous entry in the collection is focused.
• On Right or Down, if the currently-focused field is part of a collection (e.g. radio buttons), the next entry in the collection is focused.
• All other events are forwarded to the currently focused form field.

In all cases where an event is forwarded to a form field, validation of the field's input state is performed immediately after the event has been handled. If the form field's input state succeeds validation using the field's validator function, its value is immediately stored in the form state using the form field's state lens. The external validation flag is ignored during this step to ensure that external validators have a chance to get the intermediate validated value.

renderForm :: Eq n => Form s e n -> Widget n Source #

Render a form.

For each form field, each input for the field is rendered using the implementation provided by its FormField. The inputs are then vertically concatenated with vBox and then augmented using the form field's rendering augmentation function (see @@=). Fields with invalid inputs (either due to built-in validator failure or due to external validation failure via setFieldValid) will be displayed using the invalidFormInputAttr attribute.

The augmented field renderings are then placed in a vBox and returned.

(@@=) :: (Widget n -> Widget n) -> (s -> FormFieldState s e n) -> s -> FormFieldState s e n infixr 5 Source #

Compose a new rendering augmentation function with the one in the form field collection. For example, we might put a label on the left side of a form field:

(str "Please check: " <+>) @@= checkboxField alive AliveField "Alive?"

This can also be used to add multiple augmentations and associates right:

(withDefAttr someAttribute) @@=
(str "Please check: " <+>) @@=
checkboxField alive AliveField "Alive?"

allFieldsValid :: Form s e n -> Bool Source #

Returns whether all form fields in the form currently have valid values according to the fields' validation functions. This is useful when we need to decide whether the form state is up to date with respect to the form input fields.

invalidFields :: Form s e n -> [n] Source #

Returns the resource names associated with all form input fields that currently have invalid inputs. This is useful when we need to force the user to repair invalid inputs before moving on from a form editing session.

Arguments

 :: Eq n => Bool Whether the field is considered valid. -> n The name of the form field to set as (in)valid. -> Form s e n The form to modify. -> Form s e n

Manually indicate that a field has invalid contents. This can be useful in situations where validation beyond the form element's validator needs to be performed and the result of that validation needs to be fed back into the form state.

# Simple form field constructors

Arguments

 :: (Ord n, Show n) => Lens' s Text The state lens for this value. -> n The resource name for the input field. -> Maybe Int The optional line limit for the editor (see editor). -> s The initial form state. -> FormFieldState s e n

A form field using an editor to edit a text value. Since the value is free-form text, it is always valid.

This field responds to all events handled by editor, including mouse events.

Arguments

 :: (Ord n, Show n, Read a, Show a) => Lens' s a The state lens for this value. -> n The resource name for the input field. -> s The initial form state. -> FormFieldState s e n

A form field using a single-line editor to edit the Show representation of a state field value of type a. This automatically uses its Read instance to validate the input. This field is mostly useful in cases where the user-facing representation of a value matches the Show representation exactly, such as with Int.

This field responds to all events handled by editor, including mouse events.

Arguments

 :: (Ord n, Show n) => Lens' s Text The state lens for this value. -> n The resource name for the input field. -> s The initial form state. -> FormFieldState s e n

A form field using a single-line editor to edit a free-form text value represented as a password. The value is always considered valid and is always represented with one asterisk per password character.

This field responds to all events handled by editor, including mouse events.

Arguments

 :: (Ord n, Show n, Eq a) => Lens' s a The state lens for this value. -> [(a, n, Text)] The available choices, in order. Each choice has a value of type a, a resource name, and a text label. -> s The initial form state. -> FormFieldState s e n

A form field for selecting a single choice from a set of possible choices. Each choice has an associated value and text label.

This field responds to Space keypresses to select a radio button option and to mouse clicks.

Arguments

 :: (Ord n, Show n) => Lens' s Bool The state lens for this value. -> n The resource name for the input field. -> Text The label for the check box, to appear at its right. -> s The initial form state. -> FormFieldState s e n

A form field for manipulating a boolean value. This represents True as [X] label and False as [ ] label.

This field responds to Space keypresses to toggle the checkbox and to mouse clicks.

Arguments

 :: (Ord n, Show n) => Lens' s a The state lens for this value. -> n The resource name for the input field. -> Maybe Int The optional line limit for the editor (see editor). -> (a -> Text) The initialization function that turns your value into the editor's initial contents. The resulting text may contain newlines. -> ([Text] -> Maybe a) The validation function that converts the editors contents into a valid value of type a. -> ([Text] -> Widget n) The rendering function for the editor's contents (see renderEditor). -> (Widget n -> Widget n) A rendering augmentation function to adjust the representation of the rendered editor. -> s The initial form state. -> FormFieldState s e n

A form field for using an editor to edit the text representation of a value. The other editing fields in this module are special cases of this function.

This field responds to all events handled by editor, including mouse events.

# Attributes

The namespace for the other form attributes.

The attribute for form input fields with invalid values.

The attribute for form input fields that have the focus.