redox_core/buffer/text_buffer/slicing.rs
1//! `TextBuffer` slicing helpers.
2//!
3//! Design notes:
4//! - All indices are **character indices** (Unicode scalar values) to match `ropey`.
5//! - These helpers are intentionally allocating (`String`) for ergonomics.
6//! If I later need more performance, add `RopeSlice`-returning variants
7//! without changing call sites that just need owned strings.
8
9use std::cmp::min;
10
11use super::TextBuffer;
12use crate::buffer::{Pos, Selection};
13
14impl TextBuffer {
15 /// Get the full buffer as a `String`.
16 ///
17 /// For large buffers, this allocates. Kept as an inherent method so call sites
18 /// can use `b.to_string()` without depending on `Display`/`ToString`.
19 #[inline]
20 pub fn to_string(&self) -> String {
21 self.rope().to_string()
22 }
23
24 /// Get a `String` for a character range `[start, end)`.
25 ///
26 /// - Indices are clamped to the buffer bounds.
27 /// - If `start > end`, the values are swapped.
28 ///
29 /// This is a convenience API; it allocates.
30 pub fn slice_chars(&self, mut start: usize, mut end: usize) -> String {
31 let maxc = self.len_chars();
32 start = min(start, maxc);
33 end = min(end, maxc);
34 if start > end {
35 std::mem::swap(&mut start, &mut end);
36 }
37 self.rope().slice(start..end).to_string()
38 }
39
40 /// Get the selected text for a selection (ordered).
41 ///
42 /// This is a convenience API; it allocates.
43 pub fn slice_selection(&self, sel: Selection) -> String {
44 let (a, b) = sel.ordered();
45 let start = self.pos_to_char(a);
46 let end = self.pos_to_char(b);
47 self.slice_chars(start, end)
48 }
49
50 /// Convenience: slice by two logical positions (order-independent).
51 ///
52 /// This is useful if there are two cursors/marks and I want the substring
53 /// between them without explicitly building a `Selection`.
54 pub fn slice_pos_range(&self, a: Pos, b: Pos) -> String {
55 let start = self.pos_to_char(a);
56 let end = self.pos_to_char(b);
57 self.slice_chars(start, end)
58 }
59}