co-authored by
Nathan Sobo
parent
c39c7c3eff
commit
46f8665e41
@@ -14,7 +14,7 @@ use crate::{
|
||||
worktree::FileHandle,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use gpui::{AppContext, Entity, ModelContext};
|
||||
use gpui::{executor::BackgroundTask, AppContext, Entity, ModelContext};
|
||||
use lazy_static::lazy_static;
|
||||
use rand::prelude::*;
|
||||
use std::{
|
||||
@@ -46,6 +46,10 @@ pub struct Buffer {
|
||||
lamport_clock: time::Lamport,
|
||||
}
|
||||
|
||||
pub struct Snapshot {
|
||||
fragments: SumTree<Fragment>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct History {
|
||||
pub base_text: String,
|
||||
@@ -59,11 +63,17 @@ pub struct Selection {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Chars<'a> {
|
||||
pub struct CharIter<'a> {
|
||||
fragments_cursor: Cursor<'a, Fragment, usize, usize>,
|
||||
fragment_chars: str::Chars<'a>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FragmentIter<'a> {
|
||||
cursor: Cursor<'a, Fragment, usize, usize>,
|
||||
started: bool,
|
||||
}
|
||||
|
||||
struct Edits<'a, F: Fn(&FragmentSummary) -> bool> {
|
||||
cursor: FilterCursor<'a, F, Fragment, usize>,
|
||||
since: time::Global,
|
||||
@@ -225,6 +235,21 @@ impl Buffer {
|
||||
self.file.as_ref().map(|file| file.entry_id())
|
||||
}
|
||||
|
||||
pub fn snapshot(&self) -> Snapshot {
|
||||
Snapshot {
|
||||
fragments: self.fragments.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save(&self, ctx: &mut ModelContext<Self>) -> Option<BackgroundTask<Result<()>>> {
|
||||
if let Some(file) = &self.file {
|
||||
let snapshot = self.snapshot();
|
||||
Some(file.save(snapshot, ctx.app()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_modified(&self) -> bool {
|
||||
self.version != time::Global::new()
|
||||
}
|
||||
@@ -325,25 +350,13 @@ impl Buffer {
|
||||
Ok(self.chars_at(start)?.take(end - start).collect())
|
||||
}
|
||||
|
||||
pub fn chars(&self) -> Chars {
|
||||
pub fn chars(&self) -> CharIter {
|
||||
self.chars_at(0).unwrap()
|
||||
}
|
||||
|
||||
pub fn chars_at<T: ToOffset>(&self, position: T) -> Result<Chars> {
|
||||
pub fn chars_at<T: ToOffset>(&self, position: T) -> Result<CharIter> {
|
||||
let offset = position.to_offset(self)?;
|
||||
|
||||
let mut fragments_cursor = self.fragments.cursor::<usize, usize>();
|
||||
fragments_cursor.seek(&offset, SeekBias::Right);
|
||||
|
||||
let fragment_chars = fragments_cursor.item().map_or("".chars(), |fragment| {
|
||||
let offset_in_fragment = offset - fragments_cursor.start();
|
||||
fragment.text[offset_in_fragment..].chars()
|
||||
});
|
||||
|
||||
Ok(Chars {
|
||||
fragments_cursor,
|
||||
fragment_chars,
|
||||
})
|
||||
Ok(CharIter::new(&self.fragments, offset))
|
||||
}
|
||||
|
||||
pub fn selections_changed_since(&self, since: SelectionsVersion) -> bool {
|
||||
@@ -1369,6 +1382,16 @@ impl Clone for Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
impl Snapshot {
|
||||
pub fn fragments<'a>(&'a self) -> FragmentIter<'a> {
|
||||
FragmentIter::new(&self.fragments)
|
||||
}
|
||||
|
||||
pub fn text_summary(&self) -> TextSummary {
|
||||
self.fragments.summary().text_summary
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Event {
|
||||
Edited(Vec<Edit>),
|
||||
@@ -1384,7 +1407,22 @@ impl<'a> sum_tree::Dimension<'a, FragmentSummary> for Point {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Chars<'a> {
|
||||
impl<'a> CharIter<'a> {
|
||||
fn new(fragments: &'a SumTree<Fragment>, offset: usize) -> Self {
|
||||
let mut fragments_cursor = fragments.cursor::<usize, usize>();
|
||||
fragments_cursor.seek(&offset, SeekBias::Right);
|
||||
let fragment_chars = fragments_cursor.item().map_or("".chars(), |fragment| {
|
||||
let offset_in_fragment = offset - fragments_cursor.start();
|
||||
fragment.text[offset_in_fragment..].chars()
|
||||
});
|
||||
Self {
|
||||
fragments_cursor,
|
||||
fragment_chars,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for CharIter<'a> {
|
||||
type Item = char;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
@@ -1406,6 +1444,38 @@ impl<'a> Iterator for Chars<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FragmentIter<'a> {
|
||||
fn new(fragments: &'a SumTree<Fragment>) -> Self {
|
||||
let mut cursor = fragments.cursor::<usize, usize>();
|
||||
cursor.seek(&0, SeekBias::Right);
|
||||
Self {
|
||||
cursor,
|
||||
started: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for FragmentIter<'a> {
|
||||
type Item = &'a str;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
if self.started {
|
||||
self.cursor.next();
|
||||
} else {
|
||||
self.started = true;
|
||||
}
|
||||
if let Some(fragment) = self.cursor.item() {
|
||||
if fragment.is_visible() {
|
||||
return Some(fragment.text.as_str());
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> {
|
||||
type Item = Edit;
|
||||
|
||||
|
||||
@@ -5,8 +5,9 @@ use super::{
|
||||
use crate::{settings::Settings, watch, workspace};
|
||||
use anyhow::Result;
|
||||
use gpui::{
|
||||
fonts::Properties as FontProperties, keymap::Binding, text_layout, App, AppContext, Element,
|
||||
ElementBox, Entity, FontCache, ModelHandle, View, ViewContext, WeakViewHandle,
|
||||
executor::BackgroundTask, fonts::Properties as FontProperties, keymap::Binding, text_layout,
|
||||
App, AppContext, Element, ElementBox, Entity, FontCache, ModelHandle, MutableAppContext, View,
|
||||
ViewContext, WeakViewHandle,
|
||||
};
|
||||
use gpui::{geometry::vector::Vector2F, TextLayoutCache};
|
||||
use parking_lot::Mutex;
|
||||
@@ -1178,6 +1179,10 @@ impl workspace::ItemView for BufferView {
|
||||
*clone.scroll_position.lock() = *self.scroll_position.lock();
|
||||
Some(clone)
|
||||
}
|
||||
|
||||
fn save(&self, ctx: &mut MutableAppContext) -> Option<BackgroundTask<Result<()>>> {
|
||||
self.buffer.update(ctx, |buffer, ctx| buffer.save(ctx))
|
||||
}
|
||||
}
|
||||
|
||||
impl Selection {
|
||||
|
||||
@@ -403,7 +403,7 @@ pub struct Chars<'a> {
|
||||
cursor: Cursor<'a, Transform, DisplayOffset, TransformSummary>,
|
||||
offset: usize,
|
||||
buffer: &'a Buffer,
|
||||
buffer_chars: Option<Take<buffer::Chars<'a>>>,
|
||||
buffer_chars: Option<Take<buffer::CharIter<'a>>>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Chars<'a> {
|
||||
|
||||
Reference in New Issue
Block a user