ui

package
v0.11.0 Latest Latest
Warning

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

Go to latest
Published: Aug 11, 2026 License: AGPL-3.0 Imports: 31 Imported by: 0

Documentation

Overview

Package ui implements gu on top of the ninebox shell. It depends only on internal/forge: no view may import a provider package.

The shell owns the frame stack, the list, the sidebar, the banner, the prompt bar, the help and the refresh timer. gu owns what a row means: merge requests, issues, pipelines, stacks, and the screens that read them.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New(f forge.Forge, profile, host string, readOnly bool, start StartAt, opts ...Option) *ninebox.Model

New builds gu and the shell around it. The caller has already resolved the profile and wrapped f in forge.ReadOnly when appropriate.

Types

type Context

type Context struct {
	Name string
	// Provider is what the profile is configured for: "gitlab", "github", or
	// both. It comes from the config file, so listing costs nothing.
	Provider string
	// Detail is the config directory backing the profile, which is what
	// actually distinguishes two accounts on the same host.
	Detail string
	Open   func(ctx context.Context) (forge.Forge, string, error)
}

Context is one account gu can operate as: a profile, what it is configured with, and how to connect to it.

Open is deferred, and reports the host it ended up on, because resolving that means asking the CLI — a subprocess and often a round-trip per account. Only the context you actually switch to pays for it, so startup stays the cost of one account rather than all of them.

type Model

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

Model is gu: the application the shell runs. It is a ninebox.App, and holds a pointer back to the shell so its screens can push, prompt and report.

func (*Model) Attach

func (m *Model) Attach(nb *ninebox.Model)

Attach takes the shell gu is drawn in.

func (*Model) Categories

func (m *Model) Categories() []ninebox.Category

Categories hands the shell gu's menu. Project-scoped entries are listed even with no project in context — they lead to a picker rather than being silently unavailable, which left the sidebar looking broken from the account view.

func (*Model) Command

func (m *Model) Command(line string) (tea.Cmd, bool)

Command answers the `:` lines that take an argument, which a name on its own cannot express: `:ctx work` switches account outright, where bare `:ctx` opens the picker above.

func (*Model) Commands

func (m *Model) Commands() []ninebox.Command

Commands are the words `:` accepts from any screen: gu's navigation vocabulary. The shell tries the open screen's own commands first, so `:merge` on a merge request merges it rather than landing here.

func (*Model) Describe

func (m *Model) Describe(payload any, raw bool) (string, bool)

Describe renders a row for the `d` key, and its untouched provider payload for `y`. Reporting false is what makes `d` on a menu entry do nothing rather than open an empty pane.

func (*Model) Facts

func (m *Model) Facts() []ninebox.Fact

Facts is the banner's left-hand block: the handful of things that decide what an action would do.

Where you are comes first and alone: it is the fact that changes as you move around, and the one worth finding without reading the other three.

func (*Model) Help

func (m *Model) Help() []ninebox.HelpSection

Help is what the shell's own key reference does not cover: the resources gu knows about, and the keys that change them.

func (*Model) Init

func (m *Model) Init() tea.Cmd

Init dials the account when gu was launched without one, and otherwise asks who we are, which the banner needs and no frame provides.

func (*Model) Key

func (m *Model) Key(key string) (tea.Cmd, bool)

Key answers the list keys the shell does not claim for itself. Moving, filtering, describing, opening in a browser and reloading are the shell's; what is left is what gu can do to a merge request or an issue.

func (*Model) ListActions

func (m *Model) ListActions() []ninebox.Action

ListActions is what gu adds to the list's legend and help. Actions that change something are offered only when they would work.

func (*Model) Message

func (m *Model) Message(msg tea.Msg) (tea.Cmd, bool)

Message answers gu's own asynchronous results. Anything it does not claim falls through to the shell, which knows about rows, writes and toasts.

func (*Model) Start

func (m *Model) Start() *frame

Start is the frame gu opens on: a project, a group, or the account landing — or, until the account has been dialled, the frame that says so.

func (*Model) WebURL

func (m *Model) WebURL(payload any) string

WebURL is what `o` opens for a row.

Every kind of row that a provider gives a page to is listed here, so the key works uniformly rather than only on the handful it started with.

type Option

type Option func(*Model)

Option customises gu at construction.

func WithAutoRefresh

func WithAutoRefresh(d time.Duration) Option

WithAutoRefresh re-fetches the open screen every d. Zero switches it off, which is what a disabled setting and a nonsensical interval both resolve to.

func WithCache

func WithCache(c *httpcache.Transport) Option

WithCache gives gu the caching transport, so a screen can draw itself from disk before it fetches anything and a write can drop what it invalidated. A nil transport switches both off.

func WithConfigDir added in v0.11.0

func WithConfigDir(dir string) Option

WithConfigDir points gu at its own config directory, which is where the list of recently opened projects is kept.

func WithConnect

func WithConnect(connect func(ctx context.Context) (forge.Forge, string, error)) Option

WithConnect hands gu the account to dial, instead of one already dialled. The caller has applied read-only wrapping inside connect, exactly as WithContexts requires of its openers.

This is what keeps authentication off the startup path: New returns immediately, the program runs, and the frame that is already on screen is replaced when the account answers.

func WithContexts

func WithContexts(find func() []Context) Option

WithContexts supplies the accounts `:ctx` can switch between. The caller has already applied read-only wrapping inside each Open.

It takes a function rather than a list because finding the accounts means scanning the disk for CLI configuration directories, which costs about half a second. Nothing pays for it until `:ctx` is actually used.

func WithIcons

func WithIcons(name string) Option

WithIcons selects the glyph set by name: "nerd" (the default), "geometric" for terminals without a patched font, or "ascii" for fonts that manage neither.

func WithStackDir

func WithStackDir(dir string) Option

WithStackDir points the stack views at a directory of stack YAML files.

type StartAt

type StartAt struct {
	Kind  string // "account" | "group" | "repo"
	Group string
	Ref   forge.Ref
}

StartAt tells gu which screen to open first.

Jump to

Keyboard shortcuts

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