Skip to main content

TextBuffer

Struct TextBuffer 

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

Implementations§

Source§

impl TextBuffer

Source

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

Source

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.

Source

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.

Source

pub fn line_count(&self) -> usize

Source

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.

Source

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.

Source

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.

Source

pub fn path(&self) -> Option<&Path>

Source

pub fn is_dirty(&self) -> bool

Source

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.

Source

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.

Source

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

Graphemes on a line, without materializing it.

Source

pub fn insert_char(&mut self, pos: Position, ch: char)

Source

pub fn delete_before(&mut self, pos: Position)

Delete the grapheme immediately before pos (backspace).

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn end_edit_group(&mut self)

Source

pub fn undo_depth(&self) -> usize

How many undo steps are currently held.

Source

pub fn undo_boundary(&mut self)

End the current undo run. The next edit starts a new step.

Source

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.

Source

pub fn redo(&mut self, current: &Selections) -> Option<Selections>

Source

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.

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> 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, 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.