editor: Add in_preview boolean context for keybindings (#61777)
# Objective - Add an `in_preview` context that is available when the current editor is in preview mode (opened from project panel or go to definition). - closes https://github.com/zed-industries/zed/discussions/61765 ## Solution - In `editor.rs`, added a check in `key_context()` that detects if the editor is the active preview item in its pane, and if so, adds `"in_preview"` to the key context. - Uses existing `workspace.pane_for_item_id()` and `pane.is_active_preview_item()` methods — no new APIs introduced. ## Testing - Added two tests in `editor_tests.rs`: - `test_in_preview_context_added_when_in_preview_mode` — verifies `in_preview` is present when editor is set as preview item. - `test_in_preview_context_not_added_when_not_in_preview_mode` — verifies `in_preview` is absent for regular (non-preview) tabs. - Tested on Linux. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable --- Release Notes: - Added `in_preview` keybinding context for when an editor is in preview mode.
This commit is contained in:
1 parent
1155a5becd
commit
459fe185a4
3 files changed
+85
-3
No files matched your search
@@ -2787,6 +2787,14 @@ impl Editor {
|
||||
key_context.add("diffs_expanded");
|
||||
}
|
||||
|
||||
if self
|
||||
.nav_history
|
||||
.as_ref()
|
||||
.is_some_and(ItemNavHistory::is_preview_item)
|
||||
{
|
||||
key_context.add("in_preview");
|
||||
}
|
||||
|
||||
key_context
|
||||
}
|
||||
|
||||
|
||||
@@ -43364,3 +43364,74 @@ async fn test_select_delimiters_expansion(cx: &mut TestAppContext) {
|
||||
cx.dispatch_action(SelectInsideDelimiters);
|
||||
cx.assert_editor_state("foo(«x, { a: 1 }ˇ»);");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_in_preview_key_context(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
cx.update(|cx| {
|
||||
SettingsStore::update_global(cx, |store, cx| {
|
||||
store.update_user_settings(cx, |settings: &mut SettingsContent| {
|
||||
settings.preview_tabs.get_or_insert_default().enabled = Some(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
path!("/root"),
|
||||
serde_json::json!({
|
||||
"test.txt": "hello",
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
let project = Project::test(fs, [path!("/root").as_ref()], cx).await;
|
||||
let (multi_workspace, cx) =
|
||||
cx.add_window_view(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
|
||||
let workspace = multi_workspace.read_with(cx, |mw, _| mw.workspace().clone());
|
||||
let worktree_id = workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().update(cx, |project, cx| {
|
||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||
})
|
||||
});
|
||||
|
||||
let editor = workspace
|
||||
.update_in(cx, |workspace, window, cx| {
|
||||
workspace.open_path_preview(
|
||||
(worktree_id, rel_path("test.txt")),
|
||||
None,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.unwrap()
|
||||
.await
|
||||
.downcast::<Editor>()
|
||||
.unwrap();
|
||||
|
||||
let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone());
|
||||
pane.read_with(cx, |pane, _| {
|
||||
assert!(pane.is_active_preview_item(editor.entity_id()));
|
||||
});
|
||||
|
||||
cx.focus(&editor);
|
||||
editor.update_in(cx, |editor, window, cx| {
|
||||
assert!(
|
||||
editor.key_context(window, cx).contains("in_preview"),
|
||||
"Expected 'in_preview' context when the editor is the pane's preview item"
|
||||
);
|
||||
});
|
||||
|
||||
pane.update(cx, |pane, _cx| {
|
||||
pane.unpreview_item_if_preview(editor.entity_id());
|
||||
});
|
||||
|
||||
editor.update_in(cx, |editor, window, cx| {
|
||||
assert!(
|
||||
!editor.key_context(window, cx).contains("in_preview"),
|
||||
"Expected no 'in_preview' context after the tab is unpreviewed"
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -4661,6 +4661,10 @@ impl Render for Pane {
|
||||
}
|
||||
|
||||
impl ItemNavHistory {
|
||||
pub fn is_preview_item(&self) -> bool {
|
||||
self.history.0.lock().preview_item_id == Some(self.item.id())
|
||||
}
|
||||
|
||||
pub fn push<D: 'static + Any + Send + Sync>(
|
||||
&mut self,
|
||||
data: Option<D>,
|
||||
@@ -4672,19 +4676,18 @@ impl ItemNavHistory {
|
||||
.upgrade()
|
||||
.is_some_and(|item| item.include_in_nav_history())
|
||||
{
|
||||
let is_preview_item = self.history.0.lock().preview_item_id == Some(self.item.id());
|
||||
let is_preview_item = self.is_preview_item();
|
||||
self.history
|
||||
.push(data, self.item.clone(), is_preview_item, row, cx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn navigation_entry(&self, data: Option<Arc<dyn Any + Send + Sync>>) -> NavigationEntry {
|
||||
let is_preview_item = self.history.0.lock().preview_item_id == Some(self.item.id());
|
||||
NavigationEntry {
|
||||
item: self.item.clone(),
|
||||
data,
|
||||
timestamp: 0,
|
||||
is_preview: is_preview_item,
|
||||
is_preview: self.is_preview_item(),
|
||||
row: None,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user