gutter refactoring
This commit is contained in:
+76
-13
@@ -7,7 +7,9 @@
|
||||
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use crate::gutter::GutterState;
|
||||
use gpui_kit::base::input::Rope;
|
||||
|
||||
use crate::gutter::{GutterLineEdit, GutterShift, GutterState};
|
||||
|
||||
/// Счётчик идентификаторов документов.
|
||||
static NEXT_ID: AtomicU64 = AtomicU64::new(1);
|
||||
@@ -216,7 +218,12 @@ pub struct Document {
|
||||
/// индексом» после закрытия соседей.
|
||||
pub id: u64,
|
||||
pub name: String,
|
||||
pub content: String,
|
||||
/// Текст документа в виде rope: копия из редактора стоит O(1).
|
||||
content: Rope,
|
||||
/// Версия содержимого: увеличивается на каждую правку.
|
||||
content_version: u64,
|
||||
/// Есть несохранённые изменения.
|
||||
dirty: bool,
|
||||
/// Имя иконки вкладки из каталога Lucide (см. `crate::icons`).
|
||||
///
|
||||
/// `None` — показывается иконка по умолчанию. Назначается через
|
||||
@@ -231,18 +238,16 @@ pub struct Document {
|
||||
pub cursor: usize,
|
||||
/// Иконки на поле редактора для этой вкладки.
|
||||
pub gutter: GutterState,
|
||||
/// Содержимое на момент последнего «сохранения».
|
||||
saved_content: String,
|
||||
}
|
||||
|
||||
impl Document {
|
||||
pub fn new(name: impl Into<String>, content: impl Into<String>) -> Self {
|
||||
let content = content.into();
|
||||
Self {
|
||||
id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
|
||||
name: name.into(),
|
||||
saved_content: content.clone(),
|
||||
content,
|
||||
content: Rope::from(content.into()),
|
||||
content_version: 0,
|
||||
dirty: false,
|
||||
icon: None,
|
||||
language: None,
|
||||
cursor: 0,
|
||||
@@ -250,9 +255,46 @@ impl Document {
|
||||
}
|
||||
}
|
||||
|
||||
/// Текст документа.
|
||||
pub fn content(&self) -> &Rope {
|
||||
&self.content
|
||||
}
|
||||
|
||||
/// Материализованный текст для границ (сохранение, LSP, Lua).
|
||||
pub fn content_string(&self) -> String {
|
||||
self.content.to_string()
|
||||
}
|
||||
|
||||
/// Версия содержимого, увеличивается на каждую правку.
|
||||
pub fn content_version(&self) -> u64 {
|
||||
self.content_version
|
||||
}
|
||||
|
||||
/// Есть ли изменения, которые ещё не сохранены.
|
||||
pub fn is_dirty(&self) -> bool {
|
||||
self.content != self.saved_content
|
||||
self.dirty
|
||||
}
|
||||
|
||||
/// Заменяет текст и отмечает документ изменённым.
|
||||
///
|
||||
/// Это внешняя замена целого текста: иконки gutter привязаны к номерам
|
||||
/// строк старого текста, поэтому они сбрасываются. Сценарий может
|
||||
/// расставить их заново по новому тексту.
|
||||
pub fn set_content(&mut self, content: Rope) {
|
||||
if self.content == content {
|
||||
return;
|
||||
}
|
||||
self.content = content;
|
||||
self.content_version = self.content_version.wrapping_add(1);
|
||||
self.dirty = true;
|
||||
self.gutter.clear();
|
||||
}
|
||||
|
||||
/// Обновляет текст после правки в редакторе: копия rope стоит O(1).
|
||||
pub fn replace_content(&mut self, content: &Rope) {
|
||||
self.content = content.clone();
|
||||
self.content_version = self.content_version.wrapping_add(1);
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
/// Идентификатор языка для LSP.
|
||||
@@ -275,7 +317,7 @@ impl Document {
|
||||
|
||||
/// Помечает текущее содержимое сохранённым.
|
||||
pub fn mark_saved(&mut self) {
|
||||
self.saved_content = self.content.clone();
|
||||
self.dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,9 +459,11 @@ impl Workspace {
|
||||
.position(|document| document.name == name && !document.is_dirty())
|
||||
{
|
||||
let document = &mut self.documents[index];
|
||||
document.content = content;
|
||||
document.content = Rope::from(content);
|
||||
document.content_version = document.content_version.wrapping_add(1);
|
||||
document.mark_saved();
|
||||
document.language = language;
|
||||
document.gutter.clear();
|
||||
self.active = index;
|
||||
self.bump();
|
||||
return index;
|
||||
@@ -459,13 +503,32 @@ impl Workspace {
|
||||
///
|
||||
/// Используется видом после ввода в редакторе: сам виджет уже показывает
|
||||
/// этот текст, поэтому повторная синхронизация только сбросила бы курсор.
|
||||
pub fn replace_active_content(&mut self, content: String) {
|
||||
self.active_mut().content = content;
|
||||
/// Иконки gutter пересчитываются по точным правкам из `InputEvent::Change`.
|
||||
///
|
||||
/// Возвращает иконки, которые съехали.
|
||||
pub fn replace_active_content(
|
||||
&mut self,
|
||||
content: &Rope,
|
||||
line_edits: &[GutterLineEdit],
|
||||
collect_shifts: bool,
|
||||
) -> Vec<GutterShift> {
|
||||
let document = self.active_mut();
|
||||
if line_edits.is_empty() && document.content.eq(content) {
|
||||
return Vec::new();
|
||||
}
|
||||
let shifts = if collect_shifts {
|
||||
document.gutter.apply_line_edits(line_edits)
|
||||
} else {
|
||||
document.gutter.apply_line_edits_silently(line_edits);
|
||||
Vec::new()
|
||||
};
|
||||
document.replace_content(content);
|
||||
shifts
|
||||
}
|
||||
|
||||
/// Заменяет текст активной вкладки извне (Lua, меню, тесты).
|
||||
pub fn set_active_text(&mut self, text: impl Into<String>) {
|
||||
self.active_mut().content = text.into();
|
||||
self.active_mut().set_content(Rope::from(text.into()));
|
||||
self.bump();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user