editor

package
v0.18.0 Latest Latest
Warning

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

Go to latest
Published: May 24, 2026 License: MIT Imports: 6 Imported by: 0

README

Editor

Editable multi-line text buffer with a 2D cursor, viewport scrolling, gutter, undo/redo, and per-line syntax tint.

editor preview

The primitive a terminal-native code editor is built around. Pair it with file-tree for the project sidebar, tabs for open buffers, status-bar for the path and line indicator, and find-bar for in-buffer search.

Install

glyph add editor

code-view is pulled in as a dependency because the editor reuses its tokenizer for non-cursor lines.

Hello, world

package main

import (
	"fmt"

	tea "github.com/charmbracelet/bubbletea"

	codeview "github.com/truffle-dev/glyph/components/code-view"
	"github.com/truffle-dev/glyph/components/editor"
	"github.com/truffle-dev/glyph/components/theme"
)

type model struct{ ed editor.Model }

func (m model) Init() tea.Cmd { return nil }
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	if k, ok := msg.(tea.KeyMsg); ok && k.String() == "esc" {
		return m, tea.Quit
	}
	updated, cmd := m.ed.Update(msg)
	m.ed = updated
	return m, cmd
}
func (m model) View() string { return m.ed.View() }

func main() {
	ed := editor.New(theme.Default).
		WithContent("package main\n\nfunc main() {}").
		WithLanguage(codeview.LangGo).
		WithWidth(72).
		WithHeight(16)
	if _, err := tea.NewProgram(model{ed: ed}).Run(); err != nil {
		fmt.Println(err)
	}
}

Bindings

←   →   ↑   ↓                cursor by one cell
Home / End                   line edges
Ctrl-Home / Ctrl-End         document edges
PgUp / PgDn                  one viewport-height
Enter                        split line at cursor
Backspace                    delete-back; join with prev line at col 0
Delete                       delete-forward; join with next line at EOL
Tab                          insert tabSize spaces (default 4)
Ctrl-Z                       undo
Ctrl-Y                       redo

API surface

Package: editor

Types

  • Model — Bubble Tea model
  • ChangeMsg{Value, Row, Col} — emitted via Cmd on every edit

Functions

  • New

Model methods

  • Init, Update, View
  • WithContent, WithLanguage, WithWidth, WithHeight, WithGutter, WithTabSize
  • Focus, Blur, Focused
  • Value, Cursor, LineCount, Dirty

Dependencies

  • glyph component theme (installed automatically)
  • glyph component code-view (for the tokenizer)
  • github.com/charmbracelet/bubbletea@v1.3.10
  • github.com/charmbracelet/lipgloss@v1.1.0

Notes

The buffer is [][]rune so every column index is a rune offset. The cursor is a 2D (row, col) pair and never sits past the rune length of its line. ensureCursorVisible runs after every key event and scrolls viewRow/viewCol to keep the cursor on screen — vertical and horizontal scroll fall out of the same mechanism.

Undo is inverse-op based: each edit pushes a single op describing how to reverse it (insert ↔ delete, split ↔ join), so memory stays linear in edit count and an undo is O(line) not O(buffer). A fresh edit after an undo clears the redo stack — the same shape every editor uses.

Syntax tinting reuses codeview.Tokenize(line, lang) per visible non- cursor line. The cursor line is intentionally rendered as plain text so the inverted cursor cell can be injected without parsing ANSI escapes. This is also what most lightweight editors do during insert mode and yields a clean focus cue without flicker.

See also

License

MIT, same as the rest of glyph.

Documentation

Overview

Package editor renders an editable multi-line text buffer with a 2D cursor, viewport scrolling, optional line-number gutter, undo/redo, and per-line syntax tint via codeview's tokenizer.

The model is a Bubble Tea component. The buffer is stored as a slice of rune-slices so every column index is a rune index, never a byte offset; multibyte glyphs and combining marks are handled correctly at the cost of treating each rune as one cell (no East-Asian wide- rune awareness in v0.1 — that lives in a later widening of runeWidth).

The editor only knows about *text*. Saves, syntax-aware indentation, language servers, and selection clipboards are intentionally out of scope: the consumer owns the file, the disk, and the OS clipboard. The model exposes Value() so the consumer can persist whenever it wants and emits no Save/Load messages on its own.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ChangeMsg

type ChangeMsg struct {
	Value string
	Row   int
	Col   int
}

ChangeMsg is emitted on every edit so the consumer can mark a tab "dirty" or schedule an autosave. The cursor position is included so the consumer can update breadcrumbs / status-bars in lock-step.

type Model

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

Model is the Bubble Tea model for an editable text buffer.

func New

func New(t theme.Theme) Model

New returns an editor with one empty line, focused, 80 cells wide, 20 rows tall, line numbers on, no language tint, 4-space tabs.

func (Model) Blur

func (m Model) Blur() Model

Blur disables key input.

func (Model) Cursor

func (m Model) Cursor() (int, int)

Cursor returns the 0-based (row, col) cursor position.

func (Model) Dirty

func (m Model) Dirty() bool

Dirty reports whether the undo stack has at least one entry — useful for tab "modified" indicators.

func (Model) Focus

func (m Model) Focus() Model

Focus enables key input.

func (Model) Focused

func (m Model) Focused() bool

Focused reports whether the editor is currently accepting keys.

func (Model) Init

func (m Model) Init() tea.Cmd

Init implements tea.Model.

func (Model) LineCount

func (m Model) LineCount() int

LineCount returns the number of lines in the buffer.

func (Model) Update

func (m Model) Update(msg tea.Msg) (Model, tea.Cmd)

Update implements tea.Model.

func (Model) Value

func (m Model) Value() string

Value returns the buffer as "\n"-joined source.

func (Model) View

func (m Model) View() string

View renders the editor as a bordered frame containing the gutter and the visible slice of the buffer with the cursor injected on its line.

func (Model) WithContent

func (m Model) WithContent(s string) Model

WithContent presets the buffer. The cursor lands at (0, 0).

func (Model) WithGutter

func (m Model) WithGutter(on bool) Model

WithGutter toggles the line-number gutter.

func (Model) WithHeight

func (m Model) WithHeight(h int) Model

WithHeight clamps to >= 3.

func (Model) WithLanguage

func (m Model) WithLanguage(lang codeview.Language) Model

WithLanguage selects the tokenizer dialect for non-cursor lines.

func (Model) WithTabSize

func (m Model) WithTabSize(n int) Model

WithTabSize sets the tab expansion width. Clamped to [1, 16].

func (Model) WithWidth

func (m Model) WithWidth(w int) Model

WithWidth clamps to >= 16.

Jump to

Keyboard shortcuts

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