preview tabs: Allow replacing preview tab when using code navigation (#10730)

This PR adds support for replacing the current preview tab when using
GoToDefinition. Previously a tab, that was navigated away from, was
converted into a permanent tab and the new tab was opened as preview.

Without `enable_preview_from_code_navigation`:


https://github.com/zed-industries/zed/assets/53836821/99840724-d6ff-4738-a9c4-ee71a0001634

With `enable_preview_from_code_navigation`:


https://github.com/zed-industries/zed/assets/53836821/8c60efcb-d597-40bf-b08b-13faf5a289b6

Note: In the future I would like to improve support for the navigation
history, because right now tabs that are not "normal" project items,
e.g. FindAllReferences cannot be reopened

Release Notes:

- Added support for replacing the current preview tab when using code
navigation (`enable_preview_from_code_navigation`)
This commit is contained in:
Bennet Bo Fenner 2024-04-29 20:47:01 +02:00 committed by GitHub
parent 9ff847753e
commit 20625e98ad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 120 additions and 60 deletions

View file

@ -331,8 +331,10 @@
// when you switch to another file unless you explicitly pin them. // when you switch to another file unless you explicitly pin them.
// This is useful for quickly viewing files without cluttering your workspace. // This is useful for quickly viewing files without cluttering your workspace.
"enabled": true, "enabled": true,
// Whether to open files in preview mode when selected from the file finder. // Whether to open tabs in preview mode when selected from the file finder.
"enable_preview_from_file_finder": false "enable_preview_from_file_finder": false,
// Whether a preview tab gets replaced when code navigation is used to navigate away from the tab.
"enable_preview_from_code_navigation": false
}, },
// Whether or not to remove any trailing whitespace from lines of a buffer // Whether or not to remove any trailing whitespace from lines of a buffer
// before saving it. // before saving it.

View file

@ -99,6 +99,7 @@ impl ActivityIndicator {
Box::new( Box::new(
cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx)), cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx)),
), ),
None,
cx, cx,
); );
} }

View file

@ -243,7 +243,7 @@ fn view_release_notes_locally(workspace: &mut Workspace, cx: &mut ViewContext<Wo
Some(tab_description), Some(tab_description),
cx, cx,
); );
workspace.add_item_to_active_pane(Box::new(view.clone()), cx); workspace.add_item_to_active_pane(Box::new(view.clone()), None, cx);
cx.notify(); cx.notify();
}) })
.log_err(); .log_err();

View file

@ -310,7 +310,7 @@ async fn test_basic_following(
let multibuffer_editor_a = workspace_a.update(cx_a, |workspace, cx| { let multibuffer_editor_a = workspace_a.update(cx_a, |workspace, cx| {
let editor = let editor =
cx.new_view(|cx| Editor::for_multibuffer(multibuffer_a, Some(project_a.clone()), cx)); cx.new_view(|cx| Editor::for_multibuffer(multibuffer_a, Some(project_a.clone()), cx));
workspace.add_item_to_active_pane(Box::new(editor.clone()), cx); workspace.add_item_to_active_pane(Box::new(editor.clone()), None, cx);
editor editor
}); });
executor.run_until_parked(); executor.run_until_parked();

View file

@ -477,7 +477,7 @@ mod tests {
}); });
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {
workspace.add_item_to_active_pane(Box::new(editor.clone()), cx); workspace.add_item_to_active_pane(Box::new(editor.clone()), None, cx);
editor.update(cx, |editor, cx| editor.focus(cx)) editor.update(cx, |editor, cx| editor.focus(cx))
}); });

View file

@ -235,7 +235,7 @@ impl ProjectDiagnosticsEditor {
let diagnostics = cx.new_view(|cx| { let diagnostics = cx.new_view(|cx| {
ProjectDiagnosticsEditor::new(workspace.project().clone(), workspace_handle, cx) ProjectDiagnosticsEditor::new(workspace.project().clone(), workspace_handle, cx)
}); });
workspace.add_item_to_active_pane(Box::new(diagnostics), cx); workspace.add_item_to_active_pane(Box::new(diagnostics), None, cx);
} }
} }

View file

@ -130,7 +130,7 @@ use ui::{
Tooltip, Tooltip,
}; };
use util::{defer, maybe, post_inc, RangeExt, ResultExt, TryFutureExt}; use util::{defer, maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
use workspace::item::ItemHandle; use workspace::item::{ItemHandle, PreviewTabsSettings};
use workspace::notifications::NotificationId; use workspace::notifications::NotificationId;
use workspace::{ use workspace::{
searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace, WorkspaceId, searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace, WorkspaceId,
@ -1610,6 +1610,7 @@ impl Editor {
{ {
workspace.add_item_to_active_pane( workspace.add_item_to_active_pane(
Box::new(cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))), Box::new(cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
None,
cx, cx,
); );
} }
@ -3781,7 +3782,7 @@ impl Editor {
let project = workspace.project().clone(); let project = workspace.project().clone();
let editor = let editor =
cx.new_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx)); cx.new_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
workspace.add_item_to_active_pane(Box::new(editor.clone()), cx); workspace.add_item_to_active_pane(Box::new(editor.clone()), None, cx);
editor.update(cx, |editor, cx| { editor.update(cx, |editor, cx| {
editor.highlight_background::<Self>( editor.highlight_background::<Self>(
&ranges_to_highlight, &ranges_to_highlight,
@ -8102,14 +8103,23 @@ impl Editor {
cx, cx,
); );
}); });
let item = Box::new(editor); let item = Box::new(editor);
let item_id = item.item_id();
if split { if split {
workspace.split_item(SplitDirection::Right, item.clone(), cx); workspace.split_item(SplitDirection::Right, item.clone(), cx);
} else { } else {
workspace.add_item_to_active_pane(item.clone(), cx); let destination_index = workspace.active_pane().update(cx, |pane, cx| {
if PreviewTabsSettings::get_global(cx).enable_preview_from_code_navigation {
pane.close_current_preview_item(cx)
} else {
None
} }
workspace.active_pane().clone().update(cx, |pane, cx| { });
let item_id = item.item_id(); workspace.add_item_to_active_pane(item.clone(), destination_index, cx);
}
workspace.active_pane().update(cx, |pane, cx| {
pane.set_preview_item_id(Some(item_id), cx); pane.set_preview_item_id(Some(item_id), cx);
}); });
} }

View file

@ -9161,7 +9161,7 @@ async fn test_mutlibuffer_in_navigation_history(cx: &mut gpui::TestAppContext) {
workspace.active_item(cx).is_none(), workspace.active_item(cx).is_none(),
"active item should be None before the first item is added" "active item should be None before the first item is added"
); );
workspace.add_item_to_active_pane(Box::new(multi_buffer_editor.clone()), cx); workspace.add_item_to_active_pane(Box::new(multi_buffer_editor.clone()), None, cx);
let active_item = workspace let active_item = workspace
.active_item(cx) .active_item(cx)
.expect("should have an active item after adding the multi buffer"); .expect("should have an active item after adding the multi buffer");

View file

@ -106,6 +106,7 @@ pub fn expand_macro_recursively(
}); });
workspace.add_item_to_active_pane( workspace.add_item_to_active_pane(
Box::new(cx.new_view(|cx| Editor::for_multibuffer(buffer, Some(project), cx))), Box::new(cx.new_view(|cx| Editor::for_multibuffer(buffer, Some(project), cx))),
None,
cx, cx,
); );
}) })

View file

@ -45,7 +45,7 @@ pub fn init(cx: &mut AppContext) {
workspace.activate_item(&existing, cx); workspace.activate_item(&existing, cx);
} else { } else {
let extensions_page = ExtensionsPage::new(workspace, cx); let extensions_page = ExtensionsPage::new(workspace, cx);
workspace.add_item_to_active_pane(Box::new(extensions_page), cx) workspace.add_item_to_active_pane(Box::new(extensions_page), None, cx)
} }
}) })
.register_action(move |_, _: &InstallDevExtension, cx| { .register_action(move |_, _: &InstallDevExtension, cx| {

View file

@ -97,6 +97,7 @@ pub fn init(cx: &mut AppContext) {
Box::new(cx.new_view(|cx| { Box::new(cx.new_view(|cx| {
LspLogView::new(workspace.project().clone(), log_store.clone(), cx) LspLogView::new(workspace.project().clone(), log_store.clone(), cx)
})), })),
None,
cx, cx,
); );
} }

View file

@ -738,7 +738,7 @@ impl ProjectSearchView {
let model = cx.new_model(|cx| ProjectSearch::new(workspace.project().clone(), cx)); let model = cx.new_model(|cx| ProjectSearch::new(workspace.project().clone(), cx));
let search = cx.new_view(|cx| ProjectSearchView::new(model, cx, None)); let search = cx.new_view(|cx| ProjectSearchView::new(model, cx, None));
workspace.add_item_to_active_pane(Box::new(search.clone()), cx); workspace.add_item_to_active_pane(Box::new(search.clone()), None, cx);
search.update(cx, |search, cx| { search.update(cx, |search, cx| {
search search
.included_files_editor .included_files_editor
@ -789,6 +789,7 @@ impl ProjectSearchView {
}); });
workspace.add_item_to_active_pane( workspace.add_item_to_active_pane(
Box::new(cx.new_view(|cx| ProjectSearchView::new(model, cx, None))), Box::new(cx.new_view(|cx| ProjectSearchView::new(model, cx, None))),
None,
cx, cx,
); );
} }
@ -838,7 +839,7 @@ impl ProjectSearchView {
let model = cx.new_model(|cx| ProjectSearch::new(workspace.project().clone(), cx)); let model = cx.new_model(|cx| ProjectSearch::new(workspace.project().clone(), cx));
let view = cx.new_view(|cx| ProjectSearchView::new(model, cx, settings)); let view = cx.new_view(|cx| ProjectSearchView::new(model, cx, settings));
workspace.add_item_to_active_pane(Box::new(view.clone()), cx); workspace.add_item_to_active_pane(Box::new(view.clone()), None, cx);
view view
}; };

View file

@ -134,7 +134,7 @@ impl TerminalView {
cx, cx,
) )
}); });
workspace.add_item_to_active_pane(Box::new(view), cx) workspace.add_item_to_active_pane(Box::new(view), None, cx)
} }
} }

View file

@ -29,7 +29,7 @@ pub fn init(cx: &mut AppContext) {
cx.observe_new_views(|workspace: &mut Workspace, _cx| { cx.observe_new_views(|workspace: &mut Workspace, _cx| {
workspace.register_action(|workspace, _: &Welcome, cx| { workspace.register_action(|workspace, _: &Welcome, cx| {
let welcome_page = WelcomePage::new(workspace, cx); let welcome_page = WelcomePage::new(workspace, cx);
workspace.add_item_to_active_pane(Box::new(welcome_page), cx) workspace.add_item_to_active_pane(Box::new(welcome_page), None, cx)
}); });
}) })
.detach(); .detach();

View file

@ -45,6 +45,7 @@ pub struct ItemSettings {
pub struct PreviewTabsSettings { pub struct PreviewTabsSettings {
pub enabled: bool, pub enabled: bool,
pub enable_preview_from_file_finder: bool, pub enable_preview_from_file_finder: bool,
pub enable_preview_from_code_navigation: bool,
} }
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
@ -78,15 +79,19 @@ pub struct ItemSettingsContent {
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
pub struct PreviewTabsSettingsContent { pub struct PreviewTabsSettingsContent {
/// Whether to show opened editors as preview editors. /// Whether to show opened editors as preview tabs.
/// Preview editors do not stay open, are reused until explicitly set to be kept open opened (via double-click or editing) and show file names in italic. /// Preview tabs do not stay open, are reused until explicitly set to be kept open opened (via double-click or editing) and show file names in italic.
/// ///
/// Default: true /// Default: true
enabled: Option<bool>, enabled: Option<bool>,
/// Whether to open a preview editor when opening a file using the file finder. /// Whether to open tabs in preview mode when selected from the file finder.
/// ///
/// Default: false /// Default: false
enable_preview_from_file_finder: Option<bool>, enable_preview_from_file_finder: Option<bool>,
/// Whether a preview tab gets replaced when code navigation is used to navigate away from the tab.
///
/// Default: false
enable_preview_from_code_navigation: Option<bool>,
} }
impl Settings for ItemSettings { impl Settings for ItemSettings {

View file

@ -623,21 +623,13 @@ impl Pane {
self.activate_item(index, focus_item, focus_item, cx); self.activate_item(index, focus_item, focus_item, cx);
existing_item existing_item
} else { } else {
let mut destination_index = None;
if allow_preview {
// If we are opening a new item as preview and we have an existing preview tab, remove it.
if let Some(item_idx) = self.preview_item_idx() {
let prev_active_item_index = self.active_item_index;
self.remove_item(item_idx, false, false, cx);
self.active_item_index = prev_active_item_index;
// If the item is being opened as preview and we have an existing preview tab, // If the item is being opened as preview and we have an existing preview tab,
// open the new item in the position of the existing preview tab. // open the new item in the position of the existing preview tab.
if item_idx < self.items.len() { let destination_index = if allow_preview {
destination_index = Some(item_idx); self.close_current_preview_item(cx)
} } else {
} None
} };
let new_item = build_item(cx); let new_item = build_item(cx);
@ -651,6 +643,22 @@ impl Pane {
} }
} }
pub fn close_current_preview_item(&mut self, cx: &mut ViewContext<Self>) -> Option<usize> {
let Some(item_idx) = self.preview_item_idx() else {
return None;
};
let prev_active_item_index = self.active_item_index;
self.remove_item(item_idx, false, false, cx);
self.active_item_index = prev_active_item_index;
if item_idx < self.items.len() {
Some(item_idx)
} else {
None
}
}
pub fn add_item( pub fn add_item(
&mut self, &mut self,
item: Box<dyn ItemHandle>, item: Box<dyn ItemHandle>,

View file

@ -2061,14 +2061,20 @@ impl Workspace {
} }
} }
pub fn add_item_to_active_pane(&mut self, item: Box<dyn ItemHandle>, cx: &mut WindowContext) { pub fn add_item_to_active_pane(
self.add_item(self.active_pane.clone(), item, cx) &mut self,
item: Box<dyn ItemHandle>,
destination_index: Option<usize>,
cx: &mut WindowContext,
) {
self.add_item(self.active_pane.clone(), item, destination_index, cx)
} }
pub fn add_item( pub fn add_item(
&mut self, &mut self,
pane: View<Pane>, pane: View<Pane>,
item: Box<dyn ItemHandle>, item: Box<dyn ItemHandle>,
destination_index: Option<usize>,
cx: &mut WindowContext, cx: &mut WindowContext,
) { ) {
if let Some(text) = item.telemetry_event_text(cx) { if let Some(text) = item.telemetry_event_text(cx) {
@ -2077,7 +2083,9 @@ impl Workspace {
.report_app_event(format!("{}: open", text)); .report_app_event(format!("{}: open", text));
} }
pane.update(cx, |pane, cx| pane.add_item(item, true, true, None, cx)); pane.update(cx, |pane, cx| {
pane.add_item(item, true, true, destination_index, cx)
});
} }
pub fn split_item( pub fn split_item(
@ -2087,7 +2095,7 @@ impl Workspace {
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) { ) {
let new_pane = self.split_pane(self.active_pane.clone(), split_direction, cx); let new_pane = self.split_pane(self.active_pane.clone(), split_direction, cx);
self.add_item(new_pane, item, cx); self.add_item(new_pane, item, None, cx);
} }
pub fn open_abs_path( pub fn open_abs_path(
@ -2259,10 +2267,21 @@ impl Workspace {
} }
let item = cx.new_view(|cx| T::for_project_item(self.project().clone(), project_item, cx)); let item = cx.new_view(|cx| T::for_project_item(self.project().clone(), project_item, cx));
let item_id = item.item_id();
let mut destination_index = None;
pane.update(cx, |pane, cx| { pane.update(cx, |pane, cx| {
if PreviewTabsSettings::get_global(cx).enable_preview_from_code_navigation {
if let Some(preview_item_id) = pane.preview_item_id() {
if preview_item_id != item_id {
destination_index = pane.close_current_preview_item(cx);
}
}
}
pane.set_preview_item_id(Some(item.item_id()), cx) pane.set_preview_item_id(Some(item.item_id()), cx)
}); });
self.add_item(pane, Box::new(item.clone()), cx);
self.add_item(pane, Box::new(item.clone()), destination_index, cx);
item item
} }
@ -5157,7 +5176,7 @@ mod tests {
item item
}); });
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {
workspace.add_item_to_active_pane(Box::new(item1.clone()), cx); workspace.add_item_to_active_pane(Box::new(item1.clone()), None, cx);
}); });
item1.update(cx, |item, _| assert_eq!(item.tab_detail.get(), Some(0))); item1.update(cx, |item, _| assert_eq!(item.tab_detail.get(), Some(0)));
@ -5169,7 +5188,7 @@ mod tests {
item item
}); });
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {
workspace.add_item_to_active_pane(Box::new(item2.clone()), cx); workspace.add_item_to_active_pane(Box::new(item2.clone()), None, cx);
}); });
item1.update(cx, |item, _| assert_eq!(item.tab_detail.get(), Some(1))); item1.update(cx, |item, _| assert_eq!(item.tab_detail.get(), Some(1)));
item2.update(cx, |item, _| assert_eq!(item.tab_detail.get(), Some(1))); item2.update(cx, |item, _| assert_eq!(item.tab_detail.get(), Some(1)));
@ -5183,7 +5202,7 @@ mod tests {
item item
}); });
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {
workspace.add_item_to_active_pane(Box::new(item3.clone()), cx); workspace.add_item_to_active_pane(Box::new(item3.clone()), None, cx);
}); });
item1.update(cx, |item, _| assert_eq!(item.tab_detail.get(), Some(1))); item1.update(cx, |item, _| assert_eq!(item.tab_detail.get(), Some(1)));
item2.update(cx, |item, _| assert_eq!(item.tab_detail.get(), Some(3))); item2.update(cx, |item, _| assert_eq!(item.tab_detail.get(), Some(3)));
@ -5227,7 +5246,7 @@ mod tests {
// Add an item to an empty pane // Add an item to an empty pane
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {
workspace.add_item_to_active_pane(Box::new(item1), cx) workspace.add_item_to_active_pane(Box::new(item1), None, cx)
}); });
project.update(cx, |project, cx| { project.update(cx, |project, cx| {
assert_eq!( assert_eq!(
@ -5241,7 +5260,7 @@ mod tests {
// Add a second item to a non-empty pane // Add a second item to a non-empty pane
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {
workspace.add_item_to_active_pane(Box::new(item2), cx) workspace.add_item_to_active_pane(Box::new(item2), None, cx)
}); });
assert_eq!(cx.window_title().as_deref(), Some("two.txt — root1")); assert_eq!(cx.window_title().as_deref(), Some("two.txt — root1"));
project.update(cx, |project, cx| { project.update(cx, |project, cx| {
@ -5296,7 +5315,7 @@ mod tests {
// When there are no dirty items, there's nothing to do. // When there are no dirty items, there's nothing to do.
let item1 = cx.new_view(|cx| TestItem::new(cx)); let item1 = cx.new_view(|cx| TestItem::new(cx));
workspace.update(cx, |w, cx| { workspace.update(cx, |w, cx| {
w.add_item_to_active_pane(Box::new(item1.clone()), cx) w.add_item_to_active_pane(Box::new(item1.clone()), None, cx)
}); });
let task = workspace.update(cx, |w, cx| w.prepare_to_close(false, cx)); let task = workspace.update(cx, |w, cx| w.prepare_to_close(false, cx));
assert!(task.await.unwrap()); assert!(task.await.unwrap());
@ -5310,8 +5329,8 @@ mod tests {
.with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]) .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)])
}); });
workspace.update(cx, |w, cx| { workspace.update(cx, |w, cx| {
w.add_item_to_active_pane(Box::new(item2.clone()), cx); w.add_item_to_active_pane(Box::new(item2.clone()), None, cx);
w.add_item_to_active_pane(Box::new(item3.clone()), cx); w.add_item_to_active_pane(Box::new(item3.clone()), None, cx);
}); });
let task = workspace.update(cx, |w, cx| w.prepare_to_close(false, cx)); let task = workspace.update(cx, |w, cx| w.prepare_to_close(false, cx));
cx.executor().run_until_parked(); cx.executor().run_until_parked();
@ -5355,10 +5374,10 @@ mod tests {
.with_project_items(&[TestProjectItem::new_untitled(cx)]) .with_project_items(&[TestProjectItem::new_untitled(cx)])
}); });
let pane = workspace.update(cx, |workspace, cx| { let pane = workspace.update(cx, |workspace, cx| {
workspace.add_item_to_active_pane(Box::new(item1.clone()), cx); workspace.add_item_to_active_pane(Box::new(item1.clone()), None, cx);
workspace.add_item_to_active_pane(Box::new(item2.clone()), cx); workspace.add_item_to_active_pane(Box::new(item2.clone()), None, cx);
workspace.add_item_to_active_pane(Box::new(item3.clone()), cx); workspace.add_item_to_active_pane(Box::new(item3.clone()), None, cx);
workspace.add_item_to_active_pane(Box::new(item4.clone()), cx); workspace.add_item_to_active_pane(Box::new(item4.clone()), None, cx);
workspace.active_pane().clone() workspace.active_pane().clone()
}); });
@ -5480,9 +5499,9 @@ mod tests {
// multi-entry items: (3, 4) // multi-entry items: (3, 4)
let left_pane = workspace.update(cx, |workspace, cx| { let left_pane = workspace.update(cx, |workspace, cx| {
let left_pane = workspace.active_pane().clone(); let left_pane = workspace.active_pane().clone();
workspace.add_item_to_active_pane(Box::new(item_2_3.clone()), cx); workspace.add_item_to_active_pane(Box::new(item_2_3.clone()), None, cx);
for item in single_entry_items { for item in single_entry_items {
workspace.add_item_to_active_pane(Box::new(item), cx); workspace.add_item_to_active_pane(Box::new(item), None, cx);
} }
left_pane.update(cx, |pane, cx| { left_pane.update(cx, |pane, cx| {
pane.activate_item(2, true, true, cx); pane.activate_item(2, true, true, cx);
@ -5553,7 +5572,7 @@ mod tests {
}); });
let item_id = item.entity_id(); let item_id = item.entity_id();
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {
workspace.add_item_to_active_pane(Box::new(item.clone()), cx); workspace.add_item_to_active_pane(Box::new(item.clone()), None, cx);
}); });
// Autosave on window change. // Autosave on window change.
@ -5638,7 +5657,7 @@ mod tests {
// Add the item again, ensuring autosave is prevented if the underlying file has been deleted. // Add the item again, ensuring autosave is prevented if the underlying file has been deleted.
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {
workspace.add_item_to_active_pane(Box::new(item.clone()), cx); workspace.add_item_to_active_pane(Box::new(item.clone()), None, cx);
}); });
item.update(cx, |item, cx| { item.update(cx, |item, cx| {
item.project_items[0].update(cx, |item, _| { item.project_items[0].update(cx, |item, _| {
@ -5676,7 +5695,7 @@ mod tests {
let toolbar_notify_count = Rc::new(RefCell::new(0)); let toolbar_notify_count = Rc::new(RefCell::new(0));
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {
workspace.add_item_to_active_pane(Box::new(item.clone()), cx); workspace.add_item_to_active_pane(Box::new(item.clone()), None, cx);
let toolbar_notification_count = toolbar_notify_count.clone(); let toolbar_notification_count = toolbar_notify_count.clone();
cx.observe(&toolbar, move |_, _, _| { cx.observe(&toolbar, move |_, _, _| {
*toolbar_notification_count.borrow_mut() += 1 *toolbar_notification_count.borrow_mut() += 1

View file

@ -618,7 +618,7 @@ fn open_log_file(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
}) })
}); });
workspace.add_item_to_active_pane(Box::new(editor), cx); workspace.add_item_to_active_pane(Box::new(editor), None, cx);
}) })
.log_err(); .log_err();
}) })
@ -837,7 +837,7 @@ fn open_telemetry_log_file(workspace: &mut Workspace, cx: &mut ViewContext<Works
}); });
workspace.add_item_to_active_pane( workspace.add_item_to_active_pane(
Box::new(cx.new_view(|cx| Editor::for_multibuffer(buffer, Some(project), cx))), Box::new(cx.new_view(|cx| Editor::for_multibuffer(buffer, Some(project), cx))),
cx, None,cx,
); );
}).log_err()?; }).log_err()?;
@ -873,6 +873,7 @@ fn open_bundled_file(
Box::new(cx.new_view(|cx| { Box::new(cx.new_view(|cx| {
Editor::for_multibuffer(buffer, Some(project.clone()), cx) Editor::for_multibuffer(buffer, Some(project.clone()), cx)
})), })),
None,
cx, cx,
); );
}) })

View file

@ -809,7 +809,8 @@ These values take in the same options as the root-level settings with the same n
```json ```json
"preview_tabs": { "preview_tabs": {
"enabled": true, "enabled": true,
"enable_preview_from_file_finder": false "enable_preview_from_file_finder": false,
"enable_preview_from_code_navigation": false,
} }
``` ```
@ -823,6 +824,16 @@ These values take in the same options as the root-level settings with the same n
`boolean` values `boolean` values
### Enable preview from code navigation
- Description: Determines whether a preview tab gets replaced when code navigation is used to navigate away from the tab (requires Zed `0.134.x`).
- Setting: `enable_preview_from_code_navigation`
- Default: `false`
**Options**
`boolean` values
## Preferred Line Length ## Preferred Line Length
- Description: The column at which to soft-wrap lines, for buffers where soft-wrap is enabled. - Description: The column at which to soft-wrap lines, for buffers where soft-wrap is enabled.