compositor

package
v0.0.0-...-8b058bf Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 17, 2022 License: MIT Imports: 6 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Compositor

type Compositor struct {
	// The state of a compositor-based TUI is used to determine how to flow updates and views.
	State State
	// Compositors may be used in models at any level of a TUI; when compositors are submodels, they need to be able to
	// handle reporting that they are no longer active and why.
	IsSubmodel bool
	// Compositors can record and display fatal errors to the user; this simplifies handling non-recoverable errors.
	FatalError error
	// Compositors can be instantiated with a particular width and update it as needed. This field caches that value so
	// it can be reused with querying the terminal.
	Width int
	// Compositors can be instantiated with a particular height and update it as needed. This field caches that value so
	// it can be reused with querying the terminal.
	Height int
	// Compositors always include a confirmation model, but it need not be used.
	Confirmation *confirmation.Model
	// Compositors always include a confirmation model, but it need not be used.
	Selection *selection.Model
	// Compositors always include a confirmation model, but it need not be used.
	TextInput *textinput.Model
}

A Compositor is a shareable configuration for TUIs built with bubbletea, promptkit, and lipgloss. It provides some default behaviors and expectations for how a TUI is constructed and used.

func (*Compositor) Broken

func (model *Compositor) Broken() tea.Msg

This command should be called when an unhandleable problem occurs in the model

func (*Compositor) Cancelled

func (model *Compositor) Cancelled() tea.Msg

This command should be called when the user chooses to exit early from a compositor-based model when it is being used as a submodel.

func (*Compositor) Done

func (model *Compositor) Done() tea.Msg

This command should be called when the user chooses to exit gracefully after completing a compositor-based model when it is being used as a submodel.

func (*Compositor) RecordFatalError

func (model *Compositor) RecordFatalError(err error) tea.Cmd

When a compositor-based model encounters an error it cannot handle, it should record that error as fatal; this method is a shorthand for doing so, saving the error and reporting that the model is broken.

func (*Compositor) SetSize

func (sharedModel *Compositor) SetSize(width int, height int)

This method sets the cached width and height of a compositor-based model but does not otherwise change any behavior.

func (*Compositor) ViewFatalError

func (sharedModel *Compositor) ViewFatalError(options ...terminal.Option) string

This method returns the default view for a compositor-based model when a fatal error has been recorded.

type EndMsg

type EndMsg struct{}

When a compositor-based model is used as a submodel for another, it should report an end message instead of quitting the TUI.

type Modeler

type Modeler interface {
	// The Init method runs when the TUI starts
	Init() tea.Cmd
	// The SetAndStartState method is used to move into another top-level state and typically that state's default
	// substate.
	SetAndStartState(state State) (cmd tea.Cmd)
	// The Update method runs whenever the TUI receives input from the user or system and should explicitly pass the
	// update message to UpdateOnKeyPress (if the user pressed a key), UpdateOnSubmodelEnded (if the TUI received an end
	// message from a submodel), or UpdateFallThrough (if the current model does not explicitly handle the input message).
	Update(msg tea.Msg) (tea.Model, tea.Cmd)
	// The UpdateFallThrough method passes the update message to the correct submodel based on the current state/substate.
	UpdateFallThrough(msg tea.Msg) (cmd tea.Cmd)
	// The UpdateOnKeyPress method handles the update message based on the current state/substate and key pressed.
	UpdateOnKeyPress(msg tea.KeyMsg) (cmd tea.Cmd)
	// The UpdateOnSubmodelEnded method handles what to do when a submodel ends based on the current state/substate.
	UpdateOnSubmodelEnded() (cmd tea.Cmd)
	// The View method returns a string for rendering to the terminal
	View() string
}

A Modeler is a bubbletea Model which follows the design pattern the Compositor supports; namely the use of state and substate to control flow and view of the TUI.

type Option

type Option[Model Modeler] func(model Model)

Compositor-based Models should use the variadic option model by having their New function accept options to change the model before returning it. These options should be defined as functions with semantically clear names and only modify the model. For example:

type MyModel struct {
  *compositor.Compositor
  Required string
  Foo string
}
func WithFoo(foo string) compositor.Option[*MyModel] {
  return func(model *MyModel) {
    model.Foo = foo
  }
}
func New(required, options ...compositor.Option[*MyModel]) *MyModel {
  model := &MyModel{Required: required}

  for _, option := range options {
    option(model)
  }

  return model
}

type State

type State int

The State of a Compositor is used extensively when determining how to process view and update calls to the model. The shared states defined in this library can be used by any model inheriting the Compositor. When defining additional states specific to your application, be sure to start your list of State constants with a higher integer.

For example:

const (
  StateCreating compositor.State = iota + 100
  StateEditing
)

The States you define should be unique within your application and not conflict with the states defined here.

const (
	// When the state is unknown, something has gone wrong but the model is not necessarily broken
	StateUnknown State = iota
	// A fatal error has occurred
	StateBroken
	// The model is not actively in use but has been initialized and may be used again
	StateReady
	// The model has ended, cancelled by the user
	StateCancelled
	// The model has ended, the user has chosen to return to the program flow
	StateDone
	// The model is paused while the application saves
	StateSavingConfiguration
	// The model has finished saving the application but is not yet in another state
	StateSavedConfiguration
)

type SubstateInterface

type SubstateInterface[Model Modeler] interface {
	// The Start method for a substate should perform the necessary setup for the TUI to move into this substate
	Start(model Model) (cmd tea.Cmd)
	// The UpdateOnEnded method for a substate handles when a submodel associated with the substate reports an
	// end message
	UpdateOnEnded(model Model) (cmd tea.Cmd)
	// The UpdateOnEnter method for a substate handles when the user presses the enter key in that substate
	UpdateOnEnter(model Model) (cmd tea.Cmd)
	// The UpdateOnEsc method for a substate handles when the user presses the escape key in that substate
	UpdateOnEsc(model Model) (cmd tea.Cmd)
	// The UpdateOnFallThrough method passes the update message to the correct submodel
	UpdateOnFallThrough(model Model, msg tea.Msg) (cmd tea.Cmd)
	// The View method ensures the correct view for this substate is rendered and returned
	View(model Model) (view string)
}

Compositor-based Models should use substates if they have multiple distinct flows depending on the higher-level state; for example, if the TUI creates an object and edits it, it might have the creating and editing substates. Substates provide a standardized interface for managing flow and view of the model.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL