gofmt: format all remaining files with the go1.27 toolchain

The tree was formatted with an older gofmt; go1.27's gofmt additionally
wants: EOF exactly one newline (no trailing blank lines), imports sorted
alphabetically within a block, mixed-precedence binary expressions
re-spaced for grouping ((a+b)/c), single-field composite literals
un-aligned, adjacent one-line method signatures aligned, and one-line
bodies containing a compound statement expanded. Applied repo-wide
(31 files under internal/); pure formatting, no semantic changes —
build and the full test suite pass.
This commit is contained in:
Greg Pomerantz 2026-08-23 10:03:27 -04:00
parent 180fa966c8
commit 06b1444207
31 changed files with 279 additions and 247 deletions

View File

@ -66,7 +66,7 @@ func computeVisiblePageRange(s *BrowserState) (minPage, maxPage int) {
if minPage < 0 {
minPage = 0
}
maxPage = (s.GetScrollIndex() + s.VisibleCount)/PageSize + PrefetchDist
maxPage = (s.GetScrollIndex()+s.VisibleCount)/PageSize + PrefetchDist
return minPage, maxPage
}
@ -164,4 +164,3 @@ func filterEntriesByQuery(entries []Entry, query string) []int {
return results
}

View File

@ -28,7 +28,7 @@ func TestLoadPage_FromIndexAtOffset(t *testing.T) {
// Build position maps for sort modes
s.SortIndex = &DirectoryIndex{
Entries: allEntries,
Entries: allEntries,
SortOrders: map[string][]int{
"name_asc": buildPositionMap(allEntries, SortModeNameAsc),
"date_desc": buildPositionMap(allEntries, SortModeDateDesc),
@ -76,7 +76,7 @@ func TestLoadPage_LastPagePartialFromIndex(t *testing.T) {
// Build position maps for sort modes
s.SortIndex = &DirectoryIndex{
Entries: allEntries,
Entries: allEntries,
SortOrders: map[string][]int{
"name_asc": buildPositionMap(allEntries, SortModeNameAsc),
"date_desc": buildPositionMap(allEntries, SortModeDateDesc),
@ -116,7 +116,7 @@ func TestLoadPage_OutOfBoundsFromIndex(t *testing.T) {
// Build position maps for sort modes
s.SortIndex = &DirectoryIndex{
Entries: allEntries,
Entries: allEntries,
SortOrders: map[string][]int{
"name_asc": buildPositionMap(allEntries, SortModeNameAsc),
"date_desc": buildPositionMap(allEntries, SortModeDateDesc),
@ -195,7 +195,7 @@ func TestGetEntryByIndex(t *testing.T) {
// Build position maps for sort modes
s.SortIndex = &DirectoryIndex{
Entries: allEntries,
Entries: allEntries,
SortOrders: map[string][]int{
"name_asc": buildPositionMap(allEntries, SortModeNameAsc),
"date_desc": buildPositionMap(allEntries, SortModeDateDesc),
@ -236,7 +236,7 @@ func TestGetEntryByIndex_UnloadedPage(t *testing.T) {
// Build position maps for sort modes
s.SortIndex = &DirectoryIndex{
Entries: allEntries,
Entries: allEntries,
SortOrders: map[string][]int{
"name_asc": buildPositionMap(allEntries, SortModeNameAsc),
"date_desc": buildPositionMap(allEntries, SortModeDateDesc),

View File

@ -13,11 +13,11 @@ import (
// DirectoryIndex holds a cached index of a directory's contents.
// Per design: index stores raw metadata; sorting is pre-computed via position maps.
type DirectoryIndex struct {
Path string `json:"path"`
Mtime time.Time `json:"mtime"`
EntryCount int `json:"entry_count"`
Entries []Entry `json:"entries"`
SortOrders map[string][]int `json:"sort_orders,omitempty"` // key: "name_asc", "name_desc", etc.
Path string `json:"path"`
Mtime time.Time `json:"mtime"`
EntryCount int `json:"entry_count"`
Entries []Entry `json:"entries"`
SortOrders map[string][]int `json:"sort_orders,omitempty"` // key: "name_asc", "name_desc", etc.
}
// getCachePath returns the path to the cached index file for a directory.

View File

@ -224,5 +224,3 @@ func TestBuildIndex_LargeDirectory(t *testing.T) {
t.Errorf("buildIndex took %v, expected < 5s", elapsed)
}
}

View File

@ -160,8 +160,6 @@ func recomputeSearchResults(s *BrowserState) {
}
}
// ComputeVisibleEntriesForTest is exported for testing purposes.
// It builds the list of ui.ListItem entries that should be rendered.
func ComputeVisibleEntriesForTest(state *BrowserState) []ui.ListItem {

View File

@ -32,7 +32,7 @@ func makeTestState(t *testing.T, entryCount int, scrollIndex int, visibleCount i
// Build position maps for sort modes
s.SortIndex = &DirectoryIndex{
Entries: entries,
Entries: entries,
SortOrders: map[string][]int{
"name_asc": buildPositionMap(entries, SortModeNameAsc),
"date_desc": buildPositionMap(entries, SortModeDateDesc),

View File

@ -145,7 +145,7 @@ func TestPixelScroll_EvictionTriggered(t *testing.T) {
entries[i] = NewEntry("/test/file.txt", "file.txt", 100, s.TapTimestamp, false)
}
s.SortIndex = &DirectoryIndex{
Entries: entries,
Entries: entries,
SortOrders: map[string][]int{
"name_asc": buildPositionMap(entries, SortModeNameAsc),
"date_desc": buildPositionMap(entries, SortModeDateDesc),
@ -184,7 +184,7 @@ func TestPixelScroll_PrefetchTriggered(t *testing.T) {
entries[i] = NewEntry("/test/file.txt", "file.txt", 100, s.TapTimestamp, false)
}
s.SortIndex = &DirectoryIndex{
Entries: entries,
Entries: entries,
SortOrders: map[string][]int{
"name_asc": buildPositionMap(entries, SortModeNameAsc),
"date_desc": buildPositionMap(entries, SortModeDateDesc),

View File

@ -83,7 +83,7 @@ func TestScroll_PrefetchTriggered(t *testing.T) {
}
// Build position maps for sort modes
s.SortIndex = &DirectoryIndex{
Entries: entries,
Entries: entries,
SortOrders: map[string][]int{
"name_asc": buildPositionMap(entries, SortModeNameAsc),
"date_desc": buildPositionMap(entries, SortModeDateDesc),
@ -131,7 +131,7 @@ func TestScroll_EvictionTriggered(t *testing.T) {
}
// Build position maps for sort modes
s.SortIndex = &DirectoryIndex{
Entries: entries,
Entries: entries,
SortOrders: map[string][]int{
"name_asc": buildPositionMap(entries, SortModeNameAsc),
"date_desc": buildPositionMap(entries, SortModeDateDesc),
@ -246,7 +246,7 @@ func TestScroll_PrefetchTriggeredOnPageBoundary(t *testing.T) {
}
// Build position maps for sort modes
s.SortIndex = &DirectoryIndex{
Entries: entries,
Entries: entries,
SortOrders: map[string][]int{
"name_asc": buildPositionMap(entries, SortModeNameAsc),
"date_desc": buildPositionMap(entries, SortModeDateDesc),

View File

@ -69,4 +69,3 @@ func comparator(mode SortMode) func(a, b Entry) int {
return func(a, b Entry) int { return 0 }
}
}

View File

@ -19,20 +19,20 @@ type Entry struct {
// Page represents a chunk of directory entries loaded from disk.
type Page struct {
Index int // Page number (0-based)
Entries []Entry // Entries in this page
Loaded bool // True if page data is in memory
Dirty bool // True if page needs refresh (external change detected)
Index int // Page number (0-based)
Entries []Entry // Entries in this page
Loaded bool // True if page data is in memory
Dirty bool // True if page needs refresh (external change detected)
}
// BrowserState holds all mutable browser state owned by the logic goroutine.
type BrowserState struct {
// Navigation
CurrentPath string // Currently browsed directory (relative to root)
History []string // Path history for navigation
ScrollOffset float64 // Vertical scroll offset in pixels (per-pixel scrolling)
EntryHeight float64 // Height of a single entry in pixels
VisibleCount int // Number of entries currently visible
CurrentPath string // Currently browsed directory (relative to root)
History []string // Path history for navigation
ScrollOffset float64 // Vertical scroll offset in pixels (per-pixel scrolling)
EntryHeight float64 // Height of a single entry in pixels
VisibleCount int // Number of entries currently visible
// Lazy loading
Pages map[int]*Page // Loaded pages by page index
@ -44,8 +44,8 @@ type BrowserState struct {
SortMode SortMode // Current sort mode
// Search
Query string // Current search query (forwarded from the main-owned search widget)
SearchResults []int // Indices of matching entries (empty = no filter)
Query string // Current search query (forwarded from the main-owned search widget)
SearchResults []int // Indices of matching entries (empty = no filter)
// NOTE: the search bar's widget.Editor is intentionally NOT part of this
// state: Gio mutates widget state on the main goroutine during draw, and
// this state is owned by the logic goroutine (architecture.md §1). The
@ -62,8 +62,8 @@ type BrowserState struct {
}
const (
PageSize = 100 // Entries per page (tunable; ~5KB per page in memory)
PrefetchDist = 2 // Pages to prefetch beyond visible region
PageSize = 100 // Entries per page (tunable; ~5KB per page in memory)
PrefetchDist = 2 // Pages to prefetch beyond visible region
)
// NewEntry creates a new Entry from the given parameters.
@ -127,10 +127,10 @@ func formatSize(bytes int64) string {
// EvictPages removes pages that are far from the current scroll position.
func (s *BrowserState) EvictPages() {
minPage := s.GetScrollIndex()/PageSize - PrefetchDist
maxPage := (s.GetScrollIndex() + s.VisibleCount)/PageSize + PrefetchDist
maxPage := (s.GetScrollIndex()+s.VisibleCount)/PageSize + PrefetchDist
for idx, page := range s.Pages {
if idx < minPage || idx > maxPage {
page.Entries = nil // Release memory
page.Entries = nil // Release memory
page.Loaded = false
}
}

View File

@ -103,7 +103,7 @@ func TestFormatSize(t *testing.T) {
{0, "0 B"},
{500, "500 B"},
{1024, "1.0 KB"},
{1024*1024, "1.0 MB"},
{1024 * 1024, "1.0 MB"},
{1024 * 1024 * 1024, "1.0 GB"},
}
@ -118,7 +118,7 @@ func TestFormatSize(t *testing.T) {
func TestBrowserStateEvictPages(t *testing.T) {
s := NewBrowserState()
s.EntryHeight = 48.0
s.ScrollOffset = 500 * 48 // Page 5
s.ScrollOffset = 500 * 48 // Page 5
s.VisibleCount = 10
// With ScrollIndex=500, PageSize=100:
@ -127,10 +127,10 @@ func TestBrowserStateEvictPages(t *testing.T) {
// Pages 3-7 should be kept, others evicted
// Add pages at various positions
s.Pages[0] = NewPage(0, nil) // Should be evicted (far)
s.Pages[3] = NewPage(3, nil) // Should be kept (at min boundary)
s.Pages[5] = NewPage(5, nil) // Should be kept (visible)
s.Pages[7] = NewPage(7, nil) // Should be kept (at max boundary)
s.Pages[0] = NewPage(0, nil) // Should be evicted (far)
s.Pages[3] = NewPage(3, nil) // Should be kept (at min boundary)
s.Pages[5] = NewPage(5, nil) // Should be kept (visible)
s.Pages[7] = NewPage(7, nil) // Should be kept (at max boundary)
s.Pages[10] = NewPage(10, nil) // Should be evicted (far)
s.EvictPages()

View File

@ -189,9 +189,9 @@ func TestLargeFileChunkBoundary(t *testing.T) {
// (The old fixed-slot model treated each chunk as an independent buffer and
// did NOT shift later chunks; that was the bug this design replaces.)
expectedStr := string(initialContent)
expectedStr = expectedStr[:65000] + "CHUNK1" + expectedStr[65000:] // insert 1 @65000
expectedStr = expectedStr[:65535] + "BOUNDARY" + expectedStr[65535:] // insert 2 @65535
expectedStr = expectedStr[:262000] + "CHUNK3" + expectedStr[262000:] // insert 3 @262000
expectedStr = expectedStr[:65000] + "CHUNK1" + expectedStr[65000:] // insert 1 @65000
expectedStr = expectedStr[:65535] + "BOUNDARY" + expectedStr[65535:] // insert 2 @65535
expectedStr = expectedStr[:262000] + "CHUNK3" + expectedStr[262000:] // insert 3 @262000
expected := []byte(expectedStr)
if len(savedContent) != len(expected) {

View File

@ -1,8 +1,8 @@
package editor
import (
"testing"
"pad/internal/ui"
"testing"
)
func TestEditorLayout_Filename(t *testing.T) {

View File

@ -40,8 +40,8 @@ func newChunkedState(t *testing.T, content string, chunkSize int) *State {
func TestRuneIndexToByteStr(t *testing.T) {
cases := []struct {
s string
n int
s string
n int
want int
}{
{"", 0, 0},

View File

@ -111,7 +111,7 @@ func TestWordWrapFragmentStartY(t *testing.T) {
// Test case: Word wrap enabled, scroll to visual line 5
// With word wrap, visual lines don't correspond 1:1 with logical lines
wordWrap := true
_ = wordWrap // Mark as used for this test
_ = wordWrap // Mark as used for this test
scrollOffset := ui.Dp(5 * float64(lineHeight)) // Scroll to visual line 5
visualLine := int(scrollOffset / lineHeight)
@ -152,24 +152,24 @@ func TestByteOffsetAndYFromScroll(t *testing.T) {
}
layout := ui.GlyphLayout{
ByteOffsets: []int{0, 7, 14, 21},
X: []ui.Dp{0, 0, 0, 0},
Y: []ui.Dp{0, 16.8, 33.6, 50.4},
Advance: []ui.Dp{10, 10, 10, 10},
LineHeight: lineHeight,
ByteOffsets: []int{0, 7, 14, 21},
X: []ui.Dp{0, 0, 0, 0},
Y: []ui.Dp{0, 16.8, 33.6, 50.4},
Advance: []ui.Dp{10, 10, 10, 10},
LineHeight: lineHeight,
VisualLineIndex: visualLineIndex,
}
// Test scrolling to different positions
testCases := []struct {
scrollOffset ui.Dp
expectedByte int
expectedY ui.Dp
scrollOffset ui.Dp
expectedByte int
expectedY ui.Dp
}{
{ui.Dp(0), 0, ui.Dp(0)}, // Top of document
{ui.Dp(16.8), 7, ui.Dp(16.8)}, // Start of line 1
{ui.Dp(33.6), 14, ui.Dp(33.6)}, // Start of line 2
{ui.Dp(50.4), 21, ui.Dp(50.4)}, // Start of line 3
{ui.Dp(0), 0, ui.Dp(0)}, // Top of document
{ui.Dp(16.8), 7, ui.Dp(16.8)}, // Start of line 1
{ui.Dp(33.6), 14, ui.Dp(33.6)}, // Start of line 2
{ui.Dp(50.4), 21, ui.Dp(50.4)}, // Start of line 3
}
for _, tc := range testCases {

View File

@ -202,4 +202,3 @@ func byteOffsetOfLine(content string, i int) int {
}
return o
}

View File

@ -53,13 +53,13 @@ func (t *cancelTask) Execute() Result {
}
}
func (t *cancelTask) Priority() Priority { return t.priority }
func (t *cancelTask) TaskID() string { return t.id }
func (t *cancelTask) TaskType() TaskType { return t.taskType }
func (t *cancelTask) DirPath() string { return "/test" }
func (t *cancelTask) Priority() Priority { return t.priority }
func (t *cancelTask) TaskID() string { return t.id }
func (t *cancelTask) TaskType() TaskType { return t.taskType }
func (t *cancelTask) DirPath() string { return "/test" }
func (t *cancelTask) Context() context.Context { return t.ctx }
func (t *cancelTask) Cancel() { t.cancel() }
func (t *cancelTask) Timeout() time.Duration { return 0 }
func (t *cancelTask) Cancel() { t.cancel() }
func (t *cancelTask) Timeout() time.Duration { return 0 }
// timeoutTask is a task that respects timeout.
type timeoutTask struct {
@ -79,13 +79,13 @@ func (t *timeoutTask) Execute() Result {
}
}
func (t *timeoutTask) Priority() Priority { return t.priority }
func (t *timeoutTask) TaskID() string { return t.id }
func (t *timeoutTask) TaskType() TaskType { return t.taskType }
func (t *timeoutTask) DirPath() string { return "/test" }
func (t *timeoutTask) Priority() Priority { return t.priority }
func (t *timeoutTask) TaskID() string { return t.id }
func (t *timeoutTask) TaskType() TaskType { return t.taskType }
func (t *timeoutTask) DirPath() string { return "/test" }
func (t *timeoutTask) Context() context.Context { return context.Background() }
func (t *timeoutTask) Cancel() {}
func (t *timeoutTask) Timeout() time.Duration { return 50 * time.Millisecond }
func (t *timeoutTask) Cancel() {}
func (t *timeoutTask) Timeout() time.Duration { return 50 * time.Millisecond }
func TestTaskContextCancellation(t *testing.T) {
task := newCancelTask("test-cancel", 1*time.Second)

View File

@ -68,10 +68,10 @@ type notifyEvent struct {
// FileSystem is a thread-safe in-memory filesystem for testing.
type FileSystem struct {
mu sync.RWMutex
files map[string]*File // path -> file
delay time.Duration // uniform delay applied to all operations
changes chan FileChangeEvent // async change notifications (nil = no notifications)
writeError bool // Added to simulate write errors
files map[string]*File // path -> file
delay time.Duration // uniform delay applied to all operations
changes chan FileChangeEvent // async change notifications (nil = no notifications)
writeError bool // Added to simulate write errors
}
// NewFileSystem creates an empty mock filesystem.

View File

@ -115,8 +115,6 @@ func (t TaskType) String() string {
}
}
// --- Specific Task Implementations ---
// ReadChunkTask reads a specific chunk of a file.
@ -163,13 +161,17 @@ func (t *ReadChunkTask) Execute() Result {
}
}
func (t *ReadChunkTask) Priority() Priority { return HighPriority }
func (t *ReadChunkTask) TaskType() TaskType { return TypeReadChunk }
func (t *ReadChunkTask) TaskID() string { return t.taskID }
func (t *ReadChunkTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *ReadChunkTask) Priority() Priority { return HighPriority }
func (t *ReadChunkTask) TaskType() TaskType { return TypeReadChunk }
func (t *ReadChunkTask) TaskID() string { return t.taskID }
func (t *ReadChunkTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *ReadChunkTask) Context() context.Context { return t.ctx }
func (t *ReadChunkTask) Timeout() time.Duration { return 5 * time.Second }
func (t *ReadChunkTask) Cancel() { if t.cancel != nil { t.cancel() } }
func (t *ReadChunkTask) Timeout() time.Duration { return 5 * time.Second }
func (t *ReadChunkTask) Cancel() {
if t.cancel != nil {
t.cancel()
}
}
// StatFileTask retrieves file metadata (like size and modification time).
// The plan indicates this replaces the full-file ReadFileTask for opening.
@ -210,13 +212,17 @@ func (t *StatFileTask) Execute() Result {
}
}
func (t *StatFileTask) Priority() Priority { return MediumPriority }
func (t *StatFileTask) TaskType() TaskType { return TypeStatFile }
func (t *StatFileTask) TaskID() string { return t.taskID }
func (t *StatFileTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *StatFileTask) Priority() Priority { return MediumPriority }
func (t *StatFileTask) TaskType() TaskType { return TypeStatFile }
func (t *StatFileTask) TaskID() string { return t.taskID }
func (t *StatFileTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *StatFileTask) Context() context.Context { return t.ctx }
func (t *StatFileTask) Timeout() time.Duration { return 5 * time.Second }
func (t *StatFileTask) Cancel() { if t.cancel != nil { t.cancel() } }
func (t *StatFileTask) Timeout() time.Duration { return 5 * time.Second }
func (t *StatFileTask) Cancel() {
if t.cancel != nil {
t.cancel()
}
}
// FileStat holds file metadata.
type FileStat struct {
@ -267,13 +273,17 @@ func (t *BuildLineIndexTask) Execute() Result {
}
}
func (t *BuildLineIndexTask) Priority() Priority { return LowPriority }
func (t *BuildLineIndexTask) TaskType() TaskType { return TypeBuildLineIndex }
func (t *BuildLineIndexTask) TaskID() string { return t.taskID }
func (t *BuildLineIndexTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *BuildLineIndexTask) Priority() Priority { return LowPriority }
func (t *BuildLineIndexTask) TaskType() TaskType { return TypeBuildLineIndex }
func (t *BuildLineIndexTask) TaskID() string { return t.taskID }
func (t *BuildLineIndexTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *BuildLineIndexTask) Context() context.Context { return t.ctx }
func (t *BuildLineIndexTask) Timeout() time.Duration { return 30 * time.Second }
func (t *BuildLineIndexTask) Cancel() { if t.cancel != nil { t.cancel() } }
func (t *BuildLineIndexTask) Timeout() time.Duration { return 30 * time.Second }
func (t *BuildLineIndexTask) Cancel() {
if t.cancel != nil {
t.cancel()
}
}
// BuildIndexTask builds the directory index for the browser.
type BuildIndexTask struct {
@ -304,13 +314,17 @@ func (t *BuildIndexTask) Execute() Result {
return Result{TaskID: t.taskID, TaskType: TypeBuildIndex, Success: true, Data: entries}
}
func (t *BuildIndexTask) Priority() Priority { return HighPriority }
func (t *BuildIndexTask) TaskType() TaskType { return TypeBuildIndex }
func (t *BuildIndexTask) TaskID() string { return t.taskID }
func (t *BuildIndexTask) DirPath() string { return t.Dir }
func (t *BuildIndexTask) Priority() Priority { return HighPriority }
func (t *BuildIndexTask) TaskType() TaskType { return TypeBuildIndex }
func (t *BuildIndexTask) TaskID() string { return t.taskID }
func (t *BuildIndexTask) DirPath() string { return t.Dir }
func (t *BuildIndexTask) Context() context.Context { return t.ctx }
func (t *BuildIndexTask) Timeout() time.Duration { return 5 * time.Second }
func (t *BuildIndexTask) Cancel() { if t.cancel != nil { t.cancel() } }
func (t *BuildIndexTask) Timeout() time.Duration { return 5 * time.Second }
func (t *BuildIndexTask) Cancel() {
if t.cancel != nil {
t.cancel()
}
}
// LoadPagesTask loads specific pages from a directory index.
type LoadPagesTask struct {
@ -343,13 +357,17 @@ func (t *LoadPagesTask) Execute() Result {
return Result{TaskID: t.taskID, TaskType: TypeLoadPages, Success: true, Data: t.PageIdxs}
}
func (t *LoadPagesTask) Priority() Priority { return HighPriority }
func (t *LoadPagesTask) TaskType() TaskType { return TypeLoadPages }
func (t *LoadPagesTask) TaskID() string { return t.taskID }
func (t *LoadPagesTask) DirPath() string { return t.Dir }
func (t *LoadPagesTask) Priority() Priority { return HighPriority }
func (t *LoadPagesTask) TaskType() TaskType { return TypeLoadPages }
func (t *LoadPagesTask) TaskID() string { return t.taskID }
func (t *LoadPagesTask) DirPath() string { return t.Dir }
func (t *LoadPagesTask) Context() context.Context { return t.ctx }
func (t *LoadPagesTask) Timeout() time.Duration { return 5 * time.Second }
func (t *LoadPagesTask) Cancel() { if t.cancel != nil { t.cancel() } }
func (t *LoadPagesTask) Timeout() time.Duration { return 5 * time.Second }
func (t *LoadPagesTask) Cancel() {
if t.cancel != nil {
t.cancel()
}
}
// ReadDirTask reads directory entries.
type ReadDirTask struct {
@ -381,13 +399,17 @@ func (t *ReadDirTask) Execute() Result {
return Result{TaskID: t.taskID, TaskType: TypeReadDir, Success: true, Data: entries}
}
func (t *ReadDirTask) Priority() Priority { return HighPriority }
func (t *ReadDirTask) TaskType() TaskType { return TypeReadDir }
func (t *ReadDirTask) TaskID() string { return t.taskID }
func (t *ReadDirTask) DirPath() string { return t.Dir }
func (t *ReadDirTask) Priority() Priority { return HighPriority }
func (t *ReadDirTask) TaskType() TaskType { return TypeReadDir }
func (t *ReadDirTask) TaskID() string { return t.taskID }
func (t *ReadDirTask) DirPath() string { return t.Dir }
func (t *ReadDirTask) Context() context.Context { return t.ctx }
func (t *ReadDirTask) Timeout() time.Duration { return 5 * time.Second }
func (t *ReadDirTask) Cancel() { if t.cancel != nil { t.cancel() } }
func (t *ReadDirTask) Timeout() time.Duration { return 5 * time.Second }
func (t *ReadDirTask) Cancel() {
if t.cancel != nil {
t.cancel()
}
}
// SaveStateTask persists application state.
type SaveStateTask struct {
@ -421,13 +443,17 @@ func (t *SaveStateTask) Execute() Result {
return Result{TaskID: t.taskID, TaskType: TypeSaveState, Success: true}
}
func (t *SaveStateTask) Priority() Priority { return LowPriority }
func (t *SaveStateTask) TaskType() TaskType { return TypeSaveState }
func (t *SaveStateTask) TaskID() string { return t.taskID }
func (t *SaveStateTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *SaveStateTask) Priority() Priority { return LowPriority }
func (t *SaveStateTask) TaskType() TaskType { return TypeSaveState }
func (t *SaveStateTask) TaskID() string { return t.taskID }
func (t *SaveStateTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *SaveStateTask) Context() context.Context { return t.ctx }
func (t *SaveStateTask) Timeout() time.Duration { return 5 * time.Second }
func (t *SaveStateTask) Cancel() { if t.cancel != nil { t.cancel() } }
func (t *SaveStateTask) Timeout() time.Duration { return 5 * time.Second }
func (t *SaveStateTask) Cancel() {
if t.cancel != nil {
t.cancel()
}
}
// SaveUndoTask persists undo stack.
type SaveUndoTask struct {
@ -461,13 +487,17 @@ func (t *SaveUndoTask) Execute() Result {
return Result{TaskID: t.taskID, TaskType: TypeSaveUndo, Success: true}
}
func (t *SaveUndoTask) Priority() Priority { return LowPriority }
func (t *SaveUndoTask) TaskType() TaskType { return TypeSaveUndo }
func (t *SaveUndoTask) TaskID() string { return t.taskID }
func (t *SaveUndoTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *SaveUndoTask) Priority() Priority { return LowPriority }
func (t *SaveUndoTask) TaskType() TaskType { return TypeSaveUndo }
func (t *SaveUndoTask) TaskID() string { return t.taskID }
func (t *SaveUndoTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *SaveUndoTask) Context() context.Context { return t.ctx }
func (t *SaveUndoTask) Timeout() time.Duration { return 5 * time.Second }
func (t *SaveUndoTask) Cancel() { if t.cancel != nil { t.cancel() } }
func (t *SaveUndoTask) Timeout() time.Duration { return 5 * time.Second }
func (t *SaveUndoTask) Cancel() {
if t.cancel != nil {
t.cancel()
}
}
// ReadFileTask reads the full content of a file.
// Used as a fallback for small files or initial load before chunking is set up.
@ -499,13 +529,17 @@ func (t *ReadFileTask) Execute() Result {
return Result{TaskID: t.taskID, TaskType: TypeReadFile, FilePath: t.Path, Success: true, Data: content}
}
func (t *ReadFileTask) Priority() Priority { return HighPriority }
func (t *ReadFileTask) TaskType() TaskType { return TypeReadFile }
func (t *ReadFileTask) TaskID() string { return t.taskID }
func (t *ReadFileTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *ReadFileTask) Priority() Priority { return HighPriority }
func (t *ReadFileTask) TaskType() TaskType { return TypeReadFile }
func (t *ReadFileTask) TaskID() string { return t.taskID }
func (t *ReadFileTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *ReadFileTask) Context() context.Context { return t.ctx }
func (t *ReadFileTask) Timeout() time.Duration { return 5 * time.Second }
func (t *ReadFileTask) Cancel() { if t.cancel != nil { t.cancel() } }
func (t *ReadFileTask) Timeout() time.Duration { return 5 * time.Second }
func (t *ReadFileTask) Cancel() {
if t.cancel != nil {
t.cancel()
}
}
// SearchData is the payload of a completed SearchTask: the byte ranges
// [start, end) of every match of Query in the scanned Text, ascending and
@ -587,13 +621,17 @@ func toLowerFold(s string) string {
// unit; it is the standard library's two-way search.
func indexOf(s, sub string) int { return strings.Index(s, sub) }
func (t *SearchTask) Priority() Priority { return MediumPriority }
func (t *SearchTask) TaskType() TaskType { return TypeSearch }
func (t *SearchTask) TaskID() string { return t.taskID }
func (t *SearchTask) DirPath() string { return "" }
func (t *SearchTask) Context() context.Context { return t.ctx }
func (t *SearchTask) Timeout() time.Duration { return 10 * time.Second }
func (t *SearchTask) Cancel() { if t.cancel != nil { t.cancel() } }
func (t *SearchTask) Priority() Priority { return MediumPriority }
func (t *SearchTask) TaskType() TaskType { return TypeSearch }
func (t *SearchTask) TaskID() string { return t.taskID }
func (t *SearchTask) DirPath() string { return "" }
func (t *SearchTask) Context() context.Context { return t.ctx }
func (t *SearchTask) Timeout() time.Duration { return 10 * time.Second }
func (t *SearchTask) Cancel() {
if t.cancel != nil {
t.cancel()
}
}
// WriteFileTask writes content to a file.
type WriteFileTask struct {
@ -626,13 +664,17 @@ func (t *WriteFileTask) Execute() Result {
return Result{TaskID: t.taskID, TaskType: TypeWriteFile, FilePath: t.Path, Success: true}
}
func (t *WriteFileTask) Priority() Priority { return LowPriority }
func (t *WriteFileTask) TaskType() TaskType { return TypeWriteFile }
func (t *WriteFileTask) TaskID() string { return t.taskID }
func (t *WriteFileTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *WriteFileTask) Priority() Priority { return LowPriority }
func (t *WriteFileTask) TaskType() TaskType { return TypeWriteFile }
func (t *WriteFileTask) TaskID() string { return t.taskID }
func (t *WriteFileTask) DirPath() string { return filepath.Dir(t.Path) }
func (t *WriteFileTask) Context() context.Context { return t.ctx }
func (t *WriteFileTask) Timeout() time.Duration { return 5 * time.Second }
func (t *WriteFileTask) Cancel() { if t.cancel != nil { t.cancel() } }
func (t *WriteFileTask) Timeout() time.Duration { return 5 * time.Second }
func (t *WriteFileTask) Cancel() {
if t.cancel != nil {
t.cancel()
}
}
// --- Mock File System (for testing/development) ---
// MockFS implements the pool.FileSystem interface for testing.
@ -709,12 +751,12 @@ type mockFileInfo struct {
modTime time.Time
}
func (f *mockFileInfo) Name() string { return f.name }
func (f *mockFileInfo) Size() int64 { return f.size }
func (f *mockFileInfo) Mode() os.FileMode { return os.FileMode(f.mode) }
func (f *mockFileInfo) ModTime() time.Time { return f.modTime }
func (f *mockFileInfo) IsDir() bool { return false }
func (f *mockFileInfo) Sys() any { return nil }
func (f *mockFileInfo) Name() string { return f.name }
func (f *mockFileInfo) Size() int64 { return f.size }
func (f *mockFileInfo) Mode() os.FileMode { return os.FileMode(f.mode) }
func (f *mockFileInfo) ModTime() time.Time { return f.modTime }
func (f *mockFileInfo) IsDir() bool { return false }
func (f *mockFileInfo) Sys() any { return nil }
// mockDirEntry implements types.DirEntry for MockFS ReadDir.
type mockDirEntry struct {
@ -722,8 +764,8 @@ type mockDirEntry struct {
isDir bool
}
func (e *mockDirEntry) Name() string { return e.name }
func (e *mockDirEntry) IsDir() bool { return e.isDir }
func (e *mockDirEntry) Name() string { return e.name }
func (e *mockDirEntry) IsDir() bool { return e.isDir }
func (e *mockDirEntry) Info() (os.FileInfo, error) {
return &mockFileInfo{name: e.name, size: 0}, nil
}
@ -739,6 +781,3 @@ func (m *MockFS) ReadDir(path string) ([]types.DirEntry, error) {
}
var _ FileSystem = (*MockFS)(nil) // Compile-time interface check

View File

@ -73,18 +73,18 @@ func (li *LineIndex) FindLogicalLineForByteOffset(byteOffset int) int {
low, high := 0, len(li.Offsets)-1
for low <= high {
mid := (low + high) / 2
midOffset := int(li.Offsets[mid])
midOffset := int(li.Offsets[mid])
if byteOffset >= midOffset {
// This line starts at or before our byte offset
// Check if the next line starts after our byte offset
if mid == len(li.Offsets)-1 || int(li.Offsets[mid+1]) > byteOffset {
return mid // Found the line
}
low = mid + 1
} else {
high = mid - 1
if byteOffset >= midOffset {
// This line starts at or before our byte offset
// Check if the next line starts after our byte offset
if mid == len(li.Offsets)-1 || int(li.Offsets[mid+1]) > byteOffset {
return mid // Found the line
}
low = mid + 1
} else {
high = mid - 1
}
}
return -1 // Not found

View File

@ -13,15 +13,15 @@ import (
// - Workers execute tasks and post results on resultChan
// - Workers never access state directly
type WorkerPool struct {
highWorkChan chan Task
lowWorkChan chan Task
resultChan chan Result
workerCount int
stopOnce sync.Once
stopChan chan struct{}
wg sync.WaitGroup
taskCounter atomic.Int64
running atomic.Bool
highWorkChan chan Task
lowWorkChan chan Task
resultChan chan Result
workerCount int
stopOnce sync.Once
stopChan chan struct{}
wg sync.WaitGroup
taskCounter atomic.Int64
running atomic.Bool
// pendingTasks tracks in-flight tasks for cancellation by directory.
pendingTasks map[string][]Task

View File

@ -42,13 +42,13 @@ func (t *stubTask) Execute() Result {
}
}
func (t *stubTask) Priority() Priority { return t.priority }
func (t *stubTask) TaskID() string { return t.id }
func (t *stubTask) TaskType() TaskType { return t.taskType }
func (t *stubTask) DirPath() string { return "" }
func (t *stubTask) Priority() Priority { return t.priority }
func (t *stubTask) TaskID() string { return t.id }
func (t *stubTask) TaskType() TaskType { return t.taskType }
func (t *stubTask) DirPath() string { return "" }
func (t *stubTask) Context() context.Context { return context.Background() }
func (t *stubTask) Cancel() {}
func (t *stubTask) Timeout() time.Duration { return 5 * time.Second }
func (t *stubTask) Cancel() {}
func (t *stubTask) Timeout() time.Duration { return 5 * time.Second }
func TestWorkerPool_StartStop(t *testing.T) {
pool := NewWorkerPool(4)
@ -672,9 +672,9 @@ func TestWorkerPool_ResultIsSuccess(t *testing.T) {
}
result2 := Result{
TaskID: "test",
TaskID: "test",
Success: false,
Error: fmt.Errorf("error"),
Error: fmt.Errorf("error"),
}
if result2.IsSuccess() {
t.Error("Result should not be successful")
@ -683,7 +683,7 @@ func TestWorkerPool_ResultIsSuccess(t *testing.T) {
func TestWorkerPool_ResultIsError(t *testing.T) {
result := Result{
TaskID: "test",
TaskID: "test",
Success: false,
Error: fmt.Errorf("error"),
}

View File

@ -14,7 +14,7 @@ type TestScenario struct {
Setup func(*Harness)
Actions []HarnessAction
Assertions []FrameAssertion
FrameIndex int // which frame to assert on (-1 for last)
FrameIndex int // which frame to assert on (-1 for last)
Timeout time.Duration
}

View File

@ -646,7 +646,7 @@ func TestRestore_LinePinHoldsAcrossLateWrapFeedback(t *testing.T) {
File: "/wrap.txt",
Cursor: 0,
Scroll: float64(ui.Dp(500 * lh)), // the saving session's visual-space offset
ScrollLine: 200, // the logical line at the viewport top
ScrollLine: 200, // the logical line at the viewport top
ScrollSub: 0,
}

View File

@ -2,14 +2,14 @@ package ui
const (
// Standard dimensions in Dp
StatusBarLineHeight = Dp(24)
StatusBarLineHeight = Dp(24)
StatusBarFilenameLine = Dp(24)
StatusBarIconsLine = Dp(24)
BottomBarHeight = Dp(24)
IconSize = Dp(24)
IconGap = Dp(36)
Padding = Dp(8)
ButtonPadding = Dp(8)
StatusBarIconsLine = Dp(24)
BottomBarHeight = Dp(24)
IconSize = Dp(24)
IconGap = Dp(36)
Padding = Dp(8)
ButtonPadding = Dp(8)
)
// LineHeightScale is the baseline-to-baseline spacing multiplier for editor text.