Minga.Editing.Motion (Minga v0.1.0)

Copy Markdown View Source

Pure cursor-motion functions for the Minga editor.

Each function takes a Readable.t() and a current position(), and returns the new position() after applying the motion. No buffer state is mutated — the caller is responsible for moving the buffer cursor via Document.move_to/2 or Buffer.Server.move_to/2.

This module is a facade over focused sub-modules:

  • Motion.Wordw/b/e/W/B/E word motions
  • Motion.Line0/$/^ line motions
  • Motion.Documentgg/G/{/} document & paragraph motions
  • Motion.Charf/F/t/T find-char and % bracket match

Word boundary rules

A word character is any alphanumeric character or underscore ([a-zA-Z0-9_]). This matches Vim's lowercase w/b/e motions. Whitespace (space, tab, newline) acts as word separator.

Line and document motions

FunctionVim keyDescription
line_start/20First column of the current line
line_end/2$Last column of the current line
first_non_blank/2^First non-whitespace column on the line
document_start/1ggFirst character of the buffer
document_end/1GLast character of the last line

Summary

Types

A zero-indexed {line, col} cursor position.

Functions

Move to the last character of the last line (like Vim's G).

Move to the very start of the buffer (like Vim's gg). Always returns {0, 0}.

Move backward to the previous occurrence of char on the current line (Vim's F). Returns the original position if char is not found.

Move forward to the next occurrence of char on the current line (Vim's f). Returns the original position if char is not found.

Move to the first non-blank character on the current line (like Vim's ^). Falls back to {line, 0} when the line is entirely blank.

Move to the last column of the current line (like Vim's $). Returns the position of the last grapheme on the line. For an empty line, returns {line, 0}.

Move to the first column of the current line (like Vim's 0).

Jump to the matching bracket/paren/brace (Vim's %).

Move to the previous blank line (Vim's {).

Move to the next blank line (Vim's }).

Move to one after the previous occurrence of char on the current line (Vim's T). Returns the original position if char is not found.

Move to one before the next occurrence of char on the current line (Vim's t). Returns the original position if char is not found.

Move backward to the start of the previous word (like Vim's b).

Move backward to the start of the previous WORD (Vim's B).

Move to the end of the current or next word (like Vim's e).

Move to the end of the current or next WORD (Vim's E).

Move forward to the start of the next word (like Vim's w).

Move forward to the start of the next WORD (Vim's W).

Types

position()

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

A zero-indexed {line, col} cursor position.

Functions

document_end(buf)

@spec document_end(Minga.Editing.Text.Readable.t()) :: position()

Move to the last character of the last line (like Vim's G).

Examples

iex> buf = Minga.Buffer.Document.new("hello\nworld")
iex> Minga.Editing.Motion.document_end(buf)
{1, 4}

document_start(buf)

@spec document_start(Minga.Editing.Text.Readable.t()) :: position()

Move to the very start of the buffer (like Vim's gg). Always returns {0, 0}.

Examples

iex> Minga.Editing.Motion.document_start(Minga.Buffer.Document.new("hello\nworld"))
{0, 0}

find_char_backward(buf, pos, char)

@spec find_char_backward(Minga.Editing.Text.Readable.t(), position(), String.t()) ::
  position()

Move backward to the previous occurrence of char on the current line (Vim's F). Returns the original position if char is not found.

Examples

iex> buf = Minga.Buffer.Document.new("hello world")
iex> Minga.Editing.Motion.find_char_backward(buf, {0, 7}, "o")
{0, 4}

find_char_forward(buf, pos, char)

@spec find_char_forward(Minga.Editing.Text.Readable.t(), position(), String.t()) ::
  position()

Move forward to the next occurrence of char on the current line (Vim's f). Returns the original position if char is not found.

Examples

iex> buf = Minga.Buffer.Document.new("hello world")
iex> Minga.Editing.Motion.find_char_forward(buf, {0, 0}, "o")
{0, 4}

first_non_blank(buf, pos)

@spec first_non_blank(Minga.Editing.Text.Readable.t(), position()) :: position()

Move to the first non-blank character on the current line (like Vim's ^). Falls back to {line, 0} when the line is entirely blank.

Examples

iex> buf = Minga.Buffer.Document.new("  hello")
iex> Minga.Editing.Motion.first_non_blank(buf, {0, 0})
{0, 2}

line_end(buf, pos)

@spec line_end(Minga.Editing.Text.Readable.t(), position()) :: position()

Move to the last column of the current line (like Vim's $). Returns the position of the last grapheme on the line. For an empty line, returns {line, 0}.

Examples

iex> buf = Minga.Buffer.Document.new("hello\nworld")
iex> Minga.Editing.Motion.line_end(buf, {0, 0})
{0, 4}

line_start(buf, pos)

@spec line_start(Minga.Editing.Text.Readable.t(), position()) :: position()

Move to the first column of the current line (like Vim's 0).

Examples

iex> buf = Minga.Buffer.Document.new("  hello")
iex> Minga.Editing.Motion.line_start(buf, {0, 4})
{0, 0}

match_bracket(buf, pos)

@spec match_bracket(Minga.Editing.Text.Readable.t(), position()) :: position()

Jump to the matching bracket/paren/brace (Vim's %).

Examples

iex> buf = Minga.Buffer.Document.new("(hello)")
iex> Minga.Editing.Motion.match_bracket(buf, {0, 0})
{0, 6}

paragraph_backward(buf, pos)

@spec paragraph_backward(Minga.Editing.Text.Readable.t(), position()) :: position()

Move to the previous blank line (Vim's {).

Examples

iex> buf = Minga.Buffer.Document.new("hello\nworld\n\nfoo")
iex> Minga.Editing.Motion.paragraph_backward(buf, {3, 0})
{2, 0}

paragraph_forward(buf, pos)

@spec paragraph_forward(Minga.Editing.Text.Readable.t(), position()) :: position()

Move to the next blank line (Vim's }).

Examples

iex> buf = Minga.Buffer.Document.new("hello\nworld\n\nfoo")
iex> Minga.Editing.Motion.paragraph_forward(buf, {0, 0})
{2, 0}

till_char_backward(buf, pos, char)

@spec till_char_backward(Minga.Editing.Text.Readable.t(), position(), String.t()) ::
  position()

Move to one after the previous occurrence of char on the current line (Vim's T). Returns the original position if char is not found.

Examples

iex> buf = Minga.Buffer.Document.new("hello world")
iex> Minga.Editing.Motion.till_char_backward(buf, {0, 7}, "o")
{0, 5}

till_char_forward(buf, pos, char)

@spec till_char_forward(Minga.Editing.Text.Readable.t(), position(), String.t()) ::
  position()

Move to one before the next occurrence of char on the current line (Vim's t). Returns the original position if char is not found.

Examples

iex> buf = Minga.Buffer.Document.new("hello world")
iex> Minga.Editing.Motion.till_char_forward(buf, {0, 0}, "o")
{0, 3}

word_backward(buf, pos)

@spec word_backward(Minga.Editing.Text.Readable.t(), position()) :: position()

Move backward to the start of the previous word (like Vim's b).

Examples

iex> buf = Minga.Buffer.Document.new("hello world")
iex> Minga.Editing.Motion.word_backward(buf, {0, 6})
{0, 0}

word_backward_big(buf, pos)

@spec word_backward_big(Minga.Editing.Text.Readable.t(), position()) :: position()

Move backward to the start of the previous WORD (Vim's B).

Examples

iex> buf = Minga.Buffer.Document.new("foo.bar baz")
iex> Minga.Editing.Motion.word_backward_big(buf, {0, 8})
{0, 0}

word_end(buf, pos)

@spec word_end(Minga.Editing.Text.Readable.t(), position()) :: position()

Move to the end of the current or next word (like Vim's e).

Examples

iex> buf = Minga.Buffer.Document.new("hello world")
iex> Minga.Editing.Motion.word_end(buf, {0, 0})
{0, 4}

word_end_big(buf, pos)

@spec word_end_big(Minga.Editing.Text.Readable.t(), position()) :: position()

Move to the end of the current or next WORD (Vim's E).

Examples

iex> buf = Minga.Buffer.Document.new("foo.bar baz")
iex> Minga.Editing.Motion.word_end_big(buf, {0, 0})
{0, 6}

word_forward(buf, pos)

@spec word_forward(Minga.Editing.Text.Readable.t(), position()) :: position()

Move forward to the start of the next word (like Vim's w).

Examples

iex> buf = Minga.Buffer.Document.new("hello world")
iex> Minga.Editing.Motion.word_forward(buf, {0, 0})
{0, 6}

word_forward_big(buf, pos)

@spec word_forward_big(Minga.Editing.Text.Readable.t(), position()) :: position()

Move forward to the start of the next WORD (Vim's W).

Examples

iex> buf = Minga.Buffer.Document.new("foo.bar baz")
iex> Minga.Editing.Motion.word_forward_big(buf, {0, 0})
{0, 8}