internal

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Dec 10, 2023 License: GPL-3.0 Imports: 21 Imported by: 0

Documentation

Overview

internal contains the core parts of vidar that make it work as a text editor. These are the components that make the UI work the way it does.

We are using the 'internal' package here to limit how much plugins can override so that remote pairing plugins (and anything else that would need to sync core operations between multiple instances of vidar) can work without forcing all instances of vidar to have the same set of plugins.

Index

Constants

View Source
const (
	ErrPlaceholder = constant.Error("cannot add elements to a placeholder")
	ErrMustEmpty   = constant.Error("container only holds one element and is full")
	ErrNotFound    = constant.Error("container does not contain requested element")
	ErrNoUI        = constant.Error("no UI element found")
)
View Source
const ErrDone = err.Const("done")

ErrDone is used to signal that something is done. For example, when accepting input from a user prompt, a PromptEventHandler may return ErrDone to signal that the user has finished responding to the prompt.

View Source
const (
	// ErrModified is returned when saving without force if the file has changed
	// on disk.
	ErrModified = constant.Error("file modified on disk")
)
View Source
const MaxDisplayFor = 10 * time.Second

MaxDisplayFor is the maximum duration allowed in DisplayFor.

View Source
const (
	PromptMaxExtra = 6
)

Variables

This section is empty.

Functions

func BinderFor

func BinderFor(_ context.Context, elem any) (input.Binder, error)

Types

type Action

type Action interface {
	input.Action
}

Action is a copy of the input.Action interface type, to be used as a parameter or return type when we want to prevent plugins from using a method.

type Actions

type Actions struct {
	// contains filtered or unexported fields
}

Actions tracks a set of all available actions, an input.Binder, and the subset of Action values that bound successfully to the input.Binder.

func NewActions

func NewActions(ctx context.Context, b Binder, all []Action) (*Actions, error)

NewActions constructs a new Actions type using a binder and a list of all available actions.

func (*Actions) Binder

func (a *Actions) Binder(ctx context.Context, act Action) (Binder, bool)

Binder will return the input.Binder that act is bound to on a.

func (*Actions) For

func (a *Actions) For(ctx context.Context, b Binder) (*Actions, error)

For returns a copy of a, but with all actions bound to b. Any actions which were previously bound to a different binder but reject b as a valid binder for them will remain bound to their previous Binder.

func (*Actions) Named

func (a *Actions) Named(ctx context.Context, name string) input.Action

Named returns the currently-bound action named name.

type Binder

type Binder interface {
	input.Binder
}

Binder is a copy of the input.Binder interface type, to be used as a parameter or return type when we want to prevent plugins from using a method.

type Container

type Container interface {
	UIBinder
	Parent(context.Context) Container
	SetParent(context.Context, Container)
	Children(context.Context) []Binder
	Add(context.Context, Binder) error
	Remove(context.Context, Binder) (nearest Binder, _ error)
}

type DisplayOpt

type DisplayOpt func(Information) Information

DisplayOpt is an option function to change how information is displayed to the user.

func DisplayFor

func DisplayFor(d time.Duration) DisplayOpt

DisplayFor sets a minimum duration to display information to the user. The information may remain on screen longer than the minimum, but no less.

An error will be returned if d is greater than MaxDisplayFor.

func DisplayInfo

func DisplayInfo(spans ...ui.Span) DisplayOpt

DisplayInfo displays information to the user. Most of the time, this should be succinct, single-line information. Info can *only* override other info.

An error will be returned if the information cannot be displayed.

type EditApplier

type EditApplier interface {
	input.Operation
	ApplyEdit(...input.Edit) input.Operation
}

type EditHistory

type EditHistory struct {
	Before, After State
	Edit          input.Edit
}

type Editor

type Editor struct {
	// contains filtered or unexported fields
}

Editor controls all of the important parts of editing text. It is responsible for tracking text changes, reporting updated text to the UI, and keeping track of the currently open file (and any changes on disk).

TODO: really, an Editor is made up of several chunks (functions, type definitions, variables, etc), each of which could have its own actions bound. For example, you wouldn't want word wrap bound to a function body, but you would want it bound to a comment block.

We could in theory provide a mechanism for setting up separate input.Binder types for each chunk of code. This would also make syntax highlighting a little easier, since each individual input.Binder would have its own color and translation rules. When an edit operation applies to that input.Binder, it expands its range, automatically keeping existing syntax highlights relevant.

func NewEditor

func NewEditor(ctx context.Context, ui ui.TextBox, opts ...EditorOpt) (*Editor, error)

func (*Editor) Bound

func (e *Editor) Bound(context.Context) input.Actions

func (*Editor) Close

func (e *Editor) Close(ctx context.Context) Error

func (*Editor) Get

func (e *Editor) Get(ctx context.Context, a input.Action, key any) (any, bool)

func (*Editor) HasChanges

func (e *Editor) HasChanges(ctx context.Context) bool

HasChanges reports whether or not e has local changes from its on-disk state. If e is not editing a file on disk, this will always return false.

func (*Editor) Name

func (e *Editor) Name(context.Context) string

func (*Editor) Path

func (e *Editor) Path(context.Context) (string, bool)

func (*Editor) RawText

func (e *Editor) RawText(context.Context) *PieceTable

func (*Editor) Run

func (e *Editor) Run(ctx context.Context, a input.Action) error

func (*Editor) Save

func (e *Editor) Save(ctx context.Context, force bool) error

func (*Editor) ScrollPos

func (e *Editor) ScrollPos(ctx context.Context, style ui.ScrollType, sel Selection) error

func (*Editor) Selections

func (e *Editor) Selections(context.Context) (primary caret.Selection, secondary []caret.Selection)

func (*Editor) Set

func (e *Editor) Set(ctx context.Context, a input.Action, key, value any) bool

func (*Editor) SetActions

func (e *Editor) SetActions(_ context.Context, a *Actions)

func (*Editor) SetSelections

func (e *Editor) SetSelections(ctx context.Context, primary Selection, secondary ...Selection)

func (*Editor) State

func (e *Editor) State(ctx context.Context) text.State

func (*Editor) UI

func (e *Editor) UI(context.Context) Element

func (*Editor) UpdateSpans

func (e *Editor) UpdateSpans(ctx context.Context, spans ...Span)

func (*Editor) Visible

func (e *Editor) Visible(ctx context.Context) ui.Box

type EditorOpt

type EditorOpt func(context.Context, editorOpts) (editorOpts, error)

func EditorName

func EditorName(name string) EditorOpt

func EditorOpenFile

func EditorOpenFile(path string) EditorOpt

func EditorReader

func EditorReader(r io.Reader) EditorOpt

type Element

type Element any

type Empty

type Empty struct{}

Empty is used as an empty binder during editor startup. Since there are no windows yet and the first window needs to be constructed by an Action (specifically: a *WindowManager), this is a sort of placeholder for a nil binder, without the disadvantages of causing panics.

func (Empty) Bound

func (Empty) Get

func (Empty) Run

func (Empty) Set

func (Empty) SetActions

func (Empty) SetActions(context.Context, *Actions)

type Error

type Error interface {
	error
}

type Event

type Event struct {
	Ev *input.KeyEvent
	Ed *input.Edit
}

Event is a wrapper for events (e.g. key strokes). We use it to ensure that third parties can't directly send events to the InfoBox - they must go through an Operation to send events.

type Focuser

type Focuser interface {
	input.Operation
	Focus(input.Binder) input.Operation
}

type InfoBox

type InfoBox struct {
	// contains filtered or unexported fields
}

InfoBox is a type which can be used to display information to the user. It can also be used to get a response from the user, like a standard dialog window. Depending on the ui library in use, this _may_ create standard dialog windows; but vidar is designed to mimic the style of vim and emacs, where the monolog/dialog is in a little pane at the bottom of the editor window.

func NewInfoBox

func NewInfoBox(ctx context.Context, c ui.Creator) (*InfoBox, error)

NewInfoBox creates an InfoBox and sets up its UI element(s).

func (*InfoBox) Bound

func (i *InfoBox) Bound(context.Context) input.Actions

Bound implements input.Binder

func (*InfoBox) Display

func (i *InfoBox) Display(ctx context.Context, opts ...DisplayOpt) error

Display displays something to the user.

func (*InfoBox) Event

func (i *InfoBox) Event(ctx context.Context, ev Event) error

Event informs i about events.

func (*InfoBox) Get

func (e *InfoBox) Get(ctx context.Context, a input.Action, key any) (any, bool)

func (*InfoBox) Input

func (i *InfoBox) Input(ctx context.Context) Element

Input returns i's input element if Prompt has been called.

func (*InfoBox) Prompt

func (i *InfoBox) Prompt(ctx context.Context, opts ...PromptOpt) error

Prompt prompts information from the user.

func (*InfoBox) Run

func (i *InfoBox) Run(ctx context.Context, a input.Action) error

func (*InfoBox) Set

func (e *InfoBox) Set(ctx context.Context, a input.Action, key, value any) bool

func (*InfoBox) SetActions

func (i *InfoBox) SetActions(_ context.Context, acts *Actions)

func (*InfoBox) UI

func (i *InfoBox) UI(context.Context) Element

UI returns i's UI element.

type Information

type Information struct {
	Spans    []ui.Span
	Priority Priority
	Until    <-chan time.Time
}

type KeyHandler

type KeyHandler struct {
	// contains filtered or unexported fields
}

func NewKeyHandler

func NewKeyHandler(ctx context.Context) *KeyHandler

func (*KeyHandler) CharInput

func (h *KeyHandler) CharInput(ctx context.Context, r rune)

func (*KeyHandler) KeyDown

func (h *KeyHandler) KeyDown(ctx context.Context, k input.Key)

func (*KeyHandler) KeyUp

func (h *KeyHandler) KeyUp(ctx context.Context, k input.Key)

func (*KeyHandler) SetWindow

func (h *KeyHandler) SetWindow(w *Window)

SetWindow tells h which ui.Window it is handling keys for.

type MultiContainer

type MultiContainer struct {
	// contains filtered or unexported fields
}

func NewMultiContainer

func NewMultiContainer(_ context.Context, parent Container, layout ui.Layout) (*MultiContainer, error)

func (*MultiContainer) Add

func (p *MultiContainer) Add(ctx context.Context, b Binder) error

func (*MultiContainer) Bound

func (*MultiContainer) Children

func (p *MultiContainer) Children(context.Context) []Binder

func (*MultiContainer) Get

func (e *MultiContainer) Get(ctx context.Context, a input.Action, key any) (any, bool)

func (*MultiContainer) Parent

func (*MultiContainer) Remove

func (p *MultiContainer) Remove(ctx context.Context, b Binder) (Binder, error)

func (*MultiContainer) Run

func (*MultiContainer) Set

func (e *MultiContainer) Set(ctx context.Context, a input.Action, key, value any) bool

func (*MultiContainer) SetActions

func (p *MultiContainer) SetActions(_ context.Context, a *Actions)

func (*MultiContainer) SetParent

func (p *MultiContainer) SetParent(_ context.Context, parent Container)

func (*MultiContainer) UI

type PieceTable

type PieceTable struct {
	// contains filtered or unexported fields
}

PieceTable implements a piece table, a modern storage structure for text editors, used by the likes of atom and vscode. It relies on a read-only origin buffer, an append-only add buffer, and a table referencing the two buffers to create the full block of text.

Since the text in the origin and add buffers don't change, copies of the table's state are safe to use concurrently with write operations, without making a copy of the full text.

func NewPieceTable

func NewPieceTable(_ context.Context, orig []rune) *PieceTable

NewPieceTable returns a new piece table using orig as the origin buffer.

func (*PieceTable) Apply

func (t *PieceTable) Apply(ctx context.Context, edits ...input.Edit) []EditHistory

Apply applies edits to t, updating its current state.

func (*PieceTable) ApplyLine

func (t *PieceTable) ApplyLine(ctx context.Context, lineEdits ...input.LineEdit) []EditHistory

ApplyLine applies LineEdits to t, updating its current state, and returns

func (*PieceTable) Restore

func (t *PieceTable) Restore(_ context.Context, s State)

RestoreState restores a previously-created State as t's state.

func (*PieceTable) State

func (t *PieceTable) State(context.Context) State

State returns t's current state.

type Placeholder

type Placeholder struct {
	// contains filtered or unexported fields
}

func NewPlaceholder

func NewPlaceholder(_ context.Context, parent Container, ui Element) (*Placeholder, error)

func (*Placeholder) Add

func (*Placeholder) Bound

func (*Placeholder) Children

func (p *Placeholder) Children(context.Context) []Binder

func (*Placeholder) Get

func (e *Placeholder) Get(ctx context.Context, a input.Action, key any) (any, bool)

func (*Placeholder) Parent

func (p *Placeholder) Parent(context.Context) Container

func (*Placeholder) Remove

func (p *Placeholder) Remove(context.Context, Binder) (Binder, error)

func (*Placeholder) Run

func (p *Placeholder) Run(ctx context.Context, a input.Action) error

func (*Placeholder) Set

func (e *Placeholder) Set(ctx context.Context, a input.Action, key, value any) bool

func (*Placeholder) SetActions

func (p *Placeholder) SetActions(_ context.Context, a *Actions)

func (*Placeholder) SetParent

func (p *Placeholder) SetParent(_ context.Context, parent Container)

func (*Placeholder) UI

type Priority

type Priority int
const (
	PriorityDebug Priority = iota
	PriorityInfo
	PriorityWarning
	PriorityError

	// PriorityCritical is for internal use only and will override all
	// plugin-defined messages.
	//
	// NOTE: there is no reason to leave this unexported, since any package that
	// has access to PriorityError could create PriorityCritical by passing in
	// (PriorityError + 1). We export it here so that we can document that it is
	// for internal use only. Packages which can make use of this package
	// directly *must* block third parties from passing in an arbitrary Priority
	// value.
	PriorityCritical
)

type Prompt

type Prompt struct {
	// Prompt is displayed before the user input element. A prompt message is
	// always required when prompting the user for input, thus this must be
	// non-empty on first prompt.
	//
	// On updates to the prompt, a nil value means to leave the prompt as is.
	Prompt []ui.Span

	// Extra is any extra data following the user input element. These could be
	// things like completion suggestions, fuzzy matches, or just some help to
	// explain what's going on.
	//
	// This may need to be zeroed out at times, so we use a pointer to a slice.
	// A nil pointer means to leave the current Extra value as-is on updates.
	// A pointer to an empty slice means to empty the current Extra value.
	Extra *[][]ui.Span

	// Input is the input text from the user. It may be altered by the
	// PromptEventHandler in order to change the text in the input, e.g. in
	// order to accept multiple values from the prompt or to apply completions.
	//
	// If it is non-nil, then it will override whatever is in the input text
	// box.
	Input *string
	// contains filtered or unexported fields
}

Prompt is a type to track a dialog-like prompt from an action to the user.

type PromptEventHandler

type PromptEventHandler interface {
	// Input will be called for all inputs that come from the user.
	Input(context.Context, input.Binder, Prompt, input.Edit) (Prompt, error)

	// KeyPress will be called for each key code that comes from the user.
	KeyPress(context.Context, input.Binder, Prompt, input.KeyEvent) (Prompt, error)

	// Run will be called when either Input or KeyPress returns ErrDone. The
	// input.Binder passed to Run will be the input.Binder that focus is being
	// returned to.
	Run(context.Context, Prompt, input.Binder) error
}

PromptEventHandler is a type which can handle events from a user prompt.

Unless otherwise noted, any input.Binder values passed in to the handler will be the the one which is receiving user input.

type PromptOpt

type PromptOpt func(Prompt) Prompt

PromptOpt is an option function to change how information is prompted from the user.

func PromptExtra

func PromptExtra(l ...[]ui.Span) PromptOpt

PromptExtra sets the initial extra spans that are displayed after the user input box. Each slice represents one line of extra info.

func PromptHandler

func PromptHandler(h PromptEventHandler) PromptOpt

PromptHandler sets the PromptEventHandler that will be called when the user writes input to the InfoBox.

func PromptInput

func PromptInput(s string) PromptOpt

PromptInput sets the initial user input to fill in the text box with.

func PromptReturnBinder

func PromptReturnBinder(b input.Binder) PromptOpt

PromptReturnBinder sets the input.Binder that the InfoBox will return focus to after it finishes getting user input.

func PromptSpans

func PromptSpans(l ...ui.Span) PromptOpt

PromptSpans sets the initial spans that will be displayed before the input.

type Selection

type Selection = caret.Selection

Selection is an alias for (pkg/caret).Selection. We use it in the internal package to ensure that only code that has access to the internal package may access certain methods.

type SettableBinder

type SettableBinder interface {
	Binder
	SetActions(context.Context, *Actions)
}

type SingleContainer

type SingleContainer struct {
	// contains filtered or unexported fields
}

func NewSingleContainer

func NewSingleContainer(_ context.Context, parent Container, layout ui.Layout) (*SingleContainer, error)

func (*SingleContainer) Add

func (p *SingleContainer) Add(ctx context.Context, b Binder) error

func (*SingleContainer) Bound

func (*SingleContainer) Children

func (p *SingleContainer) Children(context.Context) []Binder

func (*SingleContainer) Get

func (e *SingleContainer) Get(ctx context.Context, a input.Action, key any) (any, bool)

func (*SingleContainer) Parent

func (*SingleContainer) Remove

func (p *SingleContainer) Remove(ctx context.Context, b Binder) (Binder, error)

func (*SingleContainer) Run

func (*SingleContainer) Set

func (e *SingleContainer) Set(ctx context.Context, a input.Action, key, value any) bool

func (*SingleContainer) SetActions

func (p *SingleContainer) SetActions(_ context.Context, a *Actions)

func (*SingleContainer) SetParent

func (p *SingleContainer) SetParent(_ context.Context, parent Container)

func (*SingleContainer) UI

type Span

type Span ui.Span

type State

type State struct {
	// contains filtered or unexported fields
}

State represents a state of text in a piece table. Since the elements of a piece table are immutable once referenced, a State value is safe for concurrent access and will never change, even if the piece table has changed.

func (State) Add

func (s State) Add(_ context.Context, at int, parts [][]rune) State

Add returns a new State with the addition applied. Add does not change any backing arrays, but simply returns a new state with the references added.

Note: s has no concept of backing arrays, so the parts argument is expected to reference the final backing arrays. Add simply stores those references at the correct point.

func (State) Equals

func (s State) Equals(ctx context.Context, o State) bool

func (State) Len

func (s State) Len(context.Context) int

func (State) LineEnd

func (s State) LineEnd(ctx context.Context, pos int) int

func (State) LineStart

func (s State) LineStart(ctx context.Context, pos int) int

func (State) Pos

func (s State) Pos(ctx context.Context, line, col int) int

func (State) PosTuple

func (s State) PosTuple(ctx context.Context, pos int) (line, col int)

func (State) Remove

func (s State) Remove(_ context.Context, at, length int) State

Remove returns a new State with the removal applied. Remove does not change any backing arrays, but simply returns a new state with the references removed.

func (State) Text

func (s State) Text(_ context.Context, start, end int) []rune

Text returns s as a single rune slice, to use when displaying text. The returned slice does not contain any references to the backing arrays and is therefor safe to pass to third party plugins.

func (State) Version

func (s State) Version(context.Context) int

Version returns the version of s. Whenever a new State is created by applying changes to the text, its version will be incremented. That version can be checked using this method.

type UIBinder

type UIBinder interface {
	SettableBinder
	UI(context.Context) Element
}

type Window

type Window struct {
	// contains filtered or unexported fields
}

Window is vidar's internal representation of a window, wrapping up the UI element with some extra functionality.

func NewWindow

func NewWindow(_ context.Context, ui ui.Window) *Window

func (*Window) Bound

func (w *Window) Bound(context.Context) input.Actions

func (*Window) Close

func (w *Window) Close(ctx context.Context) error

func (*Window) Focus

func (w *Window) Focus(ctx context.Context, b Binder) error

func (*Window) Focused

func (w *Window) Focused(ctx context.Context) (Binder, error)

func (*Window) Get

func (e *Window) Get(ctx context.Context, a input.Action, key any) (any, bool)

func (*Window) Run

func (w *Window) Run(ctx context.Context, a input.Action) error

func (*Window) Set

func (e *Window) Set(ctx context.Context, a input.Action, key, value any) bool

func (*Window) SetActions

func (w *Window) SetActions(_ context.Context, acts *Actions)

func (*Window) SetChild

func (w *Window) SetChild(ctx context.Context, child Element) error

Directories

Path Synopsis
Package gxui contains wrappers to make the gxui library act like a (git.sr.ht/~nelsam/vidar-lib/ui).Creator.
Package gxui contains wrappers to make the gxui library act like a (git.sr.ht/~nelsam/vidar-lib/ui).Creator.

Jump to

Keyboard shortcuts

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