Minga.Project.FileTree (Minga v0.1.0)

Copy Markdown View Source

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

Types

A single visible entry in the tree.

t()

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

entry()

@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.

t()

@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

collapse(tree)

@spec collapse(t()) :: t()

Collapses the directory at cursor, or if on a file/collapsed dir, collapses the parent.

collapse_all(tree)

@spec collapse_all(t()) :: t()

Collapses all directories, keeping only the root expanded. Resets cursor to 0.

ensure_entries(tree)

@spec ensure_entries(t()) :: t()

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.

expand(tree)

@spec expand(t()) :: t()

Expands the directory at cursor. No-op on files or already-expanded dirs.

move_down(tree)

@spec move_down(t()) :: t()

Moves the cursor down by one entry, clamped to the last visible entry.

move_up(tree)

@spec move_up(t()) :: t()

Moves the cursor up by one entry.

new(root, opts \\ [])

@spec new(
  String.t(),
  keyword()
) :: t()

Creates a new file tree rooted at the given directory path.

refresh(tree)

@spec refresh(t()) :: t()

Refreshes the tree by rescanning the filesystem (clamps cursor).

refresh_git_status(tree)

@spec refresh_git_status(t()) :: t()

Refreshes git status for the tree root. Returns the updated tree.

reveal(tree, file_path)

@spec reveal(t(), String.t()) :: t()

Highlights the given file path in the tree by expanding its parent directories and moving the cursor to it.

selected_entry(tree)

@spec selected_entry(t()) :: entry() | nil

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.

toggle_expand(tree)

@spec toggle_expand(t()) :: t()

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.

toggle_hidden(tree)

@spec toggle_hidden(t()) :: t()

Toggles visibility of hidden files (dotfiles).

visible_entries(tree)

@spec visible_entries(t()) :: [entry()]

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.