BufEdit v0.1.0 BufEdit View Source

Programmable buffer editor, similar in concept to ed.

BufEdit reads a file into memory and provides a flexible API for editing it and writing it back to a file.

Consider the following mix.exs file:

defmodule MyApp.MixProject do
  use Mix.Project

  def project do
    [
      app: :my_app,
      version: "0.1.0",
      elixir: "~> 1.6",
      start_permanent: Mix.env() == :prod,
      deps: deps()
    ]
  end

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      extra_applications: [:logger]
    ]
  end

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"},
    ]
  end
end

We’ll use BufEdit to load the file and jump to a line matching a regular expression:

iex> buf = BufEdit.load("mix.exs")
iex> buf = BufEdit.search(buf, ~r/defp deps/, :down)
%BufEdit{
  col: 1,
  filename: "test/fixtures/mix.exs",
  lines: ["defmodule MyApp.MixProject do", "  use Mix.Project", ""],
  line_num: 22,
  status: :ok
}

(The lines key value above has been abbreviated in this example)

If the line is found, the returned %BufEdit{} has a :status key set to :ok, and the :line_num key is set to the new line number.

Now, let’s say we want to remove the two comment lines from the dependencies list and add a new dependency:

iex> buf = BufEdit.search(buf, ~r/^ *#/, :down)
%BufEdit{
  col: 1,
  filename: "test/fixtures/mix.exs",
  lines: ["defmodule MyApp.MixProject do", "  use Mix.Project", ""],
  line_num: 24,
  status: :ok
}

Now, we’re at line 24. If you want to see line 24, use line/1:

iex> BufEdit.line(buf)
"      # {:dep_from_hexpm, \"~> 0.3.0\"},"

Yep, that’s the line we’re looking for.

The next step is to delete the two comments:

iex> buf = BufEdit.delete_lines(buf, 2)
%BufEdit{
  col: 1,
  filename: "test/fixtures/mix.exs",
  lines: ["defmodule MyApp.MixProject do", "  use Mix.Project", ""],
  line_num: 24,
  status: :ok
}
iex> BufEdit.line(buf)
"    ]"

Now that the lines are deleted, we’re ready to add the new dependency:

iex> buf = BufEdit.insert_line(buf, "      {:buffer, \"~> 0.1.0\"}")
iex> BufEdit.dump(buf) |> IO.puts()
defmodule MyApp.MixProject do
  use Mix.Project

  def project do
    [
      app: :my_app,
      version: "0.1.0",
      elixir: "~> 1.6",
      start_permanent: Mix.env() == :prod,
      deps: deps()
    ]
  end

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      extra_applications: [:logger]
    ]
  end

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      {:buffer, "~> 0.1.0"}
    ]
  end
end

Our new dependency is added! Now it’s time to write the file, then we’re done:

iex> BufEdit.save(buf)

Link to this section Summary

Functions

Delete the current line

Delete a number of lines from the current line number

Dump the BufEdit to a string

Insert a line at the current line number

Insert multiple lines at the current line number

Get the current line

Get a list of lines starting from the current line number

Load the file into the buffer

Move to a line offset from the current line

Move to the given line number and column

Move to the last line in the file

Replace a sub string within the current line matching pattern

Replace the current line with the output of a function

Save the BufEdit to a file specified by the :filename value

Search for a line using a regular expression

Link to this section Types

Link to this type t() View Source
t() :: %BufEdit{
  col: integer(),
  filename: String.t(),
  line_num: integer(),
  lines: [String.t()],
  status: atom()
}

Link to this section Functions

Link to this function delete_line(buf) View Source
delete_line(buf :: t()) :: t()

Delete the current line

Link to this function delete_lines(buf, count) View Source
delete_lines(buf :: t(), count :: integer()) :: t()

Delete a number of lines from the current line number

Dump the BufEdit to a string

Link to this function insert_line(buf, line) View Source
insert_line(buf :: t(), line :: String.t()) :: t()

Insert a line at the current line number.

Link to this function insert_lines(buf, lines) View Source
insert_lines(buf :: t(), lines :: [String.t()]) :: t()

Insert multiple lines at the current line number.

Get the current line.

Link to this function lines(buf, length) View Source
lines(buf :: t(), length :: integer()) :: [String.t()]

Get a list of lines starting from the current line number.

Link to this function load(filename) View Source
load(filename :: String.t()) :: t()

Load the file into the buffer

Link to this function move_relative(buf, line_num_offset, col_offset) View Source
move_relative(
  buf :: t(),
  line_num_offset :: integer(),
  col_offset :: integer()
) :: t()

Move to a line offset from the current line.

Link to this function move_to(buf, line_num, col) View Source
move_to(buf :: t(), line_num :: integer(), col :: integer()) :: t()

Move to the given line number and column

Link to this function move_to_end(buf) View Source
move_to_end(buf :: t()) :: t()

Move to the last line in the file.

Link to this function replace_in_line(buf, search, replace) View Source
replace_in_line(buf :: t(), search :: String.t(), replace :: String.t()) ::
  t()

Replace a sub string within the current line matching pattern.

Link to this function replace_line(buf, fun) View Source
replace_line(t(), (t(), line :: String.t() -> String.t())) :: t()

Replace the current line with the output of a function.

Example:

Commenting out a line of Elixir:

iex> BufEdit.replace_line(buf, fn _buf, line -> "# #{line}" end)

Save the BufEdit to a file specified by the :filename value.

Link to this function search(buf, pattern, direction \\ :down) View Source
search(buf :: t(), pattern :: Regex.t(), direction :: :down | :up) :: t()

Search for a line using a regular expression.