Pure data structure for a navigable filesystem tree.
Holds the root path, a set of expanded directories, a cursor position, and a show_hidden toggle. The flat list of visible entries is cached in the struct after the first computation and invalidated whenever tree state changes (expand, collapse, toggle_hidden, refresh, reveal).
No GenServer; the editor owns this struct in its state.
Summary
Functions
Collapses the directory at cursor, or if on a file/collapsed dir, collapses the parent.
Collapses all directories, keeping only the root expanded. Resets cursor to 0.
Returns the tree with entries guaranteed to be populated.
Expands the directory at cursor. No-op on files or already-expanded dirs.
Moves the cursor down by one entry, clamped to the last visible entry.
Moves the cursor up by one entry.
Creates a new file tree rooted at the given directory path.
Refreshes the tree by rescanning the filesystem (clamps cursor).
Refreshes git status for the tree root. Returns the updated tree.
Highlights the given file path in the tree by expanding its parent directories and moving the cursor to it.
Returns the entry at the current cursor position, or nil if empty.
Toggles expand/collapse for the entry at the cursor.
Toggles visibility of hidden files (dotfiles).
Returns the flat list of currently visible entries.
Types
@type entry() :: %{ path: String.t(), name: String.t(), dir?: boolean(), depth: non_neg_integer(), last_child?: boolean(), guides: [boolean()] }
A single visible entry in the tree.
The guides field is a list of booleans, one per ancestor depth level
(index 0 = depth 0, index 1 = depth 1, etc.). true means the ancestor
at that depth has more siblings below this entry (draw │), false
means it was the last child (draw blank). The renderer uses this plus
last_child? to pick ├── vs └── at the entry's own depth.
@type t() :: %Minga.Project.FileTree{ cursor: non_neg_integer(), entries: [entry()] | nil, expanded: MapSet.t(String.t()), git_status: Minga.Project.FileTree.GitStatus.status_map(), root: String.t(), show_hidden: boolean(), width: pos_integer() }
Functions
Collapses the directory at cursor, or if on a file/collapsed dir, collapses the parent.
Collapses all directories, keeping only the root expanded. Resets cursor to 0.
Returns the tree with entries guaranteed to be populated.
If entries are already cached, returns the tree unchanged. Otherwise computes entries from the filesystem and caches them. Use this when you need to read entries multiple times from the same tree without redundant filesystem walks.
Expands the directory at cursor. No-op on files or already-expanded dirs.
Moves the cursor down by one entry, clamped to the last visible entry.
Moves the cursor up by one entry.
Creates a new file tree rooted at the given directory path.
Refreshes the tree by rescanning the filesystem (clamps cursor).
Refreshes git status for the tree root. Returns the updated tree.
Highlights the given file path in the tree by expanding its parent directories and moving the cursor to it.
Returns the entry at the current cursor position, or nil if empty.
This reads from the cached entries if available. For performance-sensitive
callers that will call this repeatedly, call ensure_entries/1 first to
populate the cache; subsequent calls on the same struct will use it.
Toggles expand/collapse for the entry at the cursor.
If the cursor is on a directory, toggles its expanded state. If on a file, this is a no-op.
Returns the flat list of currently visible entries.
Returns cached entries if available. Otherwise walks the directory tree
starting from root, descending into expanded directories. Results are
sorted: directories first, then files, both alphabetically. Hidden
files are excluded unless show_hidden is true.
Note: this returns only the list, not the updated struct. If the cache
was empty, the computed entries are not stored back in the struct.
Callers that need repeated access should call ensure_entries/1 first
to populate the cache, then read .entries or call this function on
the returned struct.