Skip to main content

TextBuffer

Struct TextBuffer 

Source
pub struct TextBuffer { /* private fields */ }
Expand description

A Ropey-backed text buffer.

Invariants and conventions:

  • The backing store is a ropey::Rope.
  • Public APIs should generally speak in char indices (Unicode scalar value offsets) and logical positions (line/col in chars) because Ropey’s safe indexing APIs are char-based.
  • Byte indexing can be supported where needed, but should not be the primary index type for the editor core.

Higher-level editor state (modes, undo, viewports, etc.) should be built on top of this type rather than embedded inside it.

Implementations§

Source§

impl TextBuffer

Source

pub fn new() -> Self

Create an empty buffer

Source

pub fn from_str(s: &str) -> Self

Create a buffer from UTF-8 text

Source

pub fn from_file(path: impl AsRef<Path>) -> Result<Self>

Load a file as UTF-8 and create a buffer.

This is intentionally simple for now. It just:

  • reads the whole file into memory
  • requires valid UTF-8

NOTE: If/when I add encoding detection or incremental IO, those should likely live in a separate IO-focused module.

Source

pub fn rope(&self) -> &Rope

Access the underlying rope.

Prefer higher-level APIs in other modules for most editor operations.

Source

pub fn rope_mut(&mut self) -> &mut Rope

Mutable access to the underlying rope (use this sparingly!)

Prefer dedicated editing APIs so invariants and future bookkeeping (eg. undo/redo, marks, spans) remain easy to maintain.

Source

pub fn len_chars(&self) -> usize

Total number of chars in the buffer.

Kept here because it is a fundamental primitive used by most other modules.

Source

pub fn is_empty(&self) -> bool

Whether or not the buffer contains zero characters (is empty).

Source§

impl TextBuffer

Source

pub fn insert(&mut self, pos: Pos, text: &str) -> Pos

Insert text at the given logical position.

Returns the new cursor position (at the end of inserted text).

NOTE: This is a primitive operation I can build higher-level commands on top of (e.g. replace-selection-then-insert, paste, auto-indent, etc).

Source

pub fn delete_range(&mut self, a: Pos, b: Pos) -> Pos

Delete a range between two positions (order-independent).

Returns the resulting cursor position (at the start of deletion).

Source

pub fn delete_selection(&mut self, sel: Selection) -> (Pos, bool)

Delete the selection (if any). Returns (new_cursor, did_delete).

Source

pub fn backspace(&mut self, sel: Selection) -> Selection

Backspace behavior:

  • if the selection is non-empty, delete it
  • otherwise delete the char before the cursor (if any)

Returns an empty selection at the updated cursor.

Source

pub fn delete(&mut self, sel: Selection) -> Selection

Delete (forward) behavior:

  • if the selection is non-empty, delete it
  • otherwise delete the char at the cursor (if any)

Returns an empty selection at the updated cursor.

Source

pub fn insert_newline(&mut self, sel: Selection) -> Selection

Insert a newline at the cursor (or replace the selection).

Returns an empty selection at the updated cursor.

Source

pub fn apply_edit(&mut self, edit: Edit) -> Pos

Apply an Edit expressed in char indices.

NOTE: This is intended as a low-level building block for future undo/redo so I can store Edits, invert them, and replay them.

Returns the resulting cursor position (end of inserted text, or start of deletion).

Source

pub fn replace_selection(&mut self, sel: Selection, text: &str) -> Selection

Replace the current selection with text (if selection is empty, behaves like insert). This is a convenience method that a bunch of editor actions can use.

Returns an empty selection at the updated cursor.

Source§

impl TextBuffer

Source

pub fn len_lines(&self) -> usize

Number of lines in the buffer.

Ropey counts lines by '\n' boundaries and always reports at least 1 line, even for empty text.

Source

pub fn clamp_line(&self, line: usize) -> usize

Clamp a line index to the valid range [0, len_lines - 1].

If the buffer is empty, Ropey still reports len_lines() == 1, so this always returns a valid line index.

Source

pub fn line_to_char(&self, line: usize) -> usize

Returns the absolute char index at the start of line.

line is clamped into a valid range.

Source

pub fn char_to_line(&self, char_idx: usize) -> usize

Returns the line index containing char_idx.

char_idx is clamped to [0, len_chars].

Source

pub fn line_len_chars(&self, line: usize) -> usize

Returns the length of line in chars, excluding a trailing '\n' if present.

This corresponds to the number of valid “columns” for a (line, col) cursor model where the newline is not considered part of the line.

Source

pub fn line_string(&self, line: usize) -> String

Returns the line content as a String, excluding a trailing '\n' if present.

Source

pub fn line_char_range(&self, line: usize) -> Range<usize>

Returns the char range [start, end) for the line content, excluding a trailing '\n'.

This will be useful for operations like “delete to end of line” or yanking the line content without the newline.

Source§

impl TextBuffer

Source

pub fn clamp_pos(&self, pos: Pos) -> Pos

Clamp a position to a valid location in the buffer.

  • Line is clamped to [0, len_lines - 1]
  • Column is clamped to [0, line_len_chars(line)]
Source

pub fn pos_to_char(&self, pos: Pos) -> usize

Convert Pos (line+col) to absolute char index in the rope.

The position is clamped first.

Source

pub fn char_to_pos(&self, char_idx: usize) -> Pos

Convert absolute char index to Pos (line+col).

char_idx is clamped to [0, len_chars].

Source

pub fn move_left(&self, pos: Pos) -> Pos

Move position left by one char, staying within buffer.

Source

pub fn move_right(&self, pos: Pos) -> Pos

Move position right by one char, staying within buffer.

Source

pub fn move_up(&self, pos: Pos) -> Pos

Move up one line, preserving column as much as possible.

NOTE: This is a simple version with no goal/preferred column tracking. If I decide I want Vim-like vertical motion that remembers a preferred column, I should store that in higher-level state and clamp it using line_len_chars(...).

Source

pub fn move_down(&self, pos: Pos) -> Pos

Move down one line, preserving column as much as possible.

This is a simple version (no goal/preferred column tracking). NOTE: Same as above :)

Source

pub fn char_at(&self, pos: Pos) -> Option<char>

Get the char at a position, if it’s within the line’s content (not including newline).

Source

pub fn char_before(&self, pos: Pos) -> Option<char>

Get the char before a position, if one exists.

Source§

impl TextBuffer

Source

pub fn to_string(&self) -> String

Get the full buffer as a String.

For large buffers, this allocates. Kept as an inherent method so call sites can use b.to_string() without depending on Display/ToString.

Source

pub fn slice_chars(&self, start: usize, end: usize) -> String

Get a String for a character range [start, end).

  • Indices are clamped to the buffer bounds.
  • If start > end, the values are swapped.

This is a convenience API; it allocates.

Source

pub fn slice_selection(&self, sel: Selection) -> String

Get the selected text for a selection (ordered).

This is a convenience API; it allocates.

Source

pub fn slice_pos_range(&self, a: Pos, b: Pos) -> String

Convenience: slice by two logical positions (order-independent).

This is useful if there are two cursors/marks and I want the substring between them without explicitly building a Selection.

Source§

impl TextBuffer

Source

pub fn word_start_before(&self, pos: Pos) -> Pos

Find the start of the previous/current word-like run (b-style).

Source

pub fn word_end_after(&self, pos: Pos) -> Pos

Find the end of the current/next word-like run (e-style).

Source

pub fn word_start_after(&self, pos: Pos) -> Pos

Find the start of the next word-like run (w-style).

Trait Implementations§

Source§

impl Clone for TextBuffer

Source§

fn clone(&self) -> TextBuffer

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for TextBuffer

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for TextBuffer

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.