mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-20 02:47:34 +03:00
WIP
This commit is contained in:
parent
fad5c98b8d
commit
c450945001
@ -15,9 +15,9 @@ use gpui::{
|
||||
use language::{Bias, Buffer, Diagnostic, DiagnosticEntry, Point, Selection, SelectionGoal};
|
||||
use postage::watch;
|
||||
use project::{Project, ProjectPath};
|
||||
use std::{any::TypeId, cmp::Ordering, mem, ops::Range, path::PathBuf, rc::Rc, sync::Arc};
|
||||
use std::{any::TypeId, cmp::Ordering, mem, ops::Range, path::PathBuf, sync::Arc};
|
||||
use util::TryFutureExt;
|
||||
use workspace::{NavHistory, Workspace};
|
||||
use workspace::{ItemNavHistory, Workspace};
|
||||
|
||||
action!(Deploy);
|
||||
action!(OpenExcerpts);
|
||||
@ -517,7 +517,7 @@ impl workspace::Item for ProjectDiagnostics {
|
||||
fn build_view(
|
||||
handle: ModelHandle<Self>,
|
||||
workspace: &Workspace,
|
||||
_: Rc<NavHistory>,
|
||||
_: ItemNavHistory,
|
||||
cx: &mut ViewContext<Self::View>,
|
||||
) -> Self::View {
|
||||
ProjectDiagnosticsEditor::new(handle, workspace.weak_handle(), workspace.settings(), cx)
|
||||
|
@ -41,7 +41,6 @@ use std::{
|
||||
iter::{self, FromIterator},
|
||||
mem,
|
||||
ops::{Deref, Range, RangeInclusive, Sub},
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
@ -49,7 +48,7 @@ use sum_tree::Bias;
|
||||
use text::rope::TextDimension;
|
||||
use theme::{DiagnosticStyle, EditorStyle};
|
||||
use util::post_inc;
|
||||
use workspace::{NavHistory, PathOpener, Workspace};
|
||||
use workspace::{ItemNavHistory, PathOpener, Workspace};
|
||||
|
||||
const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
|
||||
const MAX_LINE_LEN: usize = 1024;
|
||||
@ -382,7 +381,7 @@ pub struct Editor {
|
||||
mode: EditorMode,
|
||||
placeholder_text: Option<Arc<str>>,
|
||||
highlighted_rows: Option<Range<u32>>,
|
||||
nav_history: Option<Rc<NavHistory>>,
|
||||
nav_history: Option<ItemNavHistory>,
|
||||
}
|
||||
|
||||
pub struct EditorSnapshot {
|
||||
@ -468,7 +467,10 @@ impl Editor {
|
||||
let mut clone = Self::new(self.buffer.clone(), self.build_settings.clone(), cx);
|
||||
clone.scroll_position = self.scroll_position;
|
||||
clone.scroll_top_anchor = self.scroll_top_anchor.clone();
|
||||
clone.nav_history = self.nav_history.clone();
|
||||
clone.nav_history = self
|
||||
.nav_history
|
||||
.as_ref()
|
||||
.map(|nav_history| nav_history.clone(&cx.handle()));
|
||||
clone
|
||||
}
|
||||
|
||||
@ -2476,13 +2478,10 @@ impl Editor {
|
||||
}
|
||||
}
|
||||
|
||||
nav_history.push(
|
||||
Some(NavigationData {
|
||||
anchor: position,
|
||||
offset,
|
||||
}),
|
||||
cx,
|
||||
);
|
||||
nav_history.push(Some(NavigationData {
|
||||
anchor: position,
|
||||
offset,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4041,7 +4040,7 @@ pub fn settings_builder(
|
||||
mod tests {
|
||||
use super::*;
|
||||
use language::LanguageConfig;
|
||||
use std::time::Instant;
|
||||
use std::{cell::RefCell, rc::Rc, time::Instant};
|
||||
use text::Point;
|
||||
use unindent::Unindent;
|
||||
use util::test::sample_text;
|
||||
@ -4220,22 +4219,22 @@ mod tests {
|
||||
fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
|
||||
cx.add_window(Default::default(), |cx| {
|
||||
use workspace::ItemView;
|
||||
let nav_history = Rc::new(workspace::NavHistory::default());
|
||||
let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
|
||||
let settings = EditorSettings::test(&cx);
|
||||
let buffer = MultiBuffer::build_simple(&sample_text(30, 5, 'a'), cx);
|
||||
let mut editor = build_editor(buffer.clone(), settings, cx);
|
||||
editor.nav_history = Some(nav_history.clone());
|
||||
editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
|
||||
|
||||
// Move the cursor a small distance.
|
||||
// Nothing is added to the navigation history.
|
||||
editor.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
|
||||
editor.select_display_ranges(&[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)], cx);
|
||||
assert!(nav_history.pop_backward().is_none());
|
||||
assert!(nav_history.borrow_mut().pop_backward().is_none());
|
||||
|
||||
// Move the cursor a large distance.
|
||||
// The history can jump back to the previous position.
|
||||
editor.select_display_ranges(&[DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)], cx);
|
||||
let nav_entry = nav_history.pop_backward().unwrap();
|
||||
let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
|
||||
editor.navigate(nav_entry.data.unwrap(), cx);
|
||||
assert_eq!(nav_entry.item_view.id(), cx.view_id());
|
||||
assert_eq!(
|
||||
@ -4251,7 +4250,7 @@ mod tests {
|
||||
editor.selected_display_ranges(cx),
|
||||
&[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
|
||||
);
|
||||
assert!(nav_history.pop_backward().is_none());
|
||||
assert!(nav_history.borrow_mut().pop_backward().is_none());
|
||||
|
||||
// Move the cursor a large distance via the mouse.
|
||||
// The history can jump back to the previous position.
|
||||
@ -4261,7 +4260,7 @@ mod tests {
|
||||
editor.selected_display_ranges(cx),
|
||||
&[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
|
||||
);
|
||||
let nav_entry = nav_history.pop_backward().unwrap();
|
||||
let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
|
||||
editor.navigate(nav_entry.data.unwrap(), cx);
|
||||
assert_eq!(nav_entry.item_view.id(), cx.view_id());
|
||||
assert_eq!(
|
||||
|
@ -8,13 +8,14 @@ use language::{Bias, Buffer, Diagnostic};
|
||||
use postage::watch;
|
||||
use project::worktree::File;
|
||||
use project::{Project, ProjectEntry, ProjectPath};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::{fmt::Write, path::PathBuf};
|
||||
use text::{Point, Selection};
|
||||
use util::TryFutureExt;
|
||||
use workspace::{
|
||||
ItemHandle, ItemView, ItemViewHandle, NavHistory, PathOpener, Settings, StatusItemView,
|
||||
WeakItemHandle, Workspace,
|
||||
ItemHandle, ItemNavHistory, ItemView, ItemViewHandle, NavHistory, PathOpener, Settings,
|
||||
StatusItemView, WeakItemHandle, Workspace,
|
||||
};
|
||||
|
||||
pub struct BufferOpener;
|
||||
@ -46,7 +47,7 @@ impl ItemHandle for BufferItemHandle {
|
||||
&self,
|
||||
window_id: usize,
|
||||
workspace: &Workspace,
|
||||
nav_history: Rc<NavHistory>,
|
||||
nav_history: Rc<RefCell<NavHistory>>,
|
||||
cx: &mut MutableAppContext,
|
||||
) -> Box<dyn ItemViewHandle> {
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(self.0.clone(), cx));
|
||||
@ -57,7 +58,7 @@ impl ItemHandle for BufferItemHandle {
|
||||
crate::settings_builder(weak_buffer, workspace.settings()),
|
||||
cx,
|
||||
);
|
||||
editor.nav_history = Some(nav_history);
|
||||
editor.nav_history = Some(ItemNavHistory::new(nav_history, &cx.handle()));
|
||||
editor
|
||||
}))
|
||||
}
|
||||
|
@ -76,14 +76,16 @@ pub struct Pane {
|
||||
item_views: Vec<(usize, Box<dyn ItemViewHandle>)>,
|
||||
active_item_index: usize,
|
||||
settings: watch::Receiver<Settings>,
|
||||
nav_history: Rc<NavHistory>,
|
||||
nav_history: Rc<RefCell<NavHistory>>,
|
||||
}
|
||||
|
||||
pub struct ItemNavHistory {
|
||||
history: Rc<RefCell<NavHistory>>,
|
||||
item_view: Rc<dyn WeakItemViewHandle>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct NavHistory(RefCell<NavHistoryState>);
|
||||
|
||||
#[derive(Default)]
|
||||
struct NavHistoryState {
|
||||
pub struct NavHistory {
|
||||
mode: NavigationMode,
|
||||
backward_stack: VecDeque<NavigationEntry>,
|
||||
forward_stack: VecDeque<NavigationEntry>,
|
||||
@ -104,7 +106,7 @@ impl Default for NavigationMode {
|
||||
}
|
||||
|
||||
pub struct NavigationEntry {
|
||||
pub item_view: Box<dyn WeakItemViewHandle>,
|
||||
pub item_view: Rc<dyn WeakItemViewHandle>,
|
||||
pub data: Option<Box<dyn Any>>,
|
||||
}
|
||||
|
||||
@ -148,7 +150,7 @@ impl Pane {
|
||||
) -> Task<()> {
|
||||
let to_load = pane.update(cx, |pane, cx| {
|
||||
// Retrieve the weak item handle from the history.
|
||||
let nav_entry = pane.nav_history.pop(mode)?;
|
||||
let nav_entry = pane.nav_history.borrow_mut().pop(mode)?;
|
||||
|
||||
// If the item is still present in this pane, then activate it.
|
||||
if let Some(index) = nav_entry
|
||||
@ -157,9 +159,11 @@ impl Pane {
|
||||
.and_then(|v| pane.index_for_item_view(v.as_ref()))
|
||||
{
|
||||
if let Some(item_view) = pane.active_item() {
|
||||
pane.nav_history.set_mode(mode);
|
||||
pane.nav_history.borrow_mut().set_mode(mode);
|
||||
item_view.deactivated(cx);
|
||||
pane.nav_history.set_mode(NavigationMode::Normal);
|
||||
pane.nav_history
|
||||
.borrow_mut()
|
||||
.set_mode(NavigationMode::Normal);
|
||||
}
|
||||
|
||||
pane.active_item_index = index;
|
||||
@ -174,7 +178,6 @@ impl Pane {
|
||||
// project path in order to reopen it.
|
||||
else {
|
||||
pane.nav_history
|
||||
.0
|
||||
.borrow_mut()
|
||||
.project_entries_by_item
|
||||
.get(&nav_entry.item_view.id())
|
||||
@ -192,9 +195,11 @@ impl Pane {
|
||||
if let Some(pane) = cx.read(|cx| pane.upgrade(cx)) {
|
||||
if let Some(item) = item.log_err() {
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
pane.update(cx, |p, _| p.nav_history.set_mode(mode));
|
||||
pane.update(cx, |p, _| p.nav_history.borrow_mut().set_mode(mode));
|
||||
let item_view = workspace.open_item_in_pane(item, &pane, cx);
|
||||
pane.update(cx, |p, _| p.nav_history.set_mode(NavigationMode::Normal));
|
||||
pane.update(cx, |p, _| {
|
||||
p.nav_history.borrow_mut().set_mode(NavigationMode::Normal)
|
||||
});
|
||||
|
||||
if let Some(data) = nav_entry.data {
|
||||
item_view.navigate(data, cx);
|
||||
@ -322,7 +327,7 @@ impl Pane {
|
||||
item_view.deactivated(cx);
|
||||
}
|
||||
|
||||
let mut nav_history = self.nav_history.0.borrow_mut();
|
||||
let mut nav_history = self.nav_history.borrow_mut();
|
||||
if let Some(entry) = item_view.project_entry(cx) {
|
||||
nav_history
|
||||
.project_entries_by_item
|
||||
@ -538,16 +543,36 @@ impl View for Pane {
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemNavHistory {
|
||||
pub fn new<T: ItemView>(history: Rc<RefCell<NavHistory>>, item_view: &ViewHandle<T>) -> Self {
|
||||
Self {
|
||||
history,
|
||||
item_view: Rc::new(item_view.downgrade()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone<T: ItemView>(&self, item_view: &ViewHandle<T>) -> Self {
|
||||
Self {
|
||||
history: self.history.clone(),
|
||||
item_view: Rc::new(item_view.downgrade()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push<D: 'static + Any>(&self, data: Option<D>) {
|
||||
self.history.borrow_mut().push(data, self.item_view.clone());
|
||||
}
|
||||
}
|
||||
|
||||
impl NavHistory {
|
||||
pub fn pop_backward(&self) -> Option<NavigationEntry> {
|
||||
self.0.borrow_mut().backward_stack.pop_back()
|
||||
pub fn pop_backward(&mut self) -> Option<NavigationEntry> {
|
||||
self.backward_stack.pop_back()
|
||||
}
|
||||
|
||||
pub fn pop_forward(&self) -> Option<NavigationEntry> {
|
||||
self.0.borrow_mut().forward_stack.pop_back()
|
||||
pub fn pop_forward(&mut self) -> Option<NavigationEntry> {
|
||||
self.forward_stack.pop_back()
|
||||
}
|
||||
|
||||
fn pop(&self, mode: NavigationMode) -> Option<NavigationEntry> {
|
||||
fn pop(&mut self, mode: NavigationMode) -> Option<NavigationEntry> {
|
||||
match mode {
|
||||
NavigationMode::Normal => None,
|
||||
NavigationMode::GoingBack => self.pop_backward(),
|
||||
@ -555,38 +580,41 @@ impl NavHistory {
|
||||
}
|
||||
}
|
||||
|
||||
fn set_mode(&self, mode: NavigationMode) {
|
||||
self.0.borrow_mut().mode = mode;
|
||||
fn set_mode(&mut self, mode: NavigationMode) {
|
||||
self.mode = mode;
|
||||
}
|
||||
|
||||
pub fn push<D: 'static + Any, T: ItemView>(&self, data: Option<D>, cx: &mut ViewContext<T>) {
|
||||
let mut state = self.0.borrow_mut();
|
||||
match state.mode {
|
||||
pub fn push<D: 'static + Any>(
|
||||
&mut self,
|
||||
data: Option<D>,
|
||||
item_view: Rc<dyn WeakItemViewHandle>,
|
||||
) {
|
||||
match self.mode {
|
||||
NavigationMode::Normal => {
|
||||
if state.backward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN {
|
||||
state.backward_stack.pop_front();
|
||||
if self.backward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN {
|
||||
self.backward_stack.pop_front();
|
||||
}
|
||||
state.backward_stack.push_back(NavigationEntry {
|
||||
item_view: Box::new(cx.weak_handle()),
|
||||
self.backward_stack.push_back(NavigationEntry {
|
||||
item_view,
|
||||
data: data.map(|data| Box::new(data) as Box<dyn Any>),
|
||||
});
|
||||
state.forward_stack.clear();
|
||||
self.forward_stack.clear();
|
||||
}
|
||||
NavigationMode::GoingBack => {
|
||||
if state.forward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN {
|
||||
state.forward_stack.pop_front();
|
||||
if self.forward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN {
|
||||
self.forward_stack.pop_front();
|
||||
}
|
||||
state.forward_stack.push_back(NavigationEntry {
|
||||
item_view: Box::new(cx.weak_handle()),
|
||||
self.forward_stack.push_back(NavigationEntry {
|
||||
item_view,
|
||||
data: data.map(|data| Box::new(data) as Box<dyn Any>),
|
||||
});
|
||||
}
|
||||
NavigationMode::GoingForward => {
|
||||
if state.backward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN {
|
||||
state.backward_stack.pop_front();
|
||||
if self.backward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN {
|
||||
self.backward_stack.pop_front();
|
||||
}
|
||||
state.backward_stack.push_back(NavigationEntry {
|
||||
item_view: Box::new(cx.weak_handle()),
|
||||
self.backward_stack.push_back(NavigationEntry {
|
||||
item_view,
|
||||
data: data.map(|data| Box::new(data) as Box<dyn Any>),
|
||||
});
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ use status_bar::StatusBar;
|
||||
pub use status_bar::StatusItemView;
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
cell::RefCell,
|
||||
future::Future,
|
||||
hash::{Hash, Hasher},
|
||||
path::{Path, PathBuf},
|
||||
@ -141,7 +142,7 @@ pub trait Item: Entity + Sized {
|
||||
fn build_view(
|
||||
handle: ModelHandle<Self>,
|
||||
workspace: &Workspace,
|
||||
nav_history: Rc<NavHistory>,
|
||||
nav_history: ItemNavHistory,
|
||||
cx: &mut ViewContext<Self::View>,
|
||||
) -> Self::View;
|
||||
fn project_entry(&self) -> Option<ProjectEntry>;
|
||||
@ -205,7 +206,7 @@ pub trait ItemHandle: Send + Sync {
|
||||
&self,
|
||||
window_id: usize,
|
||||
workspace: &Workspace,
|
||||
nav_history: Rc<NavHistory>,
|
||||
nav_history: Rc<RefCell<NavHistory>>,
|
||||
cx: &mut MutableAppContext,
|
||||
) -> Box<dyn ItemViewHandle>;
|
||||
fn boxed_clone(&self) -> Box<dyn ItemHandle>;
|
||||
@ -258,10 +259,11 @@ impl<T: Item> ItemHandle for ModelHandle<T> {
|
||||
&self,
|
||||
window_id: usize,
|
||||
workspace: &Workspace,
|
||||
nav_history: Rc<NavHistory>,
|
||||
nav_history: Rc<RefCell<NavHistory>>,
|
||||
cx: &mut MutableAppContext,
|
||||
) -> Box<dyn ItemViewHandle> {
|
||||
Box::new(cx.add_view(window_id, |cx| {
|
||||
let nav_history = ItemNavHistory::new(nav_history, &cx.handle());
|
||||
T::build_view(self.clone(), workspace, nav_history, cx)
|
||||
}))
|
||||
}
|
||||
@ -292,7 +294,7 @@ impl ItemHandle for Box<dyn ItemHandle> {
|
||||
&self,
|
||||
window_id: usize,
|
||||
workspace: &Workspace,
|
||||
nav_history: Rc<NavHistory>,
|
||||
nav_history: Rc<RefCell<NavHistory>>,
|
||||
cx: &mut MutableAppContext,
|
||||
) -> Box<dyn ItemViewHandle> {
|
||||
ItemHandle::add_view(self.as_ref(), window_id, workspace, nav_history, cx)
|
||||
|
Loading…
Reference in New Issue
Block a user