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
impl TextBuffer
Sourcepub fn from_file(path: impl AsRef<Path>) -> Result<Self>
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.
Sourcepub fn rope(&self) -> &Rope
pub fn rope(&self) -> &Rope
Access the underlying rope.
Prefer higher-level APIs in other modules for most editor operations.
Sourcepub fn rope_mut(&mut self) -> &mut Rope
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§impl TextBuffer
impl TextBuffer
Sourcepub fn insert(&mut self, pos: Pos, text: &str) -> Pos
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).
Sourcepub fn delete_range(&mut self, a: Pos, b: Pos) -> Pos
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).
Sourcepub fn delete_selection(&mut self, sel: Selection) -> (Pos, bool)
pub fn delete_selection(&mut self, sel: Selection) -> (Pos, bool)
Delete the selection (if any). Returns (new_cursor, did_delete).
Sourcepub fn backspace(&mut self, sel: Selection) -> Selection
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.
Sourcepub fn delete(&mut self, sel: Selection) -> Selection
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.
Sourcepub fn insert_newline(&mut self, sel: Selection) -> Selection
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.
Sourcepub fn apply_edit(&mut self, edit: Edit) -> Pos
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).
Sourcepub fn replace_selection(&mut self, sel: Selection, text: &str) -> Selection
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
impl TextBuffer
Sourcepub fn len_lines(&self) -> usize
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.
Sourcepub fn clamp_line(&self, line: usize) -> usize
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.
Sourcepub fn line_to_char(&self, line: usize) -> usize
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.
Sourcepub fn char_to_line(&self, char_idx: usize) -> usize
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].
Sourcepub fn line_len_chars(&self, line: usize) -> usize
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.
Sourcepub fn line_string(&self, line: usize) -> String
pub fn line_string(&self, line: usize) -> String
Returns the line content as a String, excluding a trailing '\n' if present.
Sourcepub fn line_char_range(&self, line: usize) -> Range<usize>
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
impl TextBuffer
Sourcepub fn clamp_pos(&self, pos: Pos) -> Pos
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)]
Sourcepub fn pos_to_char(&self, pos: Pos) -> usize
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.
Sourcepub fn char_to_pos(&self, char_idx: usize) -> Pos
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].
Sourcepub fn move_left(&self, pos: Pos) -> Pos
pub fn move_left(&self, pos: Pos) -> Pos
Move position left by one char, staying within buffer.
Sourcepub fn move_right(&self, pos: Pos) -> Pos
pub fn move_right(&self, pos: Pos) -> Pos
Move position right by one char, staying within buffer.
Sourcepub fn move_up(&self, pos: Pos) -> Pos
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(...).
Sourcepub fn move_down(&self, pos: Pos) -> Pos
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 :)
Sourcepub fn char_at(&self, pos: Pos) -> Option<char>
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).
Sourcepub fn char_before(&self, pos: Pos) -> Option<char>
pub fn char_before(&self, pos: Pos) -> Option<char>
Get the char before a position, if one exists.
Source§impl TextBuffer
impl TextBuffer
Sourcepub fn to_string(&self) -> String
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.
Sourcepub fn slice_chars(&self, start: usize, end: usize) -> String
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.
Sourcepub fn slice_selection(&self, sel: Selection) -> String
pub fn slice_selection(&self, sel: Selection) -> String
Get the selected text for a selection (ordered).
This is a convenience API; it allocates.
Sourcepub fn slice_pos_range(&self, a: Pos, b: Pos) -> String
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
impl TextBuffer
Sourcepub fn word_start_before(&self, pos: Pos) -> Pos
pub fn word_start_before(&self, pos: Pos) -> Pos
Find the start of the previous/current word-like run (b-style).
Sourcepub fn word_end_after(&self, pos: Pos) -> Pos
pub fn word_end_after(&self, pos: Pos) -> Pos
Find the end of the current/next word-like run (e-style).
Sourcepub fn word_start_after(&self, pos: Pos) -> Pos
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
impl Clone for TextBuffer
Source§fn clone(&self) -> TextBuffer
fn clone(&self) -> TextBuffer
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more