Minga.Git.Buffer (Minga v0.1.0)

Copy Markdown View Source

Per-buffer GenServer that tracks git diff state.

Caches the HEAD version of the file on startup, then recomputes an in-memory diff (via Minga.Core.Diff) whenever the buffer content changes. This design means buffer edits never spawn git processes; only buffer open and git index invalidation do.

One Git.Buffer exists per file-backed buffer in a git repository. Managed under Minga.Buffer.Supervisor.

Summary

Types

Diff summary counts: {added, modified, deleted}.

Pre-computed data for the modeline: branch name and diff summary.

Options for starting a git buffer.

Internal state.

Functions

Returns a specification to start this module under a supervisor.

Returns the git root path.

Returns the hunk at a specific buffer line, or nil.

Returns the list of hunks.

Re-reads the HEAD version and recomputes the diff.

Returns {branch, {added, modified, deleted}} in a single GenServer call.

Returns the file path relative to git root.

Returns the per-line sign map for the gutter.

Starts a git buffer for a file in a git repository.

Returns a summary of diff sign counts: {added, modified, deleted}.

Recomputes the diff against the cached base content.

Types

diff_summary()

@type diff_summary() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}

Diff summary counts: {added, modified, deleted}.

modeline_info()

@type modeline_info() :: {branch :: String.t() | nil, diff_summary()}

Pre-computed data for the modeline: branch name and diff summary.

start_opt()

@type start_opt() ::
  {:git_root, String.t()}
  | {:file_path, String.t()}
  | {:initial_content, String.t()}

Options for starting a git buffer.

state()

@type state() :: %{
  git_root: String.t(),
  relative_path: String.t(),
  base_lines: [String.t()],
  hunks: [Minga.Core.Diff.hunk()],
  signs: %{required(non_neg_integer()) => Minga.Core.Diff.hunk_type()},
  branch: String.t() | nil
}

Internal state.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

git_root(server)

@spec git_root(GenServer.server()) :: String.t()

Returns the git root path.

hunk_at(server, line)

@spec hunk_at(GenServer.server(), non_neg_integer()) :: Minga.Core.Diff.hunk() | nil

Returns the hunk at a specific buffer line, or nil.

hunks(server)

@spec hunks(GenServer.server()) :: [Minga.Core.Diff.hunk()]

Returns the list of hunks.

invalidate_base(server, current_content)

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

Re-reads the HEAD version and recomputes the diff.

modeline_info(server)

@spec modeline_info(GenServer.server()) :: modeline_info()

Returns {branch, {added, modified, deleted}} in a single GenServer call.

The branch name is cached on state and refreshed on init and save (:invalidate_base), so this call does zero I/O.

relative_path(server)

@spec relative_path(GenServer.server()) :: String.t()

Returns the file path relative to git root.

signs(server)

@spec signs(GenServer.server()) :: %{
  required(non_neg_integer()) => Minga.Core.Diff.hunk_type()
}

Returns the per-line sign map for the gutter.

start_link(opts)

@spec start_link([start_opt()]) :: GenServer.on_start()

Starts a git buffer for a file in a git repository.

summary(server)

@spec summary(GenServer.server()) :: diff_summary()

Returns a summary of diff sign counts: {added, modified, deleted}.

Counts are derived from the per-line sign map, which is already computed on every buffer change. This is a cheap GenServer.call (no recomputation).

update(server, current_content)

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

Recomputes the diff against the cached base content.