ExQuality.Init.DepInstaller (ExQuality v0.5.0)

View Source

Adds dependencies to mix.exs programmatically.

Uses line-based insertion to preserve formatting and comments. Validates syntax after editing to ensure correctness.

Summary

Functions

Adds dependencies to mix.exs.

Builds dependency lines to insert.

Extracts indentation from a line.

Finds the line number where new deps should be inserted.

Inserts lines into content at the specified line number.

Functions

add_dependencies(versions)

@spec add_dependencies(%{required(atom()) => {atom(), String.t()}}) ::
  :ok | {:error, String.t()}

Adds dependencies to mix.exs.

Inserts new deps immediately after :ex_quality dependency (or at end of deps list). Creates a backup at mix.exs.backup before modifying.

Returns

  • :ok on success
  • {:error, reason} on failure

build_dep_lines(versions, indent)

@spec build_dep_lines(%{required(atom()) => {atom(), String.t()}}, String.t()) :: [
  String.t()
]

Builds dependency lines to insert.

Uses recommended installation options from each tool's documentation.

Format:

{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
{:dialyxir, "~> 1.4", only: [:dev], runtime: false},
{:excoveralls, "~> 0.18", only: :test},

extract_indent(line)

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

Extracts indentation from a line.

Examples

extract_indent("      {:credo, "~> 1.7"}")
#=> "      "

extract_indent("\t\t{:dialyxir, "~> 1.4"}")
#=> "\t\t"

find_insertion_point(content)

@spec find_insertion_point(String.t()) ::
  {:ok, non_neg_integer(), String.t()} | {:error, String.t()}

Finds the line number where new deps should be inserted.

Strategy

  1. Look for :ex_quality dependency line
  2. Insert immediately BEFORE it (so new deps have commas and ex_quality comma is optional)
  3. If not found, insert at end of deps function (before closing bracket)

Returns

  • {:ok, line_number, indentation_string} on success
  • {:error, reason} on failure

insert_lines(content, line_num, new_lines)

@spec insert_lines(String.t(), non_neg_integer(), [String.t()]) :: String.t()

Inserts lines into content at the specified line number.

Examples

insert_lines("line1\nline2\nline3", 2, ["new1", "new2"])
#=> "line1\nline2\nnew1\nnew2\nline3"