Minga.Project (Minga v0.1.0)

Copy Markdown View Source

Owns the active explicit directory workspace and its project services.

Tracks the current workspace root, caches the file list, and persists a known-projects list to ~/.config/minga/known-projects so that SPC p p works across editor sessions.

State

  • workspace — one atomic typed root, relative file inventory, and rebuild status
  • known_projects — list of all project roots the user has visited, persisted to disk
  • recent_files — per-project list of recently opened files, most recent first, persisted to disk
  • command_frecency — command execution timestamps used to rank the empty command palette
  • rebuild PID, monitor, and timer fields — operational discovery lifecycle state

File cache

The cached file list lives in GenServer state (not ETS). Only one consumer (the picker, running inside the Editor process) reads it at a time, so a GenServer is simpler and sufficient. Cache rebuilds run in a supervised Task to keep the GenServer responsive during the shell-out to fd or git ls-files.

Summary

Types

Per-command execution event history (most recent first, unix seconds).

Per-file access event history (most recent first, unix seconds).

Per-project frecency map: project root => %{relative_path => access_timestamps}.

Per-project recent files map: project root => list of relative paths (most recent first).

t()

Project GenServer state.

Functions

Synchronously installs an authorized directory workspace and starts discovery.

Adds a directory as a known project.

Finds alternate files (test <> implementation) for the given file.

Returns a specification to start this module under a supervisor.

Closes the active directory workspace and cancels file discovery.

Replaces the home directory prefix with ~ for display.

Returns the raw command frecency map (command name => timestamp list).

Returns frecency scores for command palette commands (command name => score).

Detects the test runner for a project.

Expands a leading ~ to the home directory without normalizing the rest of the path.

Returns the cached file list for the current project.

Returns frecency scores for files in the current project (relative path => score).

Invalidates the file cache and triggers a rebuild.

Returns the list of known project roots.

Lists all files under an explicit directory workspace root.

Returns true while a background file-cache rebuild is in progress.

Returns the list of recently opened files for the current project (relative paths, most recent first).

Records a command execution for command palette frecency ranking.

Records a file as recently opened in the current project.

Records a workspace-relative file under its captured project root.

Removes a project from the known-projects list.

Returns the active project root without inventing a cwd fallback.

Returns the current project root, or nil if none is detected.

Scores a file's access timestamps using frecency decay buckets.

Atomically returns the active typed workspace and its cached inventory state.

Starts the project GenServer.

Switches to an explicit directory workspace, triggering one cache rebuild.

Generates a command to run all tests.

Generates a command to run test at cursor position.

Generates a command to run tests in a file.

Returns the explicit directory workspace root used by recursive project features.

Types

command_frecency_map()

@type command_frecency_map() :: %{required(atom()) => [non_neg_integer()]}

Per-command execution event history (most recent first, unix seconds).

file_accesses_map()

@type file_accesses_map() :: %{required(String.t()) => [non_neg_integer()]}

Per-file access event history (most recent first, unix seconds).

frecency_events_map()

@type frecency_events_map() :: %{required(String.t()) => file_accesses_map()}

Per-project frecency map: project root => %{relative_path => access_timestamps}.

recent_files_map()

@type recent_files_map() :: %{required(String.t()) => [String.t()]}

Per-project recent files map: project root => list of relative paths (most recent first).

t()

@type t() :: %Minga.Project{
  command_frecency: command_frecency_map(),
  events_registry: Minga.Events.registry(),
  file_find_module: module(),
  frecency_events: frecency_events_map(),
  known_projects: [String.t()],
  rebuild_pid: pid() | nil,
  rebuild_ref: reference() | nil,
  rebuild_timeout_ms: pos_integer(),
  rebuild_timer_ref: reference() | nil,
  recent_files: recent_files_map(),
  workspace: Minga.Project.WorkspaceSnapshot.t() | nil
}

Project GenServer state.

Functions

activate(root)

Synchronously installs an authorized directory workspace and starts discovery.

The returned snapshot is installed before this call returns. File discovery continues asynchronously and later replaces the inventory in one atomic snapshot transition.

activate(server, root)

add(server \\ __MODULE__, root_path)

@spec add(GenServer.server(), String.t()) :: :ok

Adds a directory as a known project.

alternate_candidates(file_path, filetype, project_root)

@spec alternate_candidates(String.t(), atom(), String.t()) :: [String.t()]

Finds alternate files (test <> implementation) for the given file.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

close(server \\ __MODULE__)

@spec close(GenServer.server()) :: :ok

Closes the active directory workspace and cancels file discovery.

collapse_home(path)

@spec collapse_home(String.t()) :: String.t()

Replaces the home directory prefix with ~ for display.

Handles both $HOME/... paths and $HOME exactly.

command_frecency(server \\ __MODULE__)

@spec command_frecency(GenServer.server()) :: command_frecency_map()

Returns the raw command frecency map (command name => timestamp list).

command_frecency_scores(server \\ __MODULE__)

@spec command_frecency_scores(GenServer.server()) :: %{
  required(atom()) => non_neg_integer()
}

Returns frecency scores for command palette commands (command name => score).

detect_test_runner(filetype, project_root)

@spec detect_test_runner(atom(), String.t()) ::
  {:ok, Minga.Project.TestRunner.Runner.t()} | :none

Detects the test runner for a project.

expand_home(path)

@spec expand_home(String.t()) :: String.t()

Expands a leading ~ to the home directory without normalizing the rest of the path.

files(server \\ __MODULE__)

@spec files(GenServer.server()) :: [String.t()]

Returns the cached file list for the current project.

frecency_scores(server \\ __MODULE__)

@spec frecency_scores(GenServer.server()) :: %{
  required(String.t()) => non_neg_integer()
}

Returns frecency scores for files in the current project (relative path => score).

invalidate(server \\ __MODULE__)

@spec invalidate(GenServer.server()) :: :ok

Invalidates the file cache and triggers a rebuild.

known_projects(server \\ __MODULE__)

@spec known_projects(GenServer.server()) :: [String.t()]

Returns the list of known project roots.

list_files(root)

@spec list_files(Minga.Project.Root.t()) :: {:ok, [String.t()]} | {:error, String.t()}

Lists all files under an explicit directory workspace root.

rebuilding?(server \\ __MODULE__)

@spec rebuilding?(GenServer.server()) :: boolean()

Returns true while a background file-cache rebuild is in progress.

recent_files(server \\ __MODULE__)

@spec recent_files(GenServer.server()) :: [String.t()]

Returns the list of recently opened files for the current project (relative paths, most recent first).

record_command(server \\ __MODULE__, command_name)

@spec record_command(GenServer.server(), atom()) :: :ok

Records a command execution for command palette frecency ranking.

record_file(server \\ __MODULE__, file_path)

@spec record_file(GenServer.server(), String.t()) :: :ok

Records a file as recently opened in the current project.

The file path should be absolute. It is stored relative to the project root. Most recent files appear first. Duplicates are moved to the front. No-op if no project root is set or the file is outside the current project.

record_file_for_root(server \\ __MODULE__, root, relative_path)

@spec record_file_for_root(GenServer.server(), Minga.Project.Root.t(), String.t()) ::
  :ok

Records a workspace-relative file under its captured project root.

Unlike record_file/2, this does not consult the active workspace. The path is re-authorized through the supplied root before that project's recent-file and frecency history is updated.

remove(server \\ __MODULE__, root_path)

@spec remove(GenServer.server(), String.t()) :: :ok

Removes a project from the known-projects list.

resolve_root()

@spec resolve_root() :: String.t() | nil

Returns the active project root without inventing a cwd fallback.

root(server \\ __MODULE__)

@spec root(GenServer.server()) :: String.t() | nil

Returns the current project root, or nil if none is detected.

score_accesses(timestamps, now_unix)

@spec score_accesses([non_neg_integer()], non_neg_integer()) :: non_neg_integer()

Scores a file's access timestamps using frecency decay buckets.

snapshot(server \\ __MODULE__)

Atomically returns the active typed workspace and its cached inventory state.

start_link(opts \\ [])

@spec start_link(keyword()) :: GenServer.on_start()

Starts the project GenServer.

switch(root)

@spec switch(String.t() | Minga.Project.Root.t()) :: :ok

Switches to an explicit directory workspace, triggering one cache rebuild.

switch(root_path, opts)

@spec switch(
  String.t(),
  keyword()
) :: :ok
@spec switch(GenServer.server(), String.t() | Minga.Project.Root.t()) :: :ok

switch(server, root, opts)

@spec switch(GenServer.server(), String.t() | Minga.Project.Root.t(), keyword()) ::
  :ok

test_all_command(runner)

@spec test_all_command(Minga.Project.TestRunner.Runner.t()) :: String.t()

Generates a command to run all tests.

test_at_point_command(runner, path, line)

@spec test_at_point_command(
  Minga.Project.TestRunner.Runner.t(),
  String.t(),
  pos_integer()
) ::
  String.t() | nil

Generates a command to run test at cursor position.

test_file_command(runner, path)

@spec test_file_command(Minga.Project.TestRunner.Runner.t(), String.t()) ::
  String.t() | nil

Generates a command to run tests in a file.

workspace_root(server \\ __MODULE__)

@spec workspace_root(GenServer.server()) :: Minga.Project.Root.t() | nil

Returns the explicit directory workspace root used by recursive project features.