vcom/docs/architecture.md

197 lines
4.8 KiB
Markdown
Raw Normal View History

2026-04-22 22:10:50 +03:00
# Architecture
## Why this shape
The project should not become a giant `main.go` that mixes rendering, key handling, filesystem I/O and business rules. The architecture is split so the UI remains reactive and file operations stay isolated.
## High-level modules
- `cmd/vcom`
Entry point, config loading, program startup.
- `internal/config`
Config schema, defaults, search paths and TOML parsing.
- `internal/fs`
Filesystem model, directory scanning, previews and file operations.
- `internal/theme`
Theme presets and style tokens.
- `internal/ui`
Bubble Tea model, key map, pane rendering, modal flow and layout.
## State model
The Bubble Tea root model owns:
- terminal dimensions
- full config
- active browser pane
- left and right pane state
- center preview state
- transient modal state
- busy/status state for async work
This keeps the Elm-style update loop simple:
1. key or resize event arrives
2. model decides whether to mutate local state or start async work
3. async work returns a typed message
4. view renders from plain state
## Pane model
Each side pane stores:
- current path
- scanned entries
- cursor index
- scroll offset
- cached directory sizes for entries calculated on demand
This is intentionally independent from rendering details, so the pane can be unit-tested later without Lip Gloss.
## Preview pipeline
The center pane is driven only by the current selection from the active side pane.
Preview strategies:
- directory preview
Shows child entries and summary data.
- text preview
Reads up to a configured byte limit and displays text safely.
- image preview
Detects dimensions and format through standard Go image decoders.
- binary fallback
Avoids dumping junk bytes into the terminal.
Metadata shown above the preview:
- kind
- full path
- size
- created time
- modified time
- permissions
Directory size is expensive, so it is not calculated eagerly. Pressing `Space` starts an async scan and updates both:
- side-pane size column
- preview metadata widget
## Configuration design
TOML is used because:
- it is readable in terminal workflows
- comments are first-class
- optional settings can stay commented out for manual enable/disable
The example config enables only MC-like columns by default:
- `name`
- `size`
- `modified`
Additional columns are left commented out so users can literally uncomment them:
- `created`
- `permissions`
- `extension`
Other useful config areas:
- startup paths for left and right panes
- theme preset
- hidden file visibility
- sort field and reverse mode
- center pane width ratio
- confirmation behavior
- preview byte limits
- text wrapping in preview
- compact path display
## Rendering strategy
The side panes are custom-rendered rather than built on top of the generic table bubble.
Reasoning:
- MC-like directory panes are not just tables
- we need tight control over selection styling, truncation and empty states
- the center pane uses a different rendering model than the side panes
Bubble usage:
- `bubbletea`
event loop and async commands
- `bubbles/key`
declarative key bindings
- `bubbles/textinput`
mkdir modal
- `bubbles/viewport`
preview scrolling surface
- `lipgloss`
all layout and styling
## Operations
The first operational slice is intentionally MC-core:
- copy selected entry to passive pane directory
- move selected entry to passive pane directory
- create directory in active pane
- delete selected entry
- refresh active pane
These operations are dispatched asynchronously to avoid freezing the TUI on large directories.
Overwrite handling is decided before the async operation begins:
- if the target does not exist, the operation runs directly
- if the target exists and overwrite confirmation is enabled, the UI opens a modal
- if overwrite confirmation is disabled, the operation replaces the target immediately
## Theme system
Themes are token-based rather than style-object based.
Each preset defines semantic colors:
- background
- panel
- panel inactive
- border
- border active
- text
- muted text
- accent
- selection
- warning
- danger
- footer key
This allows future user-defined themes without touching UI logic.
The current UI also supports runtime theme cycling, but config remains the source of truth for default startup appearance.
## Extension points
The architecture is designed to accept later additions without a rewrite:
- multi-select and batch operations
- file viewer/editor integration
- terminal image protocols
- tab history per pane
- bookmarks and quick-jump
- sort modes
- archive browsing
- search/filter overlay
- pluggable preview providers
## Constraints worth keeping
- never calculate directory sizes during normal navigation
- never read full large files into memory for preview
- keep filesystem code out of `View()`
- keep styling decisions out of `internal/fs`
- prefer typed Tea messages over stringly-typed status events