editor: Add minimap (#26893)
## Overview This PR adds the minimap feature to the Zed editor, closely following the [design from Visual Studio Code](https://code.visualstudio.com/docs/getstarted/userinterface#_minimap). When configured, a second instance of the editor will appear to the left of the scrollbar. This instance is not interactive and it has a slimmed down set of annotations, but it is otherwise just a zoomed-out version of the main editor instance. A thumb shows the line boundaries of the main viewport, as well as the progress through the document. Clicking on a section of code in the minimap will jump the editor to that code. Dragging the thumb will act like the scrollbar, moving sequentially through the document.  ## New settings This adds a `minimap` section to the editor settings with the following keys: ### `show` When to show the minimap in the editor. This setting can take three values: 1. Show the minimap if the editor's scrollbar is visible: `"auto"` 2. Always show the minimap: `"always"` 3. Never show the minimap: `"never"` (default) ### `thumb` When to show the minimap thumb. This setting can take two values: 1. Show the minimap thumb if the mouse is over the minimap: `"hover"` 2. Always show the minimap thumb: `"always"` (default) ### `width` The width of the minimap in pixels. Default: `100` ### `font_size` The font size of the minimap in pixels. Default: `2` ## Providing feedback In order to keep the PR focused on development updates, please use the discussion thread for feature suggestions and usability feedback: #26894 ## Features left to add - [x] fix scrolling performance - [x] user settings for enable/disable, width, text size, etc. - [x] show overview of visible lines in minimap - [x] clicking on minimap should navigate to the corresponding section of code - ~[ ] more prominent highlighting in the minimap editor~ - ~[ ] override scrollbar auto setting to always when minimap is set to always show~ Release Notes: - Added minimap for high-level overview and quick navigation of editor contents. --------- Co-authored-by: MrSubidubi <dev@bahn.sh> Co-authored-by: Kirill Bulatov <kirill@zed.dev>
This commit is contained in:
parent
902931fdfc
commit
607a9445fc
21 changed files with 1083 additions and 216 deletions
|
@ -193,6 +193,7 @@ pub struct CustomBlock {
|
|||
style: BlockStyle,
|
||||
render: Arc<Mutex<RenderBlock>>,
|
||||
priority: usize,
|
||||
pub(crate) render_in_minimap: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -204,6 +205,7 @@ pub struct BlockProperties<P> {
|
|||
pub style: BlockStyle,
|
||||
pub render: RenderBlock,
|
||||
pub priority: usize,
|
||||
pub render_in_minimap: bool,
|
||||
}
|
||||
|
||||
impl<P: Debug> Debug for BlockProperties<P> {
|
||||
|
@ -223,6 +225,12 @@ pub enum BlockStyle {
|
|||
Sticky,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct EditorMargins {
|
||||
pub gutter: GutterDimensions,
|
||||
pub right: Pixels,
|
||||
}
|
||||
|
||||
#[derive(gpui::AppContext, gpui::VisualContext)]
|
||||
pub struct BlockContext<'a, 'b> {
|
||||
#[window]
|
||||
|
@ -231,7 +239,7 @@ pub struct BlockContext<'a, 'b> {
|
|||
pub app: &'b mut App,
|
||||
pub anchor_x: Pixels,
|
||||
pub max_width: Pixels,
|
||||
pub gutter_dimensions: &'b GutterDimensions,
|
||||
pub margins: &'b EditorMargins,
|
||||
pub em_width: Pixels,
|
||||
pub line_height: Pixels,
|
||||
pub block_id: BlockId,
|
||||
|
@ -1037,6 +1045,7 @@ impl BlockMapWriter<'_> {
|
|||
render: Arc::new(Mutex::new(block.render)),
|
||||
style: block.style,
|
||||
priority: block.priority,
|
||||
render_in_minimap: block.render_in_minimap,
|
||||
});
|
||||
self.0.custom_blocks.insert(block_ix, new_block.clone());
|
||||
self.0.custom_blocks_by_id.insert(id, new_block);
|
||||
|
@ -1071,6 +1080,7 @@ impl BlockMapWriter<'_> {
|
|||
style: block.style,
|
||||
render: block.render.clone(),
|
||||
priority: block.priority,
|
||||
render_in_minimap: block.render_in_minimap,
|
||||
};
|
||||
let new_block = Arc::new(new_block);
|
||||
*block = new_block.clone();
|
||||
|
@ -1967,6 +1977,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
|
@ -1974,6 +1985,7 @@ mod tests {
|
|||
height: Some(2),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
|
@ -1981,6 +1993,7 @@ mod tests {
|
|||
height: Some(3),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -2205,6 +2218,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
|
@ -2212,6 +2226,7 @@ mod tests {
|
|||
height: Some(2),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
|
@ -2219,6 +2234,7 @@ mod tests {
|
|||
height: Some(3),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -2307,6 +2323,7 @@ mod tests {
|
|||
render: Arc::new(|_| div().into_any()),
|
||||
height: Some(1),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
|
@ -2314,6 +2331,7 @@ mod tests {
|
|||
render: Arc::new(|_| div().into_any()),
|
||||
height: Some(1),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -2353,6 +2371,7 @@ mod tests {
|
|||
height: Some(4),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
}])[0];
|
||||
|
||||
let blocks_snapshot = block_map.read(wraps_snapshot, Default::default());
|
||||
|
@ -2406,6 +2425,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
|
@ -2413,6 +2433,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
|
@ -2420,6 +2441,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
]);
|
||||
let blocks_snapshot = block_map.read(wraps_snapshot.clone(), Default::default());
|
||||
|
@ -2434,6 +2456,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
|
@ -2441,6 +2464,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
|
@ -2448,6 +2472,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
]);
|
||||
let blocks_snapshot = block_map.read(wraps_snapshot.clone(), Default::default());
|
||||
|
@ -2547,6 +2572,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
|
@ -2554,6 +2580,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
|
@ -2561,6 +2588,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
]);
|
||||
let excerpt_blocks_3 = writer.insert(vec![
|
||||
|
@ -2570,6 +2598,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
|
@ -2577,6 +2606,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -2624,6 +2654,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
}]);
|
||||
let blocks_snapshot = block_map.read(wrap_snapshot.clone(), Patch::default());
|
||||
let blocks = blocks_snapshot
|
||||
|
@ -2981,6 +3012,7 @@ mod tests {
|
|||
height: Some(height),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -3001,6 +3033,7 @@ mod tests {
|
|||
style: props.style,
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
}));
|
||||
|
||||
for (block_properties, block_id) in block_properties.iter().zip(block_ids) {
|
||||
|
@ -3525,6 +3558,7 @@ mod tests {
|
|||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
}])[0];
|
||||
|
||||
let blocks_snapshot = block_map.read(wraps_snapshot.clone(), Default::default());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue