Documentation
¶
Overview ¶
Package garland provides a rope-based data structure for efficient text/binary editing with multiple storage tiers, versioning, decorations, and lazy loading.
Index ¶
- Constants
- Variables
- func ValidDecorationKey(key string) bool
- type AbsoluteAddress
- type AddressMode
- type AppendPolicy
- type BackupInfo
- type BackupOptions
- type BackupState
- type ByteBufferRegion
- func (r *ByteBufferRegion) ByteCount() int64
- func (r *ByteBufferRegion) Content() []byte
- func (r *ByteBufferRegion) DeleteBytes(offset, length int64) error
- func (r *ByteBufferRegion) InsertBytes(offset int64, data []byte) error
- func (r *ByteBufferRegion) LineCount() int64
- func (r *ByteBufferRegion) ReadBytes(offset, length int64) ([]byte, error)
- func (r *ByteBufferRegion) RuneCount() int64
- type CacheTier
- type ChangeResult
- type ChillLevel
- type ColdStorageInterface
- type CopyResult
- type CountResult
- type Cursor
- func (c *Cursor) BackDeleteBytes(length int64, includeLineDecorations bool) ([]RelativeDecoration, ChangeResult, error)
- func (c *Cursor) BackDeleteRunes(length int64, includeLineDecorations bool) ([]RelativeDecoration, ChangeResult, error)
- func (c *Cursor) BeginOptimizedRegion(startByte, endByte int64) error
- func (c *Cursor) BytePos() int64
- func (c *Cursor) CopyBytes(srcStart, srcEnd, dstStart, dstEnd int64, ...) (CopyResult, error)
- func (c *Cursor) CountRegex(pattern string, caseInsensitive bool) (int, error)
- func (c *Cursor) CountString(needle string, opts SearchOptions) (int, error)
- func (c *Cursor) DeleteBytes(length int64, includeLineDecorations bool) ([]RelativeDecoration, ChangeResult, error)
- func (c *Cursor) DeleteRunes(length int64, includeLineDecorations bool) ([]RelativeDecoration, ChangeResult, error)
- func (c *Cursor) FindNext(needle string, opts SearchOptions) (*SearchResult, error)
- func (c *Cursor) FindNextRegex(pattern string, opts RegexOptions) (*SearchResult, error)
- func (c *Cursor) FindRegex(pattern string, opts RegexOptions) (*SearchResult, error)
- func (c *Cursor) FindRegexAll(pattern string, opts RegexOptions) ([]SearchResult, error)
- func (c *Cursor) FindString(needle string, opts SearchOptions) (*SearchResult, error)
- func (c *Cursor) FindStringAll(needle string, opts SearchOptions) ([]SearchResult, error)
- func (c *Cursor) HasOptimizedRegion() bool
- func (c *Cursor) InsertBytes(data []byte, decorations []RelativeDecoration, insertBefore bool) (ChangeResult, error)
- func (c *Cursor) InsertString(data string, decorations []RelativeDecoration, insertBefore bool) (ChangeResult, error)
- func (c *Cursor) IsReady() bool
- func (c *Cursor) LinePos() (line, runeInLine int64)
- func (c *Cursor) MatchRegex(pattern string, caseInsensitive bool) (bool, *SearchResult, error)
- func (c *Cursor) Mode() CursorMode
- func (c *Cursor) MoveBytes(srcStart, srcEnd, dstStart, dstEnd int64, insertBefore bool) (MoveResult, error)
- func (c *Cursor) OptimizedRegionBounds() (start, end int64, ok bool)
- func (c *Cursor) OptimizedRegionGraceWindow() (start, end int64, ok bool)
- func (c *Cursor) OptimizedRegionSerial() int64
- func (c *Cursor) OverwriteBytes(length int64, newData []byte) ([]RelativeDecoration, ChangeResult, error)
- func (c *Cursor) OverwriteBytesWithDecorations(length int64, newData []byte, decorationsToAdd []RelativeDecoration, ...) ([]RelativeDecoration, ChangeResult, error)
- func (c *Cursor) Position() CursorPosition
- func (c *Cursor) ReadBytes(length int64) ([]byte, error)
- func (c *Cursor) ReadLine() (string, error)
- func (c *Cursor) ReadString(length int64) (string, error)
- func (c *Cursor) ReplaceRegex(pattern, replacement string, opts RegexOptions) (bool, ChangeResult, error)
- func (c *Cursor) ReplaceRegexAll(pattern, replacement string, opts RegexOptions) (int, ChangeResult, error)
- func (c *Cursor) ReplaceRegexCount(pattern, replacement string, count int, opts RegexOptions) (int, ChangeResult, error)
- func (c *Cursor) ReplaceString(needle, replacement string, opts SearchOptions) (bool, ChangeResult, error)
- func (c *Cursor) ReplaceStringAll(needle, replacement string, opts SearchOptions) (int, ChangeResult, error)
- func (c *Cursor) ReplaceStringCount(needle, replacement string, count int, opts SearchOptions) (int, ChangeResult, error)
- func (c *Cursor) RunePos() int64
- func (c *Cursor) SeekByWord(n int) (int, error)
- func (c *Cursor) SeekByWordStyle(n int, style WordStyle) (int, error)
- func (c *Cursor) SeekByte(pos int64) error
- func (c *Cursor) SeekByteWithTimeout(pos int64, timeout time.Duration) error
- func (c *Cursor) SeekLine(line, runeInLine int64) error
- func (c *Cursor) SeekLineEnd() error
- func (c *Cursor) SeekLineStart() error
- func (c *Cursor) SeekLineWithTimeout(line, runeInLine int64, timeout time.Duration) error
- func (c *Cursor) SeekRelativeBytes(delta int64) error
- func (c *Cursor) SeekRelativeRunes(delta int64) error
- func (c *Cursor) SeekRune(pos int64) error
- func (c *Cursor) SeekRuneWithTimeout(pos int64, timeout time.Duration) error
- func (c *Cursor) SetMode(mode CursorMode)
- func (c *Cursor) SetTracksHistory(track bool)
- func (c *Cursor) TracksHistory() bool
- func (c *Cursor) TruncateToEOF() (ChangeResult, error)
- func (c *Cursor) WaitReady() error
- type CursorMode
- type CursorPosition
- type Decoration
- type DecorationCacheEntry
- type DecorationEntry
- type DeviceInfo
- type DivergenceDirection
- type FileHandle
- type FileMetadata
- type FileOptions
- type FileSystemInterface
- type ForkDivergence
- type ForkID
- type ForkInfo
- type ForkRevision
- type Garland
- func (g *Garland) AcknowledgeSourceChange(reload bool) error
- func (g *Garland) AdoptWarmSource(fs FileSystemInterface, name string, level VerifyLevel) error
- func (g *Garland) BackupInfo() BackupInfo
- func (g *Garland) Bake()
- func (g *Garland) BreakSourceLock() error
- func (g *Garland) ByteCount() CountResult
- func (g *Garland) ByteToLineRune(bytePos int64) (line, runeInLine int64, err error)
- func (g *Garland) ByteToRune(bytePos int64) (int64, error)
- func (g *Garland) CheckMemoryPressure() MaintenanceStats
- func (g *Garland) CheckSourceMetadata() (SourceChangeInfo, error)
- func (g *Garland) Checkpoint() error
- func (g *Garland) Chill(level ChillLevel) error
- func (g *Garland) Close() error
- func (g *Garland) CurrentFork() ForkID
- func (g *Garland) CurrentRevision() RevisionID
- func (g *Garland) Decorate(entries []DecorationEntry) (ChangeResult, error)
- func (g *Garland) DeleteFork(fork ForkID) error
- func (g *Garland) DisableSourceWatch()
- func (g *Garland) DumpDecorations(fs FileSystemInterface, path string) error
- func (g *Garland) EnableSourceWatch(interval time.Duration)
- func (g *Garland) FindForksBetween(revisionFirst, revisionLast RevisionID) ([]ForkDivergence, error)
- func (g *Garland) ForceRebalance() MaintenanceStats
- func (g *Garland) ForkSeek(fork ForkID) error
- func (g *Garland) GetDecorationPosition(key string) (AbsoluteAddress, error)
- func (g *Garland) GetDecorationsInByteRange(start, end int64) ([]DecorationEntry, error)
- func (g *Garland) GetDecorationsOnLine(line int64) ([]DecorationEntry, error)
- func (g *Garland) GetForkInfo(fork ForkID) (*ForkInfo, error)
- func (g *Garland) GetRevisionInfo(revision RevisionID) (*RevisionInfo, error)
- func (g *Garland) GetRevisionRange(start, end RevisionID) ([]RevisionInfo, error)
- func (g *Garland) GetSnapshotStats() SnapshotStats
- func (g *Garland) GetTreeInfo() *TreeNodeInfo
- func (g *Garland) HoldsSourceLock() bool
- func (g *Garland) InTransaction() bool
- func (g *Garland) IncrementalRebalance(affectedPath []NodeID) MaintenanceStats
- func (g *Garland) IntegrityEvents() []IntegrityEvent
- func (g *Garland) IsByteReady(pos int64) bool
- func (g *Garland) IsComplete() bool
- func (g *Garland) IsLineReady(line int64) bool
- func (g *Garland) IsReady() bool
- func (g *Garland) IsRuneReady(pos int64) bool
- func (g *Garland) LastSave() (SavePoint, bool)
- func (g *Garland) LineCount() CountResult
- func (g *Garland) LineRuneToByte(line, runeInLine int64) (int64, error)
- func (g *Garland) ListForks() []ForkInfo
- func (g *Garland) LoadAppendedContent() (int64, error)
- func (g *Garland) LoadDecorations(fs FileSystemInterface, path string) error
- func (g *Garland) LoadDecorationsFromString(content string) error
- func (g *Garland) MemoryPressure() MemoryPressureInfo
- func (g *Garland) MemoryUsage() MemoryStats
- func (g *Garland) NeedsRebalancing() bool
- func (g *Garland) NewCursor() *Cursor
- func (g *Garland) NewEphemeralCursor() *Cursor
- func (g *Garland) NodeManipulations() int64
- func (g *Garland) Prune(keepFromRevision RevisionID) error
- func (g *Garland) RebaseOnFile(fs FileSystemInterface, name string) (RebaseReport, error)
- func (g *Garland) RebaseOnSource() (RebaseReport, error)
- func (g *Garland) RefreshSourceInfo() error
- func (g *Garland) RemoveCursor(c *Cursor) error
- func (g *Garland) ReportSourceMetadata(meta FileMetadata) SourceConsistencyState
- func (g *Garland) RevertToLastSave() error
- func (g *Garland) RuneCount() CountResult
- func (g *Garland) RuneToByte(runePos int64) (int64, error)
- func (g *Garland) Save() (SaveReport, error)
- func (g *Garland) SaveAs(fs FileSystemInterface, name string) (SaveReport, error)
- func (g *Garland) SaveAsWith(fs FileSystemInterface, name string, opts SaveAsOptions) (SaveReport, error)
- func (g *Garland) SaveHistory() []SavePoint
- func (g *Garland) SaveWith(opts SaveOptions) (SaveReport, error)
- func (g *Garland) SetAppendPolicy(policy AppendPolicy)
- func (g *Garland) SetBackupLocation(fs FileSystemInterface, dir string, opts BackupOptions) error
- func (g *Garland) SetSourceChangeHandler(handler SourceChangeHandler)
- func (g *Garland) SetUndoCoalescing(enabled bool, autoBakeTime time.Duration)
- func (g *Garland) SetVerifyOnRead(enabled bool)
- func (g *Garland) SourceConsistency() (SourceConsistencyReport, error)
- func (g *Garland) SourceConsistencyCached() SourceConsistencyReport
- func (g *Garland) SourceDeviceInfo() (DeviceInfo, error)
- func (g *Garland) SourceLockOwner() (string, bool)
- func (g *Garland) SourcePath() string
- func (g *Garland) SourceStatus() SourceChangeStatus
- func (g *Garland) Thaw() error
- func (g *Garland) ThawRange(startByte, endByte int64) error
- func (g *Garland) ThawRevision(startRev, endRev RevisionID) error
- func (g *Garland) TransactionCommit() (ChangeResult, error)
- func (g *Garland) TransactionDepth() int
- func (g *Garland) TransactionRollback() error
- func (g *Garland) TransactionStart(name string) error
- func (g *Garland) TryRecoverSource(level VerifyLevel) (SavePoint, error)
- func (g *Garland) UndoCoalescing() (enabled bool, autoBakeTime time.Duration)
- func (g *Garland) UndoSeek(revision RevisionID) error
- func (g *Garland) VerifyBoundaryForAppend() error
- type IntegrityEvent
- type IntegrityKind
- type LeafSearchResult
- type Library
- func (lib *Library) CheckMemoryPressureError() error
- func (lib *Library) ChillToTarget() MaintenanceStats
- func (lib *Library) Close() error
- func (lib *Library) DefaultFS() FileSystemInterface
- func (lib *Library) DeviceInfoFor(fs FileSystemInterface, name string) (DeviceInfo, error)
- func (lib *Library) IncrementalChill(budget int) MaintenanceStats
- func (lib *Library) MemoryPressure() bool
- func (lib *Library) Open(options FileOptions) (*Garland, error)
- func (lib *Library) StopMaintenance()
- func (lib *Library) TotalMemoryUsage() int64
- type LibraryOptions
- type LineSearchResult
- type LineStart
- type Loader
- type LoadingStyle
- type MaintenanceStats
- type MemoryPressureInfo
- type MemoryStats
- type MoveResult
- type Node
- type NodeID
- type NodeSnapshot
- func (s *NodeSnapshot) ByteCount() int64
- func (s *NodeSnapshot) Data() []byte
- func (s *NodeSnapshot) Decorations() []Decoration
- func (s *NodeSnapshot) IsLeaf() bool
- func (s *NodeSnapshot) LeftID() NodeID
- func (s *NodeSnapshot) LineCount() int64
- func (s *NodeSnapshot) RightID() NodeID
- func (s *NodeSnapshot) RuneCount() int64
- type OpenMode
- type OptimizedRegionHandle
- type ReadAheadConfig
- type ReadyThreshold
- type RebaseRegion
- type RebaseReport
- type RegexOptions
- type RelativeDecoration
- type RevisionID
- type RevisionInfo
- type SaveAsOptions
- type SaveOptions
- type SavePoint
- type SaveReport
- type ScarWarning
- type SearchOptions
- type SearchResult
- type SnapshotStats
- type SourceChangeHandler
- type SourceChangeInfo
- type SourceChangeStatus
- type SourceChangeType
- type SourceConsistencyReport
- type SourceConsistencyState
- type StorageState
- type TransactionState
- type TreeNodeInfo
- type VerifyLevel
- type WarmTrustLevel
- type WordStyle
Constants ¶
const ( // DefaultMaxLeafSize is the maximum bytes per leaf node. // Files larger than this are split into multiple leaves. DefaultMaxLeafSize = 128 * 1024 // 128KB // DefaultTargetLeafSize is the ideal leaf size (MaxLeafSize / 2). DefaultTargetLeafSize = 64 * 1024 // 64KB // DefaultMinLeafSize is the minimum leaf size before merging (MaxLeafSize / 4). DefaultMinLeafSize = 32 * 1024 // 32KB // DefaultInitialUsageWindow is the default byte range to keep in memory. DefaultInitialUsageWindow = 1024 * 1024 // 1MB )
Default leaf size constants for tree building.
Variables ¶
var ( // ErrNotReady indicates that a position is not yet available during lazy loading. ErrNotReady = errors.New("position not yet available") // ErrInvalidPosition indicates that a position is out of bounds. ErrInvalidPosition = errors.New("position out of bounds") // ErrTimeout indicates that a blocking wait operation timed out. ErrTimeout = errors.New("operation timed out") // ErrInvalidUTF8 indicates that an operation would split a UTF-8 sequence. ErrInvalidUTF8 = errors.New("invalid UTF-8 sequence") // ErrOverlappingRanges indicates that source and destination ranges overlap // in an operation that doesn't allow overlap (e.g., Move). ErrOverlappingRanges = errors.New("source and destination ranges overlap") )
Position errors
var ( // ErrDecorationNotFound indicates that a decoration key does not exist. ErrDecorationNotFound = errors.New("decoration not found") // ErrInvalidDecorationKey indicates a decoration key with illegal // characters. RULING: keys are identifiers, not storage - ASCII // letters, digits, '_', '.', '#', and '-' only, non-empty. This // keeps every serialization of keys framing-safe by construction. ErrInvalidDecorationKey = errors.New("invalid decoration key: letters, digits, '_', '.', '#', '-' only") )
Decoration errors
var ( // ErrForkNotFound indicates that a fork ID does not exist. ErrForkNotFound = errors.New("fork not found") // ErrRevisionNotFound indicates that a revision does not exist in the current fork. ErrRevisionNotFound = errors.New("revision not found") )
Versioning errors
var ( // ErrColdStorageFailure indicates that a cold storage operation failed. ErrColdStorageFailure = errors.New("cold storage operation failed") // ErrWarmStorageMismatch indicates that the original file has changed (checksum mismatch). ErrWarmStorageMismatch = errors.New("warm storage checksum mismatch") // ErrReadOnly indicates that a region is read-only due to storage failure. ErrReadOnly = errors.New("region is read-only due to storage failure") // ErrNotFromOriginalFile indicates warm storage is not available for this node. ErrNotFromOriginalFile = errors.New("node is not from original file") // ErrNoRecoverySource indicates that no alternate known save // location could be verified and adopted (TryRecoverSource). ErrNoRecoverySource = errors.New("no alternate save location could be adopted") // ErrMemoryPressure indicates that memory limits are exceeded and cannot be reduced. // This occurs when hard memory limit is set but no cold storage is configured, // or when cold storage is full/unavailable. The application should handle this // by closing unused garlands, reducing operations, or configuring cold storage. ErrMemoryPressure = errors.New("memory limit exceeded and cannot be reduced") )
Storage errors
var ( // ErrNotSupported indicates that an optional file system operation is not supported. ErrNotSupported = errors.New("operation not supported") // ErrFileNotOpen indicates that the file handle is not open. ErrFileNotOpen = errors.New("file not open") )
File system errors
var ( // ErrRegionOverlap indicates that optimized regions cannot overlap. ErrRegionOverlap = errors.New("optimized regions cannot overlap") // ErrRegionNotFound indicates that the optimized region does not exist. ErrRegionNotFound = errors.New("optimized region not found") )
Region errors
var ( // ErrTransactionPending indicates that an operation is not allowed during a transaction. ErrTransactionPending = errors.New("operation not allowed during transaction") // ErrTransactionPoisoned indicates that a transaction was poisoned by an inner rollback. ErrTransactionPoisoned = errors.New("transaction was poisoned by inner rollback") // ErrNoTransaction indicates that there is no active transaction. ErrNoTransaction = errors.New("no active transaction") )
Transaction errors
var ( // ErrNotALeaf indicates that an operation expected a leaf node but got an internal node. ErrNotALeaf = errors.New("expected leaf node") // ErrInternal indicates an internal consistency error (should not happen). ErrInternal = errors.New("internal error") )
Tree structure errors
var ( // ErrNoDataSource indicates that no data source was provided in FileOptions. ErrNoDataSource = errors.New("no data source provided") // ErrMultipleDataSources indicates that multiple data sources were provided. ErrMultipleDataSources = errors.New("multiple data sources provided") // ErrNoColdStorage indicates that cold storage is required but not configured. ErrNoColdStorage = errors.New("cold storage not configured") // ErrDataNotLoaded indicates that data is in cold/warm storage and needs to be thawed. ErrDataNotLoaded = errors.New("data not loaded - call Thaw() first") )
Configuration errors
var ( // ErrCursorNotFound indicates that the cursor does not belong to this garland. ErrCursorNotFound = errors.New("cursor not found") )
Cursor errors
Functions ¶
func ValidDecorationKey ¶ added in v0.1.4
ValidDecorationKey reports whether key is a legal decoration identifier: non-empty, ASCII letters and digits plus '_', '.', '#' (hashtag-style marks), and '-'. RULING: keys are identifiers, not storage in their own right - restricting them keeps every serialization of keys (e.g. cold-storage .dec blocks) framing-safe by construction, with no escaping anywhere.
Types ¶
type AbsoluteAddress ¶
type AbsoluteAddress struct {
Mode AddressMode
// Byte is used when Mode is ByteMode.
Byte int64
// Rune is used when Mode is RuneMode.
Rune int64
// Line is used when Mode is LineRuneMode (0-indexed line number).
Line int64
// LineRune is used when Mode is LineRuneMode (0-indexed rune within line).
LineRune int64
}
AbsoluteAddress specifies a position using one of three addressing modes.
func ByteAddress ¶
func ByteAddress(pos int64) AbsoluteAddress
ByteAddress creates an AbsoluteAddress in byte mode.
func LineAddress ¶
func LineAddress(line, runeInLine int64) AbsoluteAddress
LineAddress creates an AbsoluteAddress in line:rune mode.
func RuneAddress ¶
func RuneAddress(pos int64) AbsoluteAddress
RuneAddress creates an AbsoluteAddress in rune mode.
type AddressMode ¶
type AddressMode int
AddressMode specifies how a position is interpreted.
const ( // ByteMode specifies an absolute byte position (0-indexed). ByteMode AddressMode = iota // RuneMode specifies an absolute rune/Unicode code point position (0-indexed). RuneMode // LineRuneMode specifies a line number and rune position within that line (both 0-indexed). // The newline character is considered the last character of its line. LineRuneMode )
type AppendPolicy ¶
type AppendPolicy int
AppendPolicy controls how the library handles detected appends.
const ( // AppendPolicyAsk notifies the application and waits for a decision. AppendPolicyAsk AppendPolicy = iota // AppendPolicyIgnore ignores this append but asks again next time. AppendPolicyIgnore // AppendPolicyNever ignores all future appends permanently. AppendPolicyNever // AppendPolicyOnce loads this append but asks again next time. AppendPolicyOnce // AppendPolicyContinuous keeps loading appends automatically (tail mode). AppendPolicyContinuous )
type BackupInfo ¶ added in v0.1.7
type BackupInfo struct {
State BackupState
Path string // destination backup file (once armed and resolved)
Subject string // the source file the backup captures
Bytes int64 // bytes copied so far / in the finished backup
Err string // failure detail when State == BackupFailed
}
BackupInfo reports the backup machinery's current standing.
type BackupOptions ¶ added in v0.1.7
type BackupOptions struct {
// Name overrides the backup filename within the backup directory.
// Default: "<source basename>~" (the emacs backup convention).
// NOTE: never use the ".#<name>" form - that is the lock-file
// namespace.
Name string
}
BackupOptions configures SetBackupLocation.
type BackupState ¶ added in v0.1.7
type BackupState int
BackupState describes where the backup machinery stands.
const ( // BackupDisabled: no backup location configured. BackupDisabled BackupState = iota // BackupArmed: configured; no modification seen yet, nothing // copied (viewing a file stays in this state forever). BackupArmed // BackupPending: a modification armed the copy; it has not // finished yet. BackupPending // BackupReady: the backup is in place at the destination. BackupReady // BackupCommitted: a save overwrote the protected file; the backup // is kept (survives Close). BackupCommitted // BackupFailed: the copy failed (see BackupInfo.Err). Saves are // never blocked by a failed backup - the app decides what to do. BackupFailed )
func (BackupState) String ¶ added in v0.1.7
func (s BackupState) String() string
String returns a human-readable description of the state.
type ByteBufferRegion ¶
type ByteBufferRegion struct {
// contains filtered or unexported fields
}
ByteBufferRegion is a simple OptimizedRegion implementation using a byte slice. It's suitable for small to medium editing sessions.
func NewByteBufferRegion ¶
func NewByteBufferRegion(initialContent []byte) *ByteBufferRegion
NewByteBufferRegion creates a new ByteBufferRegion with initial content.
func (*ByteBufferRegion) ByteCount ¶
func (r *ByteBufferRegion) ByteCount() int64
ByteCount returns the number of bytes in the region.
func (*ByteBufferRegion) Content ¶
func (r *ByteBufferRegion) Content() []byte
Content returns the full content of the region.
func (*ByteBufferRegion) DeleteBytes ¶
func (r *ByteBufferRegion) DeleteBytes(offset, length int64) error
DeleteBytes deletes length bytes starting at offset.
func (*ByteBufferRegion) InsertBytes ¶
func (r *ByteBufferRegion) InsertBytes(offset int64, data []byte) error
InsertBytes inserts data at the given offset.
func (*ByteBufferRegion) LineCount ¶
func (r *ByteBufferRegion) LineCount() int64
LineCount returns the number of newlines in the region.
func (*ByteBufferRegion) ReadBytes ¶
func (r *ByteBufferRegion) ReadBytes(offset, length int64) ([]byte, error)
ReadBytes reads length bytes starting at offset.
func (*ByteBufferRegion) RuneCount ¶
func (r *ByteBufferRegion) RuneCount() int64
RuneCount returns the number of runes in the region.
type ChangeResult ¶
type ChangeResult struct {
Fork ForkID
Revision RevisionID
}
ChangeResult contains version information after a mutation.
type ChillLevel ¶
type ChillLevel int
ChillLevel specifies how aggressively to move data to cold storage.
const ( // ChillInactiveForks moves data not used by the currently active fork // to cold storage. This is the gentlest level. ChillInactiveForks ChillLevel = iota // ChillOldHistory also moves data from older revisions in the undo // buffer that are more than a few steps back and not utilized by // any branching point. ChillOldHistory // ChillUnusedData moves all data not used at the current undo position. // This keeps only what's needed to display/edit the current state. ChillUnusedData // ChillEverything moves all data to cold storage. Use when switching // to another document or dropping to a shell. Data will be restored // from cold storage on access. ChillEverything )
type ColdStorageInterface ¶
type ColdStorageInterface interface {
// Set stores data for a block within a folder.
// Folder names are unique per loaded file.
Set(folder, block string, data []byte) error
// Get retrieves data for a block within a folder.
Get(folder, block string) ([]byte, error)
// Delete removes a block from a folder.
Delete(folder, block string) error
// DeleteFolder removes an empty folder.
// Returns an error if the folder is not empty.
DeleteFolder(folder string) error
}
ColdStorageInterface allows custom cold storage implementations.
type CopyResult ¶
type CopyResult struct {
ChangeResult
DisplacedDecorations []RelativeDecoration // Decorations that were in the destination range (original positions)
}
CopyResult contains the result of a Copy operation.
type CountResult ¶
CountResult contains a count and whether it is complete.
type Cursor ¶
type Cursor struct {
// contains filtered or unexported fields
}
Cursor represents a position within a Garland with its own ready state. Cursors automatically update when content changes before their position.
func (*Cursor) BackDeleteBytes ¶
func (c *Cursor) BackDeleteBytes(length int64, includeLineDecorations bool) ([]RelativeDecoration, ChangeResult, error)
BackDeleteBytes deletes `length` bytes BEFORE the cursor position. Cursor moves to the start of the deleted range (its new position). Returns decorations from the deleted range.
func (*Cursor) BackDeleteRunes ¶
func (c *Cursor) BackDeleteRunes(length int64, includeLineDecorations bool) ([]RelativeDecoration, ChangeResult, error)
BackDeleteRunes deletes `length` runes BEFORE the cursor position. Cursor moves to the start of the deleted range (its new position). Returns decorations from the deleted range.
func (*Cursor) BeginOptimizedRegion ¶
BeginOptimizedRegion explicitly starts an optimized region at the specified bounds.
QUARANTINED: optimized regions are unfinished scaffolding. The edit paths never route through an active region, so a region created here holds FIXED bounds that go stale on the next checkpoint/transaction - a live corruption hazard. Until the feature is either fully wired in or removed, this returns ErrNotSupported. (RULING 2026-07-12: keep the scaffolding, block the entry point.)
func (*Cursor) BytePos ¶
BytePos returns the cursor's absolute byte position. Concurrency: cursor fields are only written under the garland write lock (seeks, edits adjusting passive cursors), so accessors synchronize through it.
func (*Cursor) CopyBytes ¶
func (c *Cursor) CopyBytes(srcStart, srcEnd, dstStart, dstEnd int64, decorationsToAdd []RelativeDecoration, insertBefore bool) (CopyResult, error)
CopyBytes copies a byte range to a new location. All four addresses are interpreted in the document AS IT STANDS AT THE MOMENT OF THIS CALL (see MoveBytes; the operation compensates for its own intermediate shifts, never the caller). Source and destination ranges may overlap for Copy (source is snapshotted first). - srcStart, srcEnd: source byte range [srcStart, srcEnd) - dstStart, dstEnd: destination byte range to replace [dstStart, dstEnd) - decorationsToAdd: decorations to add to the copied content (like Insert) - insertBefore: if true, displaced decorations consolidate to end of new content Returns CopyResult with the displaced decorations from the destination range.
func (*Cursor) CountRegex ¶
CountRegex counts regex matches in the document.
func (*Cursor) CountString ¶
func (c *Cursor) CountString(needle string, opts SearchOptions) (int, error)
CountString counts occurrences of needle in the document.
func (*Cursor) DeleteBytes ¶
func (c *Cursor) DeleteBytes(length int64, includeLineDecorations bool) ([]RelativeDecoration, ChangeResult, error)
DeleteBytes deletes `length` bytes starting at cursor position. Returns decorations from the deleted range. If includeLineDecorations is true, also returns (but does not move) decorations from partially affected lines.
func (*Cursor) DeleteRunes ¶
func (c *Cursor) DeleteRunes(length int64, includeLineDecorations bool) ([]RelativeDecoration, ChangeResult, error)
DeleteRunes deletes `length` runes starting at cursor position. Returns decorations from the deleted range. If includeLineDecorations is true, also returns (but does not move) decorations from partially affected lines.
func (*Cursor) FindNext ¶
func (c *Cursor) FindNext(needle string, opts SearchOptions) (*SearchResult, error)
FindNext finds the next occurrence and moves cursor to it. Returns the match or nil if not found.
func (*Cursor) FindNextRegex ¶
func (c *Cursor) FindNextRegex(pattern string, opts RegexOptions) (*SearchResult, error)
FindNextRegex finds the next regex match and moves cursor to it.
func (*Cursor) FindRegex ¶
func (c *Cursor) FindRegex(pattern string, opts RegexOptions) (*SearchResult, error)
FindRegex searches for a regex pattern starting from the cursor position. Returns the first match found, or nil if no match. The cursor is NOT moved by this operation.
func (*Cursor) FindRegexAll ¶
func (c *Cursor) FindRegexAll(pattern string, opts RegexOptions) ([]SearchResult, error)
FindRegexAll finds all regex matches in the document.
func (*Cursor) FindString ¶
func (c *Cursor) FindString(needle string, opts SearchOptions) (*SearchResult, error)
FindString searches for a string starting from the cursor position. Returns the first match found, or nil if no match. The cursor is NOT moved by this operation.
func (*Cursor) FindStringAll ¶
func (c *Cursor) FindStringAll(needle string, opts SearchOptions) ([]SearchResult, error)
FindStringAll finds all occurrences of a string in the document. Returns all matches in document order (or reverse order if Backward).
func (*Cursor) HasOptimizedRegion ¶
HasOptimizedRegion returns true if the cursor has an active optimized region.
func (*Cursor) InsertBytes ¶
func (c *Cursor) InsertBytes(data []byte, decorations []RelativeDecoration, insertBefore bool) (ChangeResult, error)
InsertBytes inserts raw bytes at the cursor position. If insertBefore is true, insertion occurs before any existing cursors/decorations at this position; otherwise after. After insertion, cursor advances to the end of the inserted content.
func (*Cursor) InsertString ¶
func (c *Cursor) InsertString(data string, decorations []RelativeDecoration, insertBefore bool) (ChangeResult, error)
InsertString inserts a string at the cursor position. Relative decoration positions are measured in runes. If insertBefore is true, insertion occurs before any existing cursors/decorations at this position; otherwise after. After insertion, cursor advances to the end of the inserted content.
func (*Cursor) IsReady ¶
IsReady returns true if the read-ahead threshold has been met relative to this cursor's position.
func (*Cursor) LinePos ¶
LinePos returns the cursor's line number and rune position within that line. Both values are 0-indexed.
func (*Cursor) MatchRegex ¶
MatchRegex checks if the regex matches at the current cursor position. Returns true if the pattern matches starting exactly at cursor position.
func (*Cursor) MoveBytes ¶
func (c *Cursor) MoveBytes(srcStart, srcEnd, dstStart, dstEnd int64, insertBefore bool) (MoveResult, error)
MoveBytes moves a byte range to a new location. All four addresses are interpreted in the document AS IT STANDS AT THE MOMENT OF THIS CALL: the operation is internally composite (extract, delete destination, insert), and the implementation adjusts for its own intermediate shifts - the caller never compensates. (Not "as opened": prior edits are already reflected.) Source and destination ranges cannot overlap for Move. Decorations in the source range move with the content. Decorations in the destination range are consolidated and returned. - srcStart, srcEnd: source byte range [srcStart, srcEnd) - dstStart, dstEnd: destination byte range to replace [dstStart, dstEnd) - insertBefore: if true, displaced decorations consolidate to end of new content Returns MoveResult with the displaced decorations from the destination range.
func (*Cursor) OptimizedRegionBounds ¶
OptimizedRegionBounds returns the content bounds of the active region. Returns (0, 0, false) if no region is active.
func (*Cursor) OptimizedRegionGraceWindow ¶
OptimizedRegionGraceWindow returns the grace window bounds of the active region. Returns (0, 0, false) if no region is active.
func (*Cursor) OptimizedRegionSerial ¶
OptimizedRegionSerial returns the serial number of the cursor's active region, or -1 if no region is active. Useful for debugging region lifecycle.
func (*Cursor) OverwriteBytes ¶
func (c *Cursor) OverwriteBytes(length int64, newData []byte) ([]RelativeDecoration, ChangeResult, error)
OverwriteBytes replaces `length` bytes at cursor position with new data. This is more efficient than separate delete + insert for binary editing. The operation properly accounts for changes in line counts (newlines) and rune counts (UTF-8 sequences). Returns decorations that were in the overwritten range. Cursor position is not changed after the operation.
func (*Cursor) OverwriteBytesWithDecorations ¶
func (c *Cursor) OverwriteBytesWithDecorations(length int64, newData []byte, decorationsToAdd []RelativeDecoration, insertBefore bool) ([]RelativeDecoration, ChangeResult, error)
OverwriteBytesWithDecorations replaces bytes with new data, adding decorations. - decorationsToAdd: decorations to add to the new content (relative to new content start) - insertBefore: if true, displaced decorations consolidate to end; if false, to start Returns the original decorations from the overwritten range with their original relative positions.
func (*Cursor) Position ¶
func (c *Cursor) Position() CursorPosition
Position returns the cursor's position in all coordinate systems.
func (*Cursor) ReadBytes ¶
ReadBytes reads `length` bytes starting at cursor position. After reading, cursor advances past the read data.
func (*Cursor) ReadLine ¶
ReadLine reads the entire line the cursor is on. Note: Does NOT advance cursor (line-oriented reading is typically peek-like).
func (*Cursor) ReadString ¶
ReadString reads `length` runes starting at cursor position as a string. After reading, cursor advances past the read data.
func (*Cursor) ReplaceRegex ¶
func (c *Cursor) ReplaceRegex(pattern, replacement string, opts RegexOptions) (bool, ChangeResult, error)
ReplaceRegex replaces the first regex match with replacement. Replacement can include $1, $2, etc. for capture groups.
func (*Cursor) ReplaceRegexAll ¶
func (c *Cursor) ReplaceRegexAll(pattern, replacement string, opts RegexOptions) (int, ChangeResult, error)
ReplaceRegexAll replaces all regex matches with replacement.
func (*Cursor) ReplaceRegexCount ¶
func (c *Cursor) ReplaceRegexCount(pattern, replacement string, count int, opts RegexOptions) (int, ChangeResult, error)
ReplaceRegexCount replaces up to count regex matches with replacement.
func (*Cursor) ReplaceString ¶
func (c *Cursor) ReplaceString(needle, replacement string, opts SearchOptions) (bool, ChangeResult, error)
ReplaceString replaces the first occurrence of needle with replacement. Search starts from cursor position. Returns the change result and whether a replacement was made.
func (*Cursor) ReplaceStringAll ¶
func (c *Cursor) ReplaceStringAll(needle, replacement string, opts SearchOptions) (int, ChangeResult, error)
ReplaceStringAll replaces all occurrences of needle with replacement. Returns the number of replacements made.
func (*Cursor) ReplaceStringCount ¶
func (c *Cursor) ReplaceStringCount(needle, replacement string, count int, opts SearchOptions) (int, ChangeResult, error)
ReplaceStringCount replaces up to count occurrences of needle with replacement. If count is -1, replaces all occurrences. Returns the number of replacements made.
func (*Cursor) SeekByWord ¶
SeekByWord moves the cursor by n words using WordStyleSimple. Positive n moves forward, negative n moves backward. Returns the number of words actually moved (may be less than requested at the buffer boundaries). Use SeekByWordStyle to choose different word semantics.
func (*Cursor) SeekByWordStyle ¶ added in v0.1.4
SeekByWordStyle moves the cursor by n words under the given WordStyle. Positive n moves forward, negative n moves backward. Returns the number of words actually moved.
func (*Cursor) SeekByte ¶
SeekByte moves the cursor to an absolute byte position. Blocks indefinitely until the position is available during lazy loading. Use SeekByteWithTimeout for timeout control, or check IsByteReady first for non-blocking.
func (*Cursor) SeekByteWithTimeout ¶
SeekByteWithTimeout moves the cursor to an absolute byte position with timeout control. If timeout is 0, returns ErrNotReady immediately if position not available. If timeout is negative, blocks indefinitely. If timeout is positive, waits up to that duration before returning ErrTimeout.
func (*Cursor) SeekLine ¶
SeekLine moves the cursor to a line and rune-within-line position. Line and rune are both 0-indexed. The newline is the last character of its line. Blocks indefinitely until the position is available during lazy loading. Use SeekLineWithTimeout for timeout control, or check IsLineReady first for non-blocking.
func (*Cursor) SeekLineEnd ¶
SeekLineEnd moves the cursor to the end of the current line. The cursor is positioned after the last character before the newline (or at EOF).
func (*Cursor) SeekLineStart ¶
SeekLineStart moves the cursor to the beginning of the current line.
func (*Cursor) SeekLineWithTimeout ¶
SeekLineWithTimeout moves the cursor to a line and rune-within-line position with timeout control. If timeout is 0, returns ErrNotReady immediately if position not available. If timeout is negative, blocks indefinitely. If timeout is positive, waits up to that duration before returning ErrTimeout.
func (*Cursor) SeekRelativeBytes ¶
SeekRelativeBytes moves the cursor relative to its current byte position. Positive delta moves forward, negative moves backward. Clamps to valid range [0, byteCount].
func (*Cursor) SeekRelativeRunes ¶
SeekRelativeRunes moves the cursor relative to its current rune position. Positive delta moves forward, negative moves backward. Clamps to valid range [0, runeCount].
func (*Cursor) SeekRune ¶
SeekRune moves the cursor to an absolute rune position. Blocks indefinitely until the position is available during lazy loading. Use SeekRuneWithTimeout for timeout control, or check IsRuneReady first for non-blocking.
func (*Cursor) SeekRuneWithTimeout ¶
SeekRuneWithTimeout moves the cursor to an absolute rune position with timeout control. If timeout is 0, returns ErrNotReady immediately if position not available. If timeout is negative, blocks indefinitely. If timeout is positive, waits up to that duration before returning ErrTimeout.
func (*Cursor) SetMode ¶
func (c *Cursor) SetMode(mode CursorMode)
SetMode sets the cursor's mode. Changing mode does not affect any currently active optimized region.
func (*Cursor) SetTracksHistory ¶ added in v0.1.5
SetTracksHistory turns per-revision position tracking on or off for this cursor. Turning it off drops any history already accumulated (freeing it) and stops future recording - the cursor still adjusts to edits but is no longer teleported to historical positions on a seek. Turning it back on resumes recording from the current version.
func (*Cursor) TracksHistory ¶ added in v0.1.5
TracksHistory reports whether this cursor records per-revision positions and is restored on undo/redo/fork navigation.
func (*Cursor) TruncateToEOF ¶
func (c *Cursor) TruncateToEOF() (ChangeResult, error)
TruncateToEOF deletes everything from cursor position to end of file.
type CursorMode ¶
type CursorMode int
CursorMode determines how a cursor interacts with optimized regions.
const ( // CursorModeHuman automatically creates optimized regions on edit operations. // This is the default mode for interactive editing. CursorModeHuman CursorMode = iota // CursorModeProcess does not auto-create regions; uses transactions instead. // Use this mode for programmatic/scripted operations. CursorModeProcess )
type CursorPosition ¶
CursorPosition stores a cursor's position in all coordinate systems.
type Decoration ¶
Decoration represents a decoration stored within a node.
type DecorationCacheEntry ¶
type DecorationCacheEntry struct {
// Last known location (hint for search)
LastKnownFork ForkID
LastKnownRev RevisionID
LastKnownNode NodeID // 0 means "confirmed not present at this fork/revision"
LastKnownOffset int64
// Cache management
Tier CacheTier // Hot = actively used, Warm = seen during traversal
LastAccess time.Time
}
DecorationCacheEntry caches the last known location of a decoration. The presence of an entry indicates the key has been used at some point. The cached location is a hint - it may be stale if fork/revision differs.
type DecorationEntry ¶
type DecorationEntry struct {
Key string
Address *AbsoluteAddress // nil to delete the decoration
}
DecorationEntry represents a decoration with its absolute position.
type DeviceInfo ¶ added in v0.1.7
type DeviceInfo struct {
// DeviceID identifies the device/volume holding the path (on local
// unix filesystems "dev<dev>", on Windows the volume name). Two
// equal non-empty IDs mean the same device. Empty means unknown.
DeviceID string
// FreeBytes is the space available to new writes, -1 if unknown.
FreeBytes int64
// TotalBytes is the device's total capacity, -1 if unknown.
TotalBytes int64
}
DeviceInfo describes the storage device/volume behind a path, for free-space warnings ("this save may not fit") and for recognizing when two paths live on different media (e.g. saving to removable media vs. the working drive).
type DivergenceDirection ¶
type DivergenceDirection int
DivergenceDirection indicates the relationship of a fork to the current fork.
const ( // BranchedFrom means the current fork split off from the specified fork. BranchedFrom DivergenceDirection = iota // BranchedInto means the specified fork split off from the current fork. BranchedInto )
type FileMetadata ¶ added in v0.1.7
type FileMetadata struct {
// Exists is false when the path currently names no file. The other
// fields are meaningless in that case.
Exists bool
// Size is the file's length in bytes.
Size int64
// ModTime is the file's last-modification time.
ModTime time.Time
// Identity names the underlying storage object, independent of the
// path (on local unix filesystems "dev<dev>:ino<inode>"). Two
// different non-empty identities for the same path mean the path
// was re-bound to a different object - the classic write-temp-and-
// rename "file replaced" case. Empty means unknown; identity
// comparison is then skipped and detection falls back to
// size + mtime.
Identity string
}
FileMetadata describes a file as observed at one moment: the information Garland tracks to detect external modification of a source file between opening it and saving over it. A virtualized filesystem supplies these through FileSystemInterface.Stat, or the application volunteers them via Garland.ReportSourceMetadata when it learns fresher facts than Garland could observe itself.
type FileOptions ¶
type FileOptions struct {
// LoadingStyle determines storage tier availability
LoadingStyle LoadingStyle
// Data source (exactly one must be provided)
FilePath string // load from file path using default FS
FileSystem FileSystemInterface // custom file system (use with FilePath)
DataBytes []byte // literal byte content
DataString string // literal string content
DataChannel chan []byte // streaming input
// Initial decorations (optional, at most one)
Decorations []DecorationEntry // literal list
DecorationChan chan DecorationEntry
DecorationPath string // load from dump file
DecorationString string // parse from dump format
// Tree structure options
// MaxLeafSize is the maximum bytes per leaf node (default 128KB).
// Larger files are split into a balanced tree of leaves.
// Target leaf size is MaxLeafSize/2, minimum is MaxLeafSize/4.
MaxLeafSize int64
// InitialUsageStart and InitialUsageEnd define a byte range to keep in memory.
// Nodes outside this range are immediately chilled to cold storage after loading.
// This avoids loading a huge file fully into RAM just to chill it immediately.
// Set InitialUsageEnd to -1 (default) to use a reasonable default window.
// Set both to 0 to chill everything immediately (pure cold storage load).
InitialUsageStart int64
InitialUsageEnd int64 // -1 means auto (defaults to 1MB or file size, whichever is smaller)
// Ready thresholds - ALL specified (non-zero) must be met
// Measured from beginning of file at initial load
ReadyLines int64
ReadyBytes int64
ReadyRunes int64
ReadyAll bool
// Lazy read-ahead - ALL specified (non-zero) must be met
// Measured from highest seek position after any seek
ReadAheadLines int64
ReadAheadBytes int64
ReadAheadRunes int64
ReadAheadAll bool
// UseEmacsLocks (opt-in, file sources only) maintains an
// emacs-compatible ".#<name>" lock file next to the source for as
// long as the buffer holds unsaved modifications, so emacs (and
// tools honoring its protocol) warn users off the file - and
// Garland reports foreign locks it finds (SourceLockOwner,
// SourceConsistencyReport.LockedBy). See emacs_lock.go.
UseEmacsLocks bool
// LockOwner overrides the identity written inside the emacs lock
// file (and used to recognize our own lock vs. a foreign one).
// Empty means the default "user@host.pid", derived from the
// environment. Follow that form for emacs interoperability; the
// value is used verbatim after trimming surrounding whitespace,
// and must be a single line. Only meaningful with UseEmacsLocks.
LockOwner string
}
FileOptions configures how a Garland is opened.
type FileSystemInterface ¶
type FileSystemInterface interface {
// Required methods
Open(name string, mode OpenMode) (FileHandle, error)
SeekByte(handle FileHandle, pos int64) error
ReadBytes(handle FileHandle, length int) ([]byte, error)
IsEOF(handle FileHandle) bool
Close(handle FileHandle) error
// Optional methods (may return ErrNotSupported)
HasChanged(handle FileHandle) (bool, error)
FileSize(handle FileHandle) (int64, error)
BlockChecksum(handle FileHandle, start, length int64) ([]byte, error)
WriteBytes(handle FileHandle, data []byte) error
Truncate(handle FileHandle, size int64) error
// Convenience methods for file operations
WriteFile(name string, data []byte) error
ReadFile(name string) ([]byte, error)
// Directory operations
MkdirAll(path string) error
Remove(name string) error
Rmdir(path string) error // Only removes empty directories
// Rename atomically replaces newpath with oldpath. Cold storage
// relies on this so a block being re-written (chill) can never be
// torn-read by a concurrent Get (unlocked save phase, thaw).
Rename(oldpath, newpath string) error
// Stat reports a path's current metadata for external-modification
// detection. A missing file is NOT an error: report it as
// FileMetadata{Exists: false} with a nil error; errors are reserved
// for real failures. Implementations without metadata may return
// ErrNotSupported - Garland then tracks only what the application
// volunteers through ReportSourceMetadata.
Stat(name string) (FileMetadata, error)
// DeviceInfo reports the storage device behind a path (identity and
// free space), for save-time free-space warnings. May return
// ErrNotSupported.
DeviceInfo(name string) (DeviceInfo, error)
}
FileSystemInterface abstracts file operations for custom protocols. The library provides a default implementation for local files.
func NewLocalFileSystem ¶ added in v0.1.6
func NewLocalFileSystem() FileSystemInterface
NewLocalFileSystem returns a FileSystemInterface backed by the real operating-system filesystem - the same implementation Garland uses by default. Hosts that want to pass an explicit filesystem to SaveAs, or wrap/partially delegate to local disk when building a custom FileSystemInterface, can obtain one here instead of reimplementing the whole interface. (SaveAs also accepts a nil filesystem, which resolves to this automatically.)
type ForkDivergence ¶
type ForkDivergence struct {
Fork ForkID
DivergenceRev RevisionID // revision at which split occurred
Direction DivergenceDirection // relationship to current fork
}
ForkDivergence describes where a fork split occurred.
type ForkInfo ¶
type ForkInfo struct {
ID ForkID
ParentFork ForkID
ParentRevision RevisionID // revision at which this fork split from parent
HighestRevision RevisionID
PrunedUpTo RevisionID // revisions < this have been pruned from this fork's view
Deleted bool // true if fork is soft-deleted (data may still exist for child forks)
}
ForkInfo contains metadata about a fork.
type ForkRevision ¶
type ForkRevision struct {
Fork ForkID
Revision RevisionID
}
ForkRevision is a composite key for looking up versioned state.
type Garland ¶
type Garland struct {
// contains filtered or unexported fields
}
Garland is the main data structure representing an editable file.
func (*Garland) AcknowledgeSourceChange ¶
AcknowledgeSourceChange acknowledges a detected source change. Call this after the user has been notified and made a decision.
func (*Garland) AdoptWarmSource ¶ added in v0.1.7
func (g *Garland) AdoptWarmSource(fs FileSystemInterface, name string, level VerifyLevel) error
AdoptWarmSource switches the buffer's source (warm-storage backing) to another file that is believed to hold exactly the current content - swiftly and seamlessly, with the cheapest sufficient consistency check chosen by level. On success every current leaf is re-homed onto the new file, undo history that referenced the old source is migrated off it (cold storage when available, memory otherwise; unreachable history is marked lost, never silently corrupted), and change detection re-baselines against the new file.
A nil fs resolves like SaveAs: the current source filesystem, else the library default. Returns ErrWarmStorageMismatch when the candidate cannot be proven consistent at the requested level.
func (*Garland) BackupInfo ¶ added in v0.1.7
func (g *Garland) BackupInfo() BackupInfo
BackupInfo reports the backup machinery's current standing. Cheap; safe to call from a status-bar paint path.
func (*Garland) Bake ¶ added in v0.1.8
func (g *Garland) Bake()
Bake forces a hard edge: the current coalescing run (if any) is finalized, and the next edit starts a fresh history entry no matter how adjacent it is. Safe to call at any time, including when coalescing is disabled or no run is active.
func (*Garland) BreakSourceLock ¶ added in v0.1.7
BreakSourceLock force-removes a foreign emacs-style lock file on the source - the "steal the lock" choice after warning the user - and, when the buffer holds unsaved modifications, immediately acquires the lock for this garland. Returns ErrNotSupported when emacs locks were not enabled for this garland.
func (*Garland) ByteCount ¶
func (g *Garland) ByteCount() CountResult
ByteCount returns total bytes (or known bytes if still loading). For revisions created during streaming, includes the streaming remainder.
func (*Garland) ByteToLineRune ¶
ByteToLineRune converts a byte position to a line:rune position.
func (*Garland) ByteToRune ¶
ByteToRune converts a byte position to a rune position.
func (*Garland) CheckMemoryPressure ¶
func (g *Garland) CheckMemoryPressure() MaintenanceStats
CheckMemoryPressure checks if memory limits are exceeded and performs appropriate maintenance. Called after mutations. Sets memoryPressure flag if hard limit exceeded and can't be reduced.
func (*Garland) CheckSourceMetadata ¶
func (g *Garland) CheckSourceMetadata() (SourceChangeInfo, error)
CheckSourceMetadata performs a cheap metadata check on the source file. This only stats the file, it doesn't read any content.
func (*Garland) Checkpoint ¶
Checkpoint commits all active optimized regions across all cursors. This creates a single revision containing all pending region changes. Call this to establish an undo point after a burst of edits.
func (*Garland) Chill ¶
func (g *Garland) Chill(level ChillLevel) error
Chill moves data to cold storage based on the specified aggressiveness level. This frees memory by storing data externally, to be reloaded on demand.
For MemoryOnly files, this is a no-op by design.
Levels:
- ChillInactiveForks: Only chill data not used by the current fork
- ChillOldHistory: Also chill old undo history beyond recent revisions
- ChillUnusedData: Chill everything not used at current revision
- ChillEverything: Chill all data (for switching documents or shells)
func (*Garland) CurrentFork ¶
CurrentFork returns the current fork ID.
func (*Garland) CurrentRevision ¶
func (g *Garland) CurrentRevision() RevisionID
CurrentRevision returns the current revision number within the current fork.
func (*Garland) Decorate ¶
func (g *Garland) Decorate(entries []DecorationEntry) (ChangeResult, error)
Decorate adds, updates, or removes decorations at absolute positions. All changes are applied as a single revision. Pass nil Address in a DecorationEntry to delete that decoration.
func (*Garland) DeleteFork ¶
DeleteFork soft-deletes a fork, preventing further navigation to it. The fork's data remains until no other forks depend on it. Cannot delete the current fork or the last remaining non-deleted fork.
func (*Garland) DisableSourceWatch ¶
func (g *Garland) DisableSourceWatch()
DisableSourceWatch stops periodic monitoring of the source file.
func (*Garland) DumpDecorations ¶
func (g *Garland) DumpDecorations(fs FileSystemInterface, path string) error
DumpDecorations writes all decorations to a file in INI-like format. If fs is nil, uses the Garland's source filesystem.
func (*Garland) EnableSourceWatch ¶
EnableSourceWatch starts periodic monitoring of the source file.
func (*Garland) FindForksBetween ¶
func (g *Garland) FindForksBetween(revisionFirst, revisionLast RevisionID) ([]ForkDivergence, error)
FindForksBetween returns all fork divergence points between two revisions from the perspective of the current fork.
func (*Garland) ForceRebalance ¶
func (g *Garland) ForceRebalance() MaintenanceStats
ForceRebalance performs a full tree rebalance (not incremental). Use sparingly as this can be expensive for large trees.
func (*Garland) ForkSeek ¶
ForkSeek switches to a different fork. Retains current revision if it exists in both forks, otherwise retreats to the last common revision.
func (*Garland) GetDecorationPosition ¶
func (g *Garland) GetDecorationPosition(key string) (AbsoluteAddress, error)
GetDecorationPosition returns the current position of a decoration by key. Uses registry-based O(1) existence check and cached location hints for fast lookup.
func (*Garland) GetDecorationsInByteRange ¶
func (g *Garland) GetDecorationsInByteRange(start, end int64) ([]DecorationEntry, error)
GetDecorationsInByteRange returns all decorations within [start, end).
func (*Garland) GetDecorationsOnLine ¶
func (g *Garland) GetDecorationsOnLine(line int64) ([]DecorationEntry, error)
GetDecorationsOnLine returns all decorations on the specified line.
func (*Garland) GetForkInfo ¶
GetForkInfo returns information about a specific fork.
func (*Garland) GetRevisionInfo ¶
func (g *Garland) GetRevisionInfo(revision RevisionID) (*RevisionInfo, error)
GetRevisionInfo returns information about a specific revision.
func (*Garland) GetRevisionRange ¶
func (g *Garland) GetRevisionRange(start, end RevisionID) ([]RevisionInfo, error)
GetRevisionRange returns info for revisions in [start, end] inclusive.
func (*Garland) GetSnapshotStats ¶
func (g *Garland) GetSnapshotStats() SnapshotStats
GetSnapshotStats returns statistics about node snapshots. Useful for testing and diagnostics to verify garbage collection.
func (*Garland) GetTreeInfo ¶
func (g *Garland) GetTreeInfo() *TreeNodeInfo
GetTreeInfo returns a snapshot of the current tree structure for visualization.
func (*Garland) HoldsSourceLock ¶ added in v0.1.7
HoldsSourceLock reports whether this garland currently holds the emacs-style lock on its source file.
func (*Garland) InTransaction ¶
InTransaction returns true if any transaction is active.
func (*Garland) IncrementalRebalance ¶
func (g *Garland) IncrementalRebalance(affectedPath []NodeID) MaintenanceStats
IncrementalRebalance performs budgeted tree rebalancing along a path. Called after mutations with the path of affected nodes.
func (*Garland) IntegrityEvents ¶ added in v0.1.4
func (g *Garland) IntegrityEvents() []IntegrityEvent
IntegrityEvents returns a copy of the integrity events accumulated since the last successful save (which drains them into its SaveReport).
func (*Garland) IsByteReady ¶
IsByteReady returns true if the given byte position is available for reading. This is a non-blocking check that can be used to guard against blocking waits. A negative position returns false. A position beyond EOF returns true only when loading is complete (at which point seeking there would return ErrInvalidPosition).
func (*Garland) IsComplete ¶
IsComplete returns true if EOF has been reached during loading.
func (*Garland) IsLineReady ¶
IsLineReady returns true if the given line number is available for reading. This is a non-blocking check that can be used to guard against blocking waits.
func (*Garland) IsRuneReady ¶
IsRuneReady returns true if the given rune position is available for reading. This is a non-blocking check that can be used to guard against blocking waits.
func (*Garland) LineCount ¶
func (g *Garland) LineCount() CountResult
LineCount returns total newlines (or known newlines if still loading).
func (*Garland) LineRuneToByte ¶
LineRuneToByte converts a line:rune position to a byte position.
func (*Garland) LoadAppendedContent ¶
LoadAppendedContent loads newly appended content from the source file. Only valid after VerifyBoundaryForAppend succeeds.
func (*Garland) LoadDecorations ¶
func (g *Garland) LoadDecorations(fs FileSystemInterface, path string) error
LoadDecorations loads decorations from a file using the INI format. Unknown sections are ignored for future compatibility. Comments are lines starting with ';' or '# ' (hash followed by space). End-of-line comments start with whitespace followed by ';' or '#'.
func (*Garland) LoadDecorationsFromString ¶
LoadDecorationsFromString loads decorations from an INI-formatted string. Unknown sections are ignored for future compatibility. Comments are lines starting with ';' or '# ' (hash followed by space). End-of-line comments start with whitespace followed by ';' or '#'.
func (*Garland) MemoryPressure ¶ added in v0.1.4
func (g *Garland) MemoryPressure() MemoryPressureInfo
MemoryPressure reports the buffer's memory standing. See MemoryPressureInfo for the intended app-side use.
func (*Garland) MemoryUsage ¶
func (g *Garland) MemoryUsage() MemoryStats
MemoryUsage returns current memory statistics for this Garland.
func (*Garland) NeedsRebalancing ¶
NeedsRebalancing checks if the tree is significantly unbalanced.
func (*Garland) NewCursor ¶
NewCursor creates a new cursor at position 0. Its position is tracked through undo/redo/fork navigation (see Cursor.SetTracksHistory).
func (*Garland) NewEphemeralCursor ¶ added in v0.1.5
NewEphemeralCursor creates a cursor whose position is NOT recorded per revision or restored on seeks - for paint carets, maintenance scans, and transient work that only needs a live, edit-adjusted position. Equivalent to NewCursor followed by SetTracksHistory(false), but without ever allocating the initial history entry.
func (*Garland) NodeManipulations ¶ added in v0.1.1
NodeManipulations returns the count of node operations since the last rebalance. This is a cheap counter incremented during tree mutations.
func (*Garland) Prune ¶
func (g *Garland) Prune(keepFromRevision RevisionID) error
Prune removes revision history before keepFromRevision in the current fork. Revisions >= keepFromRevision are kept. This sets the fork's PrunedUpTo watermark and cleans up: - RevisionInfo entries for pruned revisions - Cursor position history for pruned revisions - Node snapshots that are no longer needed by any fork
Shared revisions (inherited from parent forks) are only truly deleted when all forks that share them have pruned past that point.
func (*Garland) RebaseOnFile ¶ added in v0.1.4
func (g *Garland) RebaseOnFile(fs FileSystemInterface, name string) (RebaseReport, error)
RebaseOnFile reconciles the buffer against the named file, which then becomes the buffer's source (path, handle, and warm backing switch to it). A nil fs uses the library default.
func (*Garland) RebaseOnSource ¶ added in v0.1.4
func (g *Garland) RebaseOnSource() (RebaseReport, error)
RebaseOnSource reconciles the buffer against its own source file. See the file header for semantics.
func (*Garland) RefreshSourceInfo ¶
RefreshSourceInfo updates stored metadata after a save.
func (*Garland) RemoveCursor ¶
RemoveCursor removes a cursor from the Garland.
func (*Garland) ReportSourceMetadata ¶ added in v0.1.7
func (g *Garland) ReportSourceMetadata(meta FileMetadata) SourceConsistencyState
ReportSourceMetadata volunteers fresh metadata for the source file - the push-style counterpart to SourceConsistency's pull. Use it when the app learns facts Garland cannot observe itself (its own file watcher, a sync client, a virtualized filesystem event). The observation is recorded exactly as a stat result would be, and the resulting consistency state is returned. When no baseline exists yet (a metadata-less filesystem hook), the first volunteered observation becomes the baseline.
func (*Garland) RevertToLastSave ¶ added in v0.1.7
RevertToLastSave rewinds the buffer to the state captured by the most recent save - "revert to last saved version" as a pure history seek. Nothing is destroyed: the abandoned edits remain reachable as redo / fork history until the app prunes them. Returns ErrRevisionNotFound when no save was recorded (or the revision was pruned away).
func (*Garland) RuneCount ¶
func (g *Garland) RuneCount() CountResult
RuneCount returns total runes (or known runes if still loading).
func (*Garland) RuneToByte ¶
RuneToByte converts a rune position to a byte position.
func (*Garland) Save ¶
func (g *Garland) Save() (SaveReport, error)
Save overwrites the original file IN PLACE with the current content. The file is rewritten without a temporary copy (peak disk usage never exceeds max(old, new) size) and shrinks only as the final step; warm storage survives the save, re-homed to the new layout. Undo history that depends on overwritten warm bytes is migrated to cold storage first. See save.go for the full design. The returned SaveReport lists any blocks whose data was lost and had to be written as visible scars; the app decides how to surface them. Returns ErrNoDataSource if there is no original file path.
func (*Garland) SaveAs ¶
func (g *Garland) SaveAs(fs FileSystemInterface, name string) (SaveReport, error)
SaveAs writes the current content to a new location. Warm storage remains pointing to the original file (if any). Saving onto the original file itself routes through the in-place engine so the warm backing store is never destroyed. The returned SaveReport lists any lost blocks written as scars. Equivalent to SaveAsWith(fs, name, SaveAsOptions{}) - the destination does NOT become the buffer's source.
func (*Garland) SaveAsWith ¶ added in v0.1.7
func (g *Garland) SaveAsWith(fs FileSystemInterface, name string, opts SaveAsOptions) (SaveReport, error)
SaveAsWith writes the current content to a new location with control over whether the destination becomes the buffer's new source (warm- storage location). See SaveAsOptions. The returned SaveReport lists any lost blocks written as scars.
func (*Garland) SaveHistory ¶ added in v0.1.7
SaveHistory returns the recorded save points, oldest first (bounded to the most recent few).
func (*Garland) SaveWith ¶ added in v0.1.4
func (g *Garland) SaveWith(opts SaveOptions) (SaveReport, error)
SaveWith overwrites the original file in place with the current content. See the file header for the full design. The report lists any lost blocks that were scarred; the app should warn the user.
func (*Garland) SetAppendPolicy ¶
func (g *Garland) SetAppendPolicy(policy AppendPolicy)
SetAppendPolicy sets the policy for handling detected appends.
func (*Garland) SetBackupLocation ¶ added in v0.1.7
func (g *Garland) SetBackupLocation(fs FileSystemInterface, dir string, opts BackupOptions) error
SetBackupLocation configures (or, with an empty dir, disables) pre-session backups for this garland. The directory may live on any filesystem (nil fs = library default / local disk). Configuring replaces any previous configuration; an uncommitted previous backup is removed. If the buffer already holds unsaved modifications, the capture arms immediately (the source file still holds the pre-session content - nothing has overwritten it yet). Returns ErrNoDataSource when the buffer has no source file (there is nothing on disk to protect).
func (*Garland) SetSourceChangeHandler ¶
func (g *Garland) SetSourceChangeHandler(handler SourceChangeHandler)
SetSourceChangeHandler sets a callback for source file changes.
func (*Garland) SetUndoCoalescing ¶ added in v0.1.8
SetUndoCoalescing enables or disables undo coalescing and sets the auto-bake window. While enabled, runs of adjacent inserts (typing), adjacent deletes (backspacing / forward-deleting at one caret), and adjacent overwrites (replace-mode typing) each collapse into a single revision - the three kinds run separately and never merge with one another. autoBakeTime > 0 bakes the run automatically when the next edit arrives more than that long after the previous one; 0 disables time-based baking. Changing the configuration is itself a hard edge. Disabled by default - every mutation is its own revision unless this is turned on.
func (*Garland) SetVerifyOnRead ¶
SetVerifyOnRead sets whether warm storage reads should verify checksums.
func (*Garland) SourceConsistency ¶ added in v0.1.7
func (g *Garland) SourceConsistency() (SourceConsistencyReport, error)
SourceConsistency performs a fresh metadata check through the filesystem hook and reports the source file's consistency state. With a metadata-less hook it reports from the last volunteered observation instead (never an error - the report just says what is actually known). When emacs locks are enabled the lock file is also re-probed, so a foreign editor grabbing the file shows up here.
func (*Garland) SourceConsistencyCached ¶ added in v0.1.7
func (g *Garland) SourceConsistencyCached() SourceConsistencyReport
SourceConsistencyCached reports the consistency state from what Garland already knows, with NO filesystem access - safe to call from a paint path. Pair it with volunteered metadata (ReportSourceMetadata) or periodic SourceConsistency / EnableSourceWatch calls.
func (*Garland) SourceDeviceInfo ¶ added in v0.1.7
func (g *Garland) SourceDeviceInfo() (DeviceInfo, error)
SourceDeviceInfo reports the storage device behind this buffer's source file. Returns ErrNoDataSource when there is no source path.
func (*Garland) SourceLockOwner ¶ added in v0.1.7
SourceLockOwner reports the owner string of a foreign emacs-style lock on the source file ("user@host.pid"), as last observed. Returns ("", false) when no foreign lock is known - including when locks are disabled. SourceConsistency re-probes the lock file; this call does not touch the filesystem.
func (*Garland) SourcePath ¶
SourcePath returns the path to the source file, if any.
func (*Garland) SourceStatus ¶
func (g *Garland) SourceStatus() SourceChangeStatus
SourceStatus returns the current source change status.
func (*Garland) Thaw ¶
Thaw restores data from cold storage to memory for the current fork. This is the inverse of Chill - it loads data back from cold storage.
func (*Garland) ThawRange ¶
ThawRange restores cold data for a specific byte range at the current revision. This is RAM-safe for large files - it only thaws the nodes needed to read the specified byte range instead of the entire file.
func (*Garland) ThawRevision ¶
func (g *Garland) ThawRevision(startRev, endRev RevisionID) error
ThawRevision restores cold data for a specific revision range in the current fork. WARNING: This thaws ALL data for the revision(s), which could be very large. For large files, prefer ThawRange() to thaw only the bytes you need.
func (*Garland) TransactionCommit ¶
func (g *Garland) TransactionCommit() (ChangeResult, error)
TransactionCommit commits the current transaction.
func (*Garland) TransactionDepth ¶
TransactionDepth returns the current nesting depth (0 = no active transaction).
func (*Garland) TransactionRollback ¶
TransactionRollback discards all changes in the current transaction.
func (*Garland) TransactionStart ¶
TransactionStart begins a new transaction with an optional descriptive name.
func (*Garland) TryRecoverSource ¶ added in v0.1.7
func (g *Garland) TryRecoverSource(level VerifyLevel) (SavePoint, error)
TryRecoverSource walks the save history newest-first looking for an alternate known location whose file can be adopted as the source - automatic recovery for when the current source becomes corrupt or unreachable. Each candidate is checked at the given level (see AdoptWarmSource); the first that verifies is adopted and its save point returned. Returns ErrNoRecoverySource when no alternate location works.
func (*Garland) UndoCoalescing ¶ added in v0.1.8
UndoCoalescing reports the current coalescing configuration.
func (*Garland) UndoSeek ¶
func (g *Garland) UndoSeek(revision RevisionID) error
UndoSeek navigates to a specific revision within the current fork. Cannot seek forward past the highest revision in this fork. Seeking backwards then making a change creates a new fork.
func (*Garland) VerifyBoundaryForAppend ¶
VerifyBoundaryForAppend verifies just the boundary block to confirm an append. Returns nil if the boundary is intact (safe to treat as append).
type IntegrityEvent ¶ added in v0.1.4
type IntegrityEvent struct {
Kind IntegrityKind
BufferOffset int64 // block's byte offset in the buffer at discovery (-1 if unknown)
FileOffset int64 // where its backing bytes lived in the source file (-1 if none)
Length int64 // byte count of the block
Detail string // human-readable specifics (shift distance, duplicate location, cause)
}
IntegrityEvent records one block-level integrity finding, kept from the moment of discovery until it is reported to the app (peek with Garland.IntegrityEvents; a successful save drains pending events into its SaveReport).
type IntegrityKind ¶ added in v0.1.4
type IntegrityKind int
IntegrityKind classifies what happened to a block whose backing bytes stopped matching expectations.
const ( // IntegrityBlockSlid: the block was found intact at a shifted file // offset (external insert/delete earlier in the file) and was // re-homed. Nothing lost; buffer content unchanged. IntegrityBlockSlid IntegrityKind = iota // IntegrityBlockSwapped: the block's exact bytes were found at // another block's backing position, and that block's bytes at // ours - an external move. Backing offsets were exchanged. // Nothing lost; buffer content unchanged. IntegrityBlockSwapped // IntegrityBlockAdopted: soft loss of integrity. The surrounding // blocks still verify, so the mismatch looks like a deliberate // external edit confined to this block. The file's bytes were // adopted into the buffer (a future save preserves them); the // buffer's previous bytes for this block are gone. IntegrityBlockAdopted // IntegrityBlockAdoptedDuplicate: adopted as above, but the // adopted content is an exact duplicate of another preserved // block - an external move/copy is likely, so the app may want to // look more closely. IntegrityBlockAdoptedDuplicate // IntegrityBlockLost: hard corruption. Nothing around the block // matched expectations and no relocation was found. The block is a // placeholder and will be written as a scar by the next save. IntegrityBlockLost // IntegrityDecorationsLost: a block's CONTENT thawed fine but its // decorations could not be restored from cold storage (side block // missing, hash mismatch, or corrupt encoding). The marks in that // block are gone; everything else is intact. IntegrityDecorationsLost // IntegrityBlockResized: an external edit INSIDE this block changed // its length - its old bytes no longer exist contiguously anywhere, // so reads fail (placeholder), but the situation is precisely // diagnosed: the neighbor before verifies at its recorded offset // and the neighbor after verifies shifted by the file's size // change. RebaseOnSource() will adopt the resized content cleanly. IntegrityBlockResized )
func (IntegrityKind) String ¶ added in v0.1.4
func (k IntegrityKind) String() string
String returns a short human-readable name for the kind.
type LeafSearchResult ¶
type LeafSearchResult struct {
Node *Node // the leaf node
Snapshot *NodeSnapshot // the node's snapshot at current version
ByteOffset int64 // byte offset from start of this leaf to target
RuneOffset int64 // rune offset from start of this leaf to target
LeafByteStart int64 // absolute byte position where this leaf starts
LeafRuneStart int64 // absolute rune position where this leaf starts
RunesOnLineBeforeLeaf int64 // runes on current line before this leaf starts
}
LeafSearchResult contains information about a leaf node found during tree traversal.
type Library ¶
type Library struct {
// contains filtered or unexported fields
}
Library manages garland instances and shared resources like cold storage.
func Init ¶
func Init(options LibraryOptions) (*Library, error)
Init initializes the garland library with cold storage options. Cold storage is shared across all files opened through this library instance.
func (*Library) CheckMemoryPressureError ¶
CheckMemoryPressureError returns ErrMemoryPressure if the library is under memory pressure, nil otherwise. Useful for checking before mutations.
func (*Library) ChillToTarget ¶
func (lib *Library) ChillToTarget() MaintenanceStats
ChillToTarget performs incremental chilling until memory is below the soft limit. It respects the budget per tick and returns when either: - Memory is below soft limit - No more candidates to chill - Budget exhausted for this tick
func (*Library) DefaultFS ¶ added in v0.1.6
func (lib *Library) DefaultFS() FileSystemInterface
DefaultFS returns the filesystem this library uses for local-disk operations (the same one Garland resolves to when no explicit filesystem is given). Useful for hosts that want to wrap or delegate to it when composing a custom FileSystemInterface.
func (*Library) DeviceInfoFor ¶ added in v0.1.7
func (lib *Library) DeviceInfoFor(fs FileSystemInterface, name string) (DeviceInfo, error)
DeviceInfoFor reports the storage device behind a path (identity and free space) through the given filesystem, for free-space warnings before a save. A nil fs uses the library default (local disk).
func (*Library) IncrementalChill ¶
func (lib *Library) IncrementalChill(budget int) MaintenanceStats
IncrementalChill performs budgeted LRU-based chilling across all Garlands. It chills at most `budget` nodes, prioritizing least-recently-used. Returns the number of nodes chilled and bytes freed.
func (*Library) MemoryPressure ¶
MemoryPressure returns true if the library is under memory pressure (hard limit exceeded and cannot be reduced). Applications should check this before performing memory-intensive operations.
func (*Library) Open ¶
func (lib *Library) Open(options FileOptions) (*Garland, error)
Open creates or loads a Garland from various sources.
func (*Library) StopMaintenance ¶
func (lib *Library) StopMaintenance()
StopMaintenance stops the background maintenance worker.
func (*Library) TotalMemoryUsage ¶
TotalMemoryUsage returns the total memory usage across all Garlands in the library.
type LibraryOptions ¶
type LibraryOptions struct {
// ColdStoragePath is a filesystem path for cold storage.
// Either this or ColdStorageBackend must be provided (or both).
ColdStoragePath string
// ColdStorageBackend is a custom cold storage implementation.
ColdStorageBackend ColdStorageInterface
// Memory management options
// MemorySoftLimit is the target memory usage in bytes.
// When exceeded, background maintenance starts chilling LRU nodes.
// 0 means disabled (default).
MemorySoftLimit int64
// MemoryHardLimit is the maximum memory usage in bytes.
// When exceeded, immediate (but still budgeted) chilling occurs.
// 0 means disabled (default).
MemoryHardLimit int64
// ChillBudgetPerTick is the maximum nodes to chill per maintenance tick.
// Default is 5 if not specified.
ChillBudgetPerTick int
// RebalanceBudget is the maximum rotations per mutation operation.
// Default is 2 if not specified.
RebalanceBudget int
// BackgroundInterval is how often the background maintenance worker runs.
// 0 means disabled (maintenance only happens opportunistically).
// Typical value: 100ms to 1s.
BackgroundInterval time.Duration
}
LibraryOptions configures the garland library.
type LineSearchResult ¶
type LineSearchResult struct {
LeafResult *LeafSearchResult
LineByteStart int64 // absolute byte position where target line starts
LineRuneStart int64 // absolute rune position where target line starts
}
LineSearchResult contains information about a line found during tree traversal.
type LineStart ¶
type LineStart struct {
// ByteOffset is the byte offset from the start of the node where this line begins.
ByteOffset int64
// RuneOffset is the rune offset from the start of the node where this line begins.
RuneOffset int64
}
LineStart represents the starting position of a line within a leaf node.
type Loader ¶
type Loader struct {
// contains filtered or unexported fields
}
Loader handles background loading of data from various sources.
type LoadingStyle ¶
type LoadingStyle int
LoadingStyle determines which storage tiers are available.
const ( // AllStorage allows memory, warm (original file), and cold storage. // Warm storage requires the original file to be unchanged. AllStorage LoadingStyle = iota // ColdAndMemory prevents warm storage, only memory and cold. ColdAndMemory // MemoryOnly keeps everything in memory, no external storage. MemoryOnly )
type MaintenanceStats ¶
type MaintenanceStats struct {
NodesChilled int // number of nodes moved to cold storage
BytesChilled int64 // bytes moved to cold storage
RotationsPerformed int // number of tree rotations performed
}
MaintenanceStats contains statistics from a maintenance run.
type MemoryPressureInfo ¶ added in v0.1.4
type MemoryPressureInfo struct {
// ResidentBytes is the leaf data currently held in memory.
ResidentBytes int64
// EvictableBytes could be chilled to warm or cold storage right
// now without any save.
EvictableBytes int64
// SaveableBytes are current-revision bytes that only a Save can
// make evictable: they have no file backing yet and no cold
// backend exists, so saving (which gives them warm backing) is
// the only way to get them out of memory.
SaveableBytes int64
// SoftLimitBytes / HardLimitBytes echo the configured library
// limits (0 = none).
SoftLimitBytes int64
HardLimitBytes int64
}
MemoryPressureInfo describes where this buffer's resident memory stands and what can relieve it. It is the signal for an app-side "hot-write mode": when SaveableBytes dominates ResidentBytes and the total approaches the hard limit, saving is the only relief left - "in order to keep editing, I need to save before I run out of RAM." The library reports; the app decides when to prompt or act.
type MemoryStats ¶
type MemoryStats struct {
MemoryBytes int64 // bytes of in-memory leaf data
SoftLimit int64 // configured soft limit (0 = disabled)
HardLimit int64 // configured hard limit (0 = disabled)
InMemoryLeaves int // count of leaves with data in memory
ColdStoredLeaves int // count of leaves with data in cold storage
WarmStoredLeaves int // count of leaves with data in warm storage
UnderPressure bool // true if hard limit exceeded and can't reduce
}
MemoryStats contains current memory usage statistics.
type MoveResult ¶
type MoveResult struct {
ChangeResult
DisplacedDecorations []RelativeDecoration // Decorations that were in the destination range (original positions)
}
MoveResult contains the result of a Move operation.
type Node ¶
type Node struct {
// contains filtered or unexported fields
}
Node is a versioned container in the rope structure. Each node maintains a history of its state indexed by (ForkID, RevisionID).
type NodeSnapshot ¶
type NodeSnapshot struct {
// contains filtered or unexported fields
}
NodeSnapshot represents the immutable state of a node at a specific version.
func (*NodeSnapshot) ByteCount ¶
func (s *NodeSnapshot) ByteCount() int64
ByteCount returns the total bytes in this subtree.
func (*NodeSnapshot) Data ¶
func (s *NodeSnapshot) Data() []byte
Data returns the leaf node's data. Returns nil for internal nodes.
func (*NodeSnapshot) Decorations ¶
func (s *NodeSnapshot) Decorations() []Decoration
Decorations returns the leaf node's decorations. Returns nil for internal nodes.
func (*NodeSnapshot) IsLeaf ¶
func (s *NodeSnapshot) IsLeaf() bool
IsLeaf returns true if this snapshot represents a leaf node.
func (*NodeSnapshot) LeftID ¶
func (s *NodeSnapshot) LeftID() NodeID
LeftID returns the left child's ID. Only valid for internal nodes.
func (*NodeSnapshot) LineCount ¶
func (s *NodeSnapshot) LineCount() int64
LineCount returns the total newlines in this subtree.
func (*NodeSnapshot) RightID ¶
func (s *NodeSnapshot) RightID() NodeID
RightID returns the right child's ID. Only valid for internal nodes.
func (*NodeSnapshot) RuneCount ¶
func (s *NodeSnapshot) RuneCount() int64
RuneCount returns the total runes in this subtree.
type OptimizedRegionHandle ¶
type OptimizedRegionHandle struct {
// contains filtered or unexported fields
}
OptimizedRegionHandle tracks an active optimized region attached to a cursor.
func (*OptimizedRegionHandle) ByteCount ¶
func (h *OptimizedRegionHandle) ByteCount() int64
ByteCount returns the current byte count of the region content.
func (*OptimizedRegionHandle) ContentBounds ¶
func (h *OptimizedRegionHandle) ContentBounds() (start, end int64)
ContentBounds returns the current content bounds (document coordinates).
func (*OptimizedRegionHandle) GraceWindow ¶
func (h *OptimizedRegionHandle) GraceWindow() (start, end int64)
GraceWindow returns the grace window bounds (document coordinates).
func (*OptimizedRegionHandle) Serial ¶
func (h *OptimizedRegionHandle) Serial() uint64
Serial returns the unique serial number of this region for debugging.
type ReadAheadConfig ¶
type ReadAheadConfig struct {
Lines int64 // additional lines to read ahead (0 = ignore)
Bytes int64 // additional bytes to read ahead (0 = ignore)
Runes int64 // additional runes to read ahead (0 = ignore)
All bool // read entire file ASAP
}
ReadAheadConfig specifies lazy read-ahead behavior.
type ReadyThreshold ¶
type ReadyThreshold struct {
Lines int64 // number of complete lines (0 = ignore)
Bytes int64 // number of bytes (0 = ignore)
Runes int64 // number of runes (0 = ignore)
All bool // only ready when entire file processed
}
ReadyThreshold specifies when a garland is considered "ready".
type RebaseRegion ¶ added in v0.1.4
type RebaseRegion struct {
Offset int64 // byte offset in the new buffer (== file offset)
Length int64
}
RebaseRegion is one contiguous region of the new buffer whose content came from the file rather than from preserved blocks.
type RebaseReport ¶ added in v0.1.4
type RebaseReport struct {
// Adopted lists the regions whose content was taken from the file
// (external edits ingested; unsaved local edits displaced).
Adopted []RebaseRegion
BytesKept int64 // bytes preserved through matched blocks
BytesAdopted int64 // bytes taken from the file
BlocksKept int // matched blocks (identity preserved)
BlocksHealed int // placeholder blocks recovered from the file
OldSize int64 // buffer size before the rebase
NewSize int64 // buffer size after (== file size)
// NoChange is true when the buffer already matched the file
// byte-for-byte: no mutation was recorded (backing offsets may
// still have been re-homed and placeholders healed in place).
NoChange bool
// PreviousRevision is the revision holding the pre-rebase buffer;
// UndoSeek there is the "keep your version" escape hatch. Equal to
// the current revision when NoChange.
PreviousRevision RevisionID
}
RebaseReport describes what a Rebase did.
type RegexOptions ¶
type RegexOptions struct {
CaseInsensitive bool // If true, regex is case-insensitive
Backward bool // If true, search backward from cursor
}
RegexOptions configures regex search behavior.
type RelativeDecoration ¶
RelativeDecoration specifies a decoration position relative to an insert point. Position semantics:
- < 0 : attach after the newline preceding the insert point
- 0 to Len : attach to the byte/rune at that offset in inserted content
- Len + 1 : attach before the newline following the insert point
- > Len + 1: attach after the newline following the insert point
type RevisionInfo ¶
type RevisionInfo struct {
Revision RevisionID
Name string // from TransactionStart
HasChanges bool // true if actual mutations occurred
RootID NodeID // root node ID at this revision (for UndoSeek)
StreamKnownBytes int64 // bytes of streaming content known when revision was created (-1 if complete)
}
RevisionInfo contains metadata about a revision for undo history display.
type SaveAsOptions ¶ added in v0.1.7
type SaveAsOptions struct {
// AdoptAsSource makes the destination the buffer's new source and
// warm-storage backing after a successful write: warm references
// re-home onto the new file, change detection re-baselines against
// it, and future Save calls write there. Use this for "the file
// lives here now". Leave it false when the destination must not be
// depended on afterwards - an export, or removable media about to
// be ejected - so the buffer keeps working from its original
// source.
AdoptAsSource bool
// PreserveHistory (adoption only): undo history backed by the OLD
// source is migrated off it (cold storage when available, else
// memory) before the source switches. When false such history is
// marked lost - amputated, never silently corrupted. Ignored when
// AdoptAsSource is false (the old source stays attached, history
// untouched).
PreserveHistory bool
}
SaveAsOptions configures SaveAsWith.
type SaveOptions ¶ added in v0.1.4
type SaveOptions struct {
// PreserveHistory protects warm-backed data that only OLDER
// revisions reference: before the rewrite can overwrite its
// backing bytes it is migrated to cold storage (or held in memory
// when no cold backend is configured), so undo history survives
// the save intact.
//
// When false, such history keeps pointing at its old file offsets;
// regions the rewrite left untouched remain valid, and regions
// that were overwritten fail their hash check on access and become
// placeholders - undo history may be amputated, but never silently
// corrupted.
PreserveHistory bool
// Concurrent (opt-in) runs the rewrite WITHOUT holding the buffer
// lock: the app may keep reading and editing on its op goroutine
// while the save writes (only Prune, DeleteFork, Rebase, Close,
// and other saves wait for it). The cost is that every warm span
// the rewrite displaces must first be EVACUATED - to cold storage
// when a backend exists, else into memory - because the file
// cannot be both the old layout (for live warm reads) and the new
// layout (being written) at once. When there is no cold backend
// and the evacuation would push memory past the configured hard
// limit, the save transparently falls back to the locked zero-copy
// path (SaveReport.Concurrent reports what actually ran).
Concurrent bool
}
SaveOptions configures Save behavior.
type SavePoint ¶ added in v0.1.7
type SavePoint struct {
// Fork and Revision identify the buffer state the save wrote.
Fork ForkID
Revision RevisionID
// Path is where the content was written.
Path string
// Meta is the file's metadata observed right after the save (zero
// when the destination filesystem cannot report metadata).
Meta FileMetadata
// SavedAt is when the save completed.
SavedAt time.Time
// AdoptedAsSource reports whether this location became (or already
// was) the buffer's source / warm-storage backing at save time.
AdoptedAsSource bool
// contains filtered or unexported fields
}
SavePoint records one successful save: where the content went, what the file looked like immediately afterwards, and which fork/revision the save captured - the anchor for "revert to last saved version" (a pure history seek) and for source recovery/adoption.
type SaveReport ¶ added in v0.1.4
type SaveReport struct {
// Scars lists blocks whose data was lost to storage failure and
// were written as visible scars instead. Empty on a clean save.
Scars []ScarWarning
// Integrity lists block-level integrity events discovered since
// the last successful save: external edits that slid, moved, or
// modified warm-backed blocks (recovered or adopted without loss),
// and hard losses. A successful save drains the pending log here;
// IntegrityEvents() peeks at it between saves.
Integrity []IntegrityEvent
// Concurrent reports whether the save actually ran without holding
// the buffer lock. A SaveOptions.Concurrent request falls back to
// the locked zero-copy path (Concurrent=false here) when the
// required evacuation cannot be afforded.
Concurrent bool
}
SaveReport carries non-fatal outcomes of a save.
type ScarWarning ¶ added in v0.1.4
type ScarWarning struct {
Offset int64 // byte offset of the scarred block in the saved content
Length int64 // byte count of the lost block (the scar occupies exactly this)
Marker string // the human-readable marker text
Appended bool // marker did not fit in the block; it was appended at EOF
// Reason is why the data was lost, recorded at the moment the loss
// was discovered (e.g. "cold storage read failed: ...", "source
// file changed on disk (hash mismatch)"). Empty when the cause was
// never observed by the library.
Reason string
}
ScarWarning reports one lost block that was written as a visible scar during a save. The app should surface these to the user: the save succeeded, but this data is gone.
type SearchOptions ¶
type SearchOptions struct {
CaseSensitive bool // If false, search is case-insensitive
WholeWord bool // If true, only match whole words
Backward bool // If true, search backward from cursor
}
SearchOptions configures string search behavior.
type SearchResult ¶
type SearchResult struct {
ByteStart int64 // Start position in bytes
ByteEnd int64 // End position in bytes (exclusive)
Match string // The matched text
}
SearchResult contains information about a search match.
type SnapshotStats ¶
type SnapshotStats struct {
TotalSnapshots int // Total snapshots across all nodes
ByFork map[ForkID]int // Snapshots per fork
ByForkRevision map[ForkRevision]int // Snapshots per fork/revision
}
SnapshotStats contains statistics about node snapshots.
type SourceChangeHandler ¶
type SourceChangeHandler func(g *Garland, status SourceChangeStatus, info SourceChangeInfo)
SourceChangeHandler is called when a source file change is detected.
type SourceChangeInfo ¶
type SourceChangeInfo struct {
Type SourceChangeType
PreviousSize int64
CurrentSize int64
AppendedBytes int64 // Only valid if Type == SourceAppended
}
SourceChangeInfo contains details about a detected source file change.
type SourceChangeStatus ¶
type SourceChangeStatus int
SourceChangeStatus indicates the current status of source file tracking.
const ( // SourceStatusNormal indicates no changes have been detected. SourceStatusNormal SourceChangeStatus = iota // SourceStatusAppendAvailable indicates an append was detected and verified. SourceStatusAppendAvailable // SourceStatusSuspectChange indicates metadata changed but not yet verified. SourceStatusSuspectChange // SourceStatusModified indicates a checksum mismatch was confirmed. SourceStatusModified )
type SourceChangeType ¶
type SourceChangeType int
SourceChangeType indicates the type of change detected in the source file.
const ( // SourceUnchanged indicates no change was detected. SourceUnchanged SourceChangeType = iota // SourceAppended indicates the file grew but existing content is intact. SourceAppended // SourceModified indicates existing content was altered. SourceModified // SourceTruncated indicates the file was shortened. SourceTruncated // SourceReplaced indicates the file was replaced (different inode). SourceReplaced // SourceDeleted indicates the file no longer exists. SourceDeleted )
func (SourceChangeType) String ¶
func (t SourceChangeType) String() string
String returns a human-readable description of the change type.
type SourceConsistencyReport ¶ added in v0.1.7
type SourceConsistencyReport struct {
State SourceConsistencyState
// Baseline is the metadata recorded when buffer and file last
// agreed (open, save, adoption). Zero when State is Untracked.
Baseline FileMetadata
// Observed is the most recent observation (stat through the hook or
// volunteered), Zero when nothing was ever observed past baseline.
Observed FileMetadata
// ObservedAt is when Observed was recorded (zero: never).
ObservedAt time.Time
// LockedBy is the owner string of a foreign emacs-style lock file
// seen on the source ("user@host.pid"), empty when none is known.
// Only populated when FileOptions.UseEmacsLocks was enabled.
LockedBy string
}
SourceConsistencyReport answers "can I trust the source file right now?" with everything the app needs for its UI decision.
type SourceConsistencyState ¶ added in v0.1.7
type SourceConsistencyState int
SourceConsistencyState summarizes the relationship between the buffer's baseline (the file as last known to agree with the buffer's origin) and the most recent observation of the file.
const ( // ConsistencyUntracked: no metadata baseline exists - there is no // source path, or the filesystem hook does not support Stat and the // application never volunteered metadata. ConsistencyUntracked SourceConsistencyState = iota // ConsistencyClean: the file looks exactly as baselined. ConsistencyClean // ConsistencyAppended: the file grew; existing content may be intact // (verify with VerifyBoundaryForAppend). ConsistencyAppended // ConsistencyModified: same size but the modification time changed. ConsistencyModified // ConsistencyTruncated: the file shrank. ConsistencyTruncated // ConsistencyReplaced: the path is bound to a different storage // object (the file was replaced by rename). ConsistencyReplaced // ConsistencyMissing: the file no longer exists. ConsistencyMissing )
func (SourceConsistencyState) String ¶ added in v0.1.7
func (s SourceConsistencyState) String() string
String returns a human-readable description of the state.
type StorageState ¶
type StorageState int
StorageState indicates where a node's data is currently stored.
const ( // StorageMemory indicates data is in memory. StorageMemory StorageState = iota // StorageWarm indicates data is in the original file (warm storage). StorageWarm // StorageCold indicates data is in cold storage. StorageCold // StoragePlaceholder indicates data was lost due to storage failure. StoragePlaceholder )
type TransactionState ¶
type TransactionState struct {
// contains filtered or unexported fields
}
TransactionState holds the state of an active transaction.
type TreeNodeInfo ¶
type TreeNodeInfo struct {
NodeID NodeID
IsLeaf bool
ByteCount int64
RuneCount int64
LineCount int64
Storage StorageState
DataPreview string // First 32 chars of leaf data (for leaves only)
LeftChildID NodeID // For internal nodes
RightChildID NodeID // For internal nodes
Children []*TreeNodeInfo
}
TreeNodeInfo contains information about a single node in the tree.
type VerifyLevel ¶ added in v0.1.7
type VerifyLevel int
VerifyLevel selects how much evidence AdoptWarmSource requires that a candidate file's content matches the buffer, trading speed for proof.
const ( // VerifyMetadata is the swiftest check: the candidate must carry // the exact metadata recorded by a save of THIS buffer state (a // SavePoint at the current fork/revision for that path). No content // is read. With a metadata-less filesystem the save point alone is // accepted as the best available evidence. VerifyMetadata VerifyLevel = iota // VerifySample also hash-checks a bounded sample of content spans // (first, last, and a few evenly spaced blocks). VerifySample // VerifyFull hash-checks every span before adopting. VerifyFull )
type WarmTrustLevel ¶
type WarmTrustLevel int
WarmTrustLevel indicates how much we trust warm storage for a given block.
const ( // WarmTrustFull indicates no changes ever detected, fully trusted. WarmTrustFull WarmTrustLevel = iota // WarmTrustVerified indicates changes detected but block verified since. WarmTrustVerified // WarmTrustStale indicates changes detected and block not verified. WarmTrustStale // WarmTrustSuspended indicates user notified but hasn't responded. WarmTrustSuspended )
type WordStyle ¶ added in v0.1.4
type WordStyle int
WordStyle selects the word-boundary semantics for word motions.
const ( // WordStyleSimple: a word is a run of letters/digits/underscore; // punctuation and whitespace are separators (never stops). WordStyleSimple WordStyle = iota // WordStyleVi: like vi's w/b - punctuation runs are words of // their own, so both word-character runs and punctuation runs are // stops; only whitespace separates. WordStyleVi )
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
garland-bench
command
garland-bench is a benchmark and stress test for the Garland library.
|
garland-bench is a benchmark and stress test for the Garland library. |
|
garland-repl
command
|