# `Minga.Core.Diff`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga/core/diff.ex#L1)

In-memory line diffing and hunk operations.

Uses `List.myers_difference/2` to compute line-level diffs between
two versions of text. Produces hunk structs consumed by git gutter
rendering, hunk navigation, AI diff review, and patch generation.

Pure computation with no side effects.

# `hunk`

```elixir
@type hunk() :: %{
  type: hunk_type(),
  start_line: non_neg_integer(),
  count: non_neg_integer(),
  old_start: non_neg_integer(),
  old_count: non_neg_integer(),
  old_lines: [String.t()]
}
```

A hunk represents a contiguous group of changed lines.

* `type` — the kind of change
* `start_line` — first buffer line affected (0-indexed)
* `count` — number of buffer lines in this hunk (0 for pure deletions)
* `old_start` — first line in the base content (0-indexed)
* `old_count` — number of base lines replaced/deleted
* `old_lines` — the original lines from base (for revert and preview)

# `hunk_type`

```elixir
@type hunk_type() :: :added | :modified | :deleted
```

A contiguous region of change.

* `:added` — new lines not in the base
* `:modified` — lines that differ from the base
* `:deleted` — lines removed from the base (rendered on the line above)

# `merge3_result`

```elixir
@type merge3_result() :: {:ok, [String.t()]} | {:conflict, [merge_hunk()]}
```

Result of a three-way merge.

# `merge_hunk`

```elixir
@type merge_hunk() ::
  {:resolved, [String.t()]} | {:conflict, [String.t()], [String.t()]}
```

A hunk in a three-way merge result.

* `{:resolved, lines}` — auto-merged content (from either side or unchanged)
* `{:conflict, fork_lines, parent_lines}` — both sides changed the same region

# `diff_lines`

```elixir
@spec diff_lines([String.t()], [String.t()]) :: [hunk()]
```

Diffs base lines against current lines and returns a list of hunks.

Both inputs should be lists of strings (one per line, without trailing newlines).

# `generate_patch`

```elixir
@spec generate_patch(String.t(), [String.t()], [String.t()], hunk()) :: String.t()
```

Generates a unified diff patch for a single hunk.

The patch can be fed to `git apply --cached` to stage just this hunk.
Uses the standard unified diff format with `a/` and `b/` path prefixes.

# `hunk_at_line`

```elixir
@spec hunk_at_line([hunk()], non_neg_integer()) :: hunk() | nil
```

Finds the hunk containing or nearest to the given buffer line.

# `merge3`

```elixir
@spec merge3([String.t()], [String.t()], [String.t()]) ::
  {:ok, [String.t()]} | {:conflict, [merge_hunk()]}
```

Three-way merge: given a common ancestor and two divergent versions (fork and parent),
produces a merged result or identifies conflicts.

Non-overlapping changes from both sides are merged automatically.
Overlapping changes (both sides modified the same region of the ancestor)
become conflicts.

Returns `{:ok, merged_lines}` when all changes merge cleanly, or
`{:conflict, merge_hunks}` when at least one conflict exists.
The hunks list contains both resolved and conflicting regions.

# `next_hunk_line`

```elixir
@spec next_hunk_line([hunk()], non_neg_integer()) :: non_neg_integer() | nil
```

Finds the start line of the next hunk after the given line.
Returns `nil` if no hunk follows.

# `prev_hunk_line`

```elixir
@spec prev_hunk_line([hunk()], non_neg_integer()) :: non_neg_integer() | nil
```

Finds the start line of the previous hunk before the given line.
Returns `nil` if no hunk precedes.

# `revert_hunk`

```elixir
@spec revert_hunk([String.t()], hunk()) :: [String.t()]
```

Returns buffer lines with the given hunk reverted to base content.

For added hunks: removes the added lines.
For modified hunks: replaces with the old lines.
For deleted hunks: re-inserts the old lines at the deletion point.

# `signs_for_hunks`

```elixir
@spec signs_for_hunks([hunk()]) :: %{required(non_neg_integer()) =&gt; hunk_type()}
```

Converts hunks to a per-line sign map for the gutter renderer.

Returns `%{line_number => :added | :modified | :deleted}`.
Deleted hunks are placed on the line above the deletion point
(or line 0 if deleted at the start).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
