pub struct TextBuffer { /* private fields */ }Implementations§
Source§impl TextBuffer
impl TextBuffer
pub fn from_str(s: &str) -> Self
Sourcepub fn new_at(path: &Path) -> Self
pub fn new_at(path: &Path) -> Self
An empty buffer that will be written to path when saved.
A sibling of from_path rather than a flag on it, so “read this file”
keeps meaning exactly that and never quietly invents one.
Not dirty: nothing has been typed. Marking it dirty would make Ctrl+Q challenge the user over a file they never edited.
Sourcepub fn from_path(path: &Path) -> Result<Self>
pub fn from_path(path: &Path) -> Result<Self>
Read a file into a buffer.
CRLF is normalized to LF in the rope and the original recorded in
line_ending, which save writes back. Keeping the \r in the rope
would put it inside every line as a grapheme that col arithmetic, word
motion and search all have to know to skip — and an editor whose whole
cursor model is “col is a grapheme index” cannot afford one grapheme
that is secretly punctuation. TermIDE takes the same approach for the
same reason.
pub fn line_count(&self) -> usize
Sourcepub fn text(&self) -> String
pub fn text(&self) -> String
The whole buffer as a String.
Allocates the entire text, so it is for whole-file work and never for anything on the keystroke path.
Sourcepub fn text_as_saved(&self) -> String
pub fn text_as_saved(&self) -> String
The whole buffer as save would write it, line endings and all.
The rope holds LF only. Comparing text() against a CRLF file on disk
says they differ when they do not, which would make every save of a
Windows file report itself as an external change.
Sourcepub fn line_ending(&self) -> LineEnding
pub fn line_ending(&self) -> LineEnding
The line terminator this file was loaded with, and the one save
writes back. The rope itself holds LF only.
pub fn path(&self) -> Option<&Path>
pub fn is_dirty(&self) -> bool
Sourcepub fn with_line_str<T>(&self, line: usize, f: impl FnOnce(&str) -> T) -> T
pub fn with_line_str<T>(&self, line: usize, f: impl FnOnce(&str) -> T) -> T
Call f with one line’s text, borrowed from the rope when possible.
RopeSlice::as_str succeeds whenever the line lives inside a single
chunk, which is the overwhelmingly common case — ropey chunks are ~1 KB
and lines of code are not. Only a line straddling a chunk boundary pays
for a String.
This exists because line_text returning an owned String was correct
but quadratic in aggregate: three callers looped it over every line in
the buffer, so one keystroke on a 50k-line file allocated 50k strings.
A borrowing accessor makes the cheap thing the easy thing to reach for.
Sourcepub fn line_text(&self, line: usize) -> String
pub fn line_text(&self, line: usize) -> String
Line contents without the trailing newline.
Allocates. Prefer with_line_str in anything that runs per line over a
range of lines.
Sourcepub fn line_grapheme_count(&self, line: usize) -> usize
pub fn line_grapheme_count(&self, line: usize) -> usize
Graphemes on a line, without materializing it.
pub fn insert_char(&mut self, pos: Position, ch: char)
Sourcepub fn delete_before(&mut self, pos: Position)
pub fn delete_before(&mut self, pos: Position)
Delete the grapheme immediately before pos (backspace).
Sourcepub fn delete_after(&mut self, pos: Position)
pub fn delete_after(&mut self, pos: Position)
Delete the grapheme at pos (forward delete).
At the end of a line this removes the newline, joining the next line up.
Sourcepub fn text_in_range(&self, start: Position, end: Position) -> String
pub fn text_in_range(&self, start: Position, end: Position) -> String
The text between two positions.
Ordered by the caller — a selection’s range() already answers which end
comes first, so this does not second-guess it.
Sourcepub fn find_all(&self, query: &SearchQuery) -> Vec<Selection>
pub fn find_all(&self, query: &SearchQuery) -> Vec<Selection>
Every match in the buffer, in document order, as selections whose head sits at the end of the match — so jumping to one leaves the cursor where typing would naturally continue.
Sourcepub fn find_next(
&self,
query: &SearchQuery,
after: Position,
) -> Option<Selection>
pub fn find_next( &self, query: &SearchQuery, after: Position, ) -> Option<Selection>
The first match strictly after after, wrapping to the top of the
buffer if there is none below it.
This exists so Ctrl+D is not find_all with a filter on it. find_all
scans the whole buffer — measured at ~7 ms on 50k lines, against a 16 ms
keystroke budget — and select-next-occurrence is a key people hold, so
one scan per press is not a cost that can be paid. Stopping at the first
hit is both the faster thing and the simpler one.
Wrapping is unconditional, and it is load-bearing rather than a
convenience: coming back round to a match the caller already holds is how
Ctrl+D knows every occurrence is selected and it is time to stop.
Sourcepub fn replace_range(&mut self, start: Position, end: Position, text: &str)
pub fn replace_range(&mut self, start: Position, end: Position, text: &str)
Replace the text between two positions as a single undo step.
An empty range inserts, so callers can express insertion, deletion and replacement as one operation and not branch three ways.
Sourcepub fn begin_edit_group(&mut self, kind: EditKind, selections: &Selections)
pub fn begin_edit_group(&mut self, kind: EditKind, selections: &Selections)
Begin a group of edits that undo together.
One snapshot is taken up front and none during the group, so thirty cursors typing one character is one undo step. Without this, undoing a thirty-caret edit would take thirty presses and leave the buffer in states the user never typed.
Whether that snapshot is actually pushed is History’s call: a group
continuing a run of the same kind folds into the one already there.
pub fn end_edit_group(&mut self)
Sourcepub fn undo_depth(&self) -> usize
pub fn undo_depth(&self) -> usize
How many undo steps are currently held.
Sourcepub fn undo_boundary(&mut self)
pub fn undo_boundary(&mut self)
End the current undo run. The next edit starts a new step.
Sourcepub fn undo(&mut self, current: &Selections) -> Option<Selections>
pub fn undo(&mut self, current: &Selections) -> Option<Selections>
Undo one step, returning the selections to restore.
None means there was nothing to undo, so the caller leaves its
selections alone.
pub fn redo(&mut self, current: &Selections) -> Option<Selections>
Sourcepub fn save(&mut self) -> Result<()>
pub fn save(&mut self) -> Result<()>
Write the buffer to disk, atomically.
The content goes to a sibling temporary file, is flushed to the device,
and is then renamed over the target. rename replaces the destination
in one step on both NTFS and POSIX, so an interrupted save leaves the
previous file intact rather than a truncated one. Writing in place would
mean a crash between truncate and write costs the user the whole file
rather than the last edit.