Implement methods to query the contents of a TextEditor

This commit is contained in:
Héctor Ramón Jiménez 2023-09-16 15:27:25 +02:00
parent f7fc13d98c
commit c6d0443627
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
4 changed files with 107 additions and 0 deletions

View file

@ -125,6 +125,18 @@ impl text::Editor for () {
text::editor::Cursor::Caret(Point::ORIGIN)
}
fn selection(&self) -> Option<String> {
None
}
fn line(&self, _index: usize) -> Option<&str> {
None
}
fn line_count(&self) -> usize {
0
}
fn perform(&mut self, _action: text::editor::Action) {}
fn bounds(&self) -> Size {

View file

@ -9,6 +9,12 @@ pub trait Editor: Sized + Default {
fn cursor(&self) -> Cursor;
fn selection(&self) -> Option<String>;
fn line(&self, index: usize) -> Option<&str>;
fn line_count(&self) -> usize;
fn perform(&mut self, action: Action);
/// Returns the current boundaries of the [`Editor`].

View file

@ -69,6 +69,47 @@ impl editor::Editor for Editor {
})))
}
fn line(&self, index: usize) -> Option<&str> {
self.buffer()
.lines
.get(index)
.map(cosmic_text::BufferLine::text)
}
fn line_count(&self) -> usize {
self.buffer().lines.len()
}
fn selection(&self) -> Option<String> {
let internal = self.internal();
let cursor = internal.editor.cursor();
let selection = internal.editor.select_opt()?;
let (start, end) = if cursor < selection {
(cursor, selection)
} else {
(selection, cursor)
};
Some(
internal.editor.buffer().lines[start.line..=end.line]
.iter()
.enumerate()
.map(|(i, line)| {
if i == 0 {
&line.text()[start.index..]
} else if i == end.line - start.line {
&line.text()[..end.index]
} else {
line.text()
}
})
.collect::<Vec<_>>()
.join("\n"),
)
}
fn cursor(&self) -> editor::Cursor {
let internal = self.internal();

View file

@ -100,6 +100,54 @@ where
internal.editor.perform(action);
internal.is_dirty = true;
}
pub fn line_count(&self) -> usize {
self.0.borrow().editor.line_count()
}
pub fn line(
&self,
index: usize,
) -> Option<impl std::ops::Deref<Target = str> + '_> {
std::cell::Ref::filter_map(self.0.borrow(), |internal| {
internal.editor.line(index)
})
.ok()
}
pub fn lines(
&self,
) -> impl Iterator<Item = impl std::ops::Deref<Target = str> + '_> {
struct Lines<'a, Renderer: text::Renderer> {
internal: std::cell::Ref<'a, Internal<Renderer>>,
current: usize,
}
impl<'a, Renderer: text::Renderer> Iterator for Lines<'a, Renderer> {
type Item = std::cell::Ref<'a, str>;
fn next(&mut self) -> Option<Self::Item> {
let line = std::cell::Ref::filter_map(
std::cell::Ref::clone(&self.internal),
|internal| internal.editor.line(self.current),
)
.ok()?;
self.current += 1;
Some(line)
}
}
Lines {
internal: self.0.borrow(),
current: 0,
}
}
pub fn selection(&self) -> Option<String> {
self.0.borrow().editor.selection()
}
}
impl<Renderer> Default for Content<Renderer>