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
|
@ -356,6 +356,49 @@
|
||||||
"vertical": true
|
"vertical": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// Minimap related settings
|
||||||
|
"minimap": {
|
||||||
|
// 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)
|
||||||
|
"show": "never",
|
||||||
|
// 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)
|
||||||
|
"thumb": "always",
|
||||||
|
// How the minimap thumb border should look.
|
||||||
|
// This setting can take five values:
|
||||||
|
// 1. Display a border on all sides of the thumb:
|
||||||
|
// "thumb_border": "full"
|
||||||
|
// 2. Display a border on all sides except the left side of the thumb:
|
||||||
|
// "thumb_border": "left_open" (default)
|
||||||
|
// 3. Display a border on all sides except the right side of the thumb:
|
||||||
|
// "thumb_border": "right_open"
|
||||||
|
// 4. Display a border only on the left side of the thumb:
|
||||||
|
// "thumb_border": "left_only"
|
||||||
|
// 5. Display the thumb without any border:
|
||||||
|
// "thumb_border": "none"
|
||||||
|
"thumb_border": "left_open",
|
||||||
|
// How to highlight the current line in the minimap.
|
||||||
|
// This setting can take the following values:
|
||||||
|
//
|
||||||
|
// 1. `null` to inherit the editor `current_line_highlight` setting (default)
|
||||||
|
// 2. "line" or "all" to highlight the current line in the minimap.
|
||||||
|
// 3. "gutter" or "none" to not highlight the current line in the minimap.
|
||||||
|
"current_line_highlight": null,
|
||||||
|
// The width of the minimap in pixels.
|
||||||
|
"width": 100,
|
||||||
|
// The font size of the minimap in pixels.
|
||||||
|
"font_size": 2
|
||||||
|
},
|
||||||
// Enable middle-click paste on Linux.
|
// Enable middle-click paste on Linux.
|
||||||
"middle_click_paste": true,
|
"middle_click_paste": true,
|
||||||
// What to do when multibuffer is double clicked in some of its excerpts
|
// What to do when multibuffer is double clicked in some of its excerpts
|
||||||
|
|
|
@ -8,9 +8,10 @@ use anyhow::{Context as _, Result};
|
||||||
use assistant_settings::AssistantSettings;
|
use assistant_settings::AssistantSettings;
|
||||||
use client::telemetry::Telemetry;
|
use client::telemetry::Telemetry;
|
||||||
use collections::{HashMap, HashSet, VecDeque, hash_map};
|
use collections::{HashMap, HashSet, VecDeque, hash_map};
|
||||||
|
use editor::display_map::EditorMargins;
|
||||||
use editor::{
|
use editor::{
|
||||||
Anchor, AnchorRangeExt, CodeActionProvider, Editor, EditorEvent, ExcerptId, ExcerptRange,
|
Anchor, AnchorRangeExt, CodeActionProvider, Editor, EditorEvent, ExcerptId, ExcerptRange,
|
||||||
GutterDimensions, MultiBuffer, MultiBufferSnapshot, ToOffset as _, ToPoint,
|
MultiBuffer, MultiBufferSnapshot, ToOffset as _, ToPoint,
|
||||||
actions::SelectAll,
|
actions::SelectAll,
|
||||||
display_map::{
|
display_map::{
|
||||||
BlockContext, BlockPlacement, BlockProperties, BlockStyle, CustomBlockId, RenderBlock,
|
BlockContext, BlockPlacement, BlockProperties, BlockStyle, CustomBlockId, RenderBlock,
|
||||||
|
@ -458,11 +459,11 @@ impl InlineAssistant {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let gutter_dimensions = Arc::new(Mutex::new(GutterDimensions::default()));
|
let editor_margins = Arc::new(Mutex::new(EditorMargins::default()));
|
||||||
let prompt_editor = cx.new(|cx| {
|
let prompt_editor = cx.new(|cx| {
|
||||||
PromptEditor::new_buffer(
|
PromptEditor::new_buffer(
|
||||||
assist_id,
|
assist_id,
|
||||||
gutter_dimensions.clone(),
|
editor_margins,
|
||||||
self.prompt_history.clone(),
|
self.prompt_history.clone(),
|
||||||
prompt_buffer.clone(),
|
prompt_buffer.clone(),
|
||||||
codegen.clone(),
|
codegen.clone(),
|
||||||
|
@ -577,11 +578,11 @@ impl InlineAssistant {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let gutter_dimensions = Arc::new(Mutex::new(GutterDimensions::default()));
|
let editor_margins = Arc::new(Mutex::new(EditorMargins::default()));
|
||||||
let prompt_editor = cx.new(|cx| {
|
let prompt_editor = cx.new(|cx| {
|
||||||
PromptEditor::new_buffer(
|
PromptEditor::new_buffer(
|
||||||
assist_id,
|
assist_id,
|
||||||
gutter_dimensions.clone(),
|
editor_margins,
|
||||||
self.prompt_history.clone(),
|
self.prompt_history.clone(),
|
||||||
prompt_buffer.clone(),
|
prompt_buffer.clone(),
|
||||||
codegen.clone(),
|
codegen.clone(),
|
||||||
|
@ -650,6 +651,7 @@ impl InlineAssistant {
|
||||||
height: Some(prompt_editor_height),
|
height: Some(prompt_editor_height),
|
||||||
render: build_assist_editor_renderer(prompt_editor),
|
render: build_assist_editor_renderer(prompt_editor),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: false,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Sticky,
|
style: BlockStyle::Sticky,
|
||||||
|
@ -664,6 +666,7 @@ impl InlineAssistant {
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
}),
|
}),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1405,11 +1408,11 @@ impl InlineAssistant {
|
||||||
|
|
||||||
enum DeletedLines {}
|
enum DeletedLines {}
|
||||||
let mut editor = Editor::for_multibuffer(multi_buffer, None, window, cx);
|
let mut editor = Editor::for_multibuffer(multi_buffer, None, window, cx);
|
||||||
|
editor.disable_scrollbars_and_minimap(cx);
|
||||||
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::None, cx);
|
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::None, cx);
|
||||||
editor.set_show_wrap_guides(false, cx);
|
editor.set_show_wrap_guides(false, cx);
|
||||||
editor.set_show_gutter(false, cx);
|
editor.set_show_gutter(false, cx);
|
||||||
editor.scroll_manager.set_forbid_vertical_scroll(true);
|
editor.scroll_manager.set_forbid_vertical_scroll(true);
|
||||||
editor.set_show_scrollbars(false, cx);
|
|
||||||
editor.set_read_only(true);
|
editor.set_read_only(true);
|
||||||
editor.set_show_edit_predictions(Some(false), window, cx);
|
editor.set_show_edit_predictions(Some(false), window, cx);
|
||||||
editor.highlight_rows::<DeletedLines>(
|
editor.highlight_rows::<DeletedLines>(
|
||||||
|
@ -1433,11 +1436,12 @@ impl InlineAssistant {
|
||||||
.bg(cx.theme().status().deleted_background)
|
.bg(cx.theme().status().deleted_background)
|
||||||
.size_full()
|
.size_full()
|
||||||
.h(height as f32 * cx.window.line_height())
|
.h(height as f32 * cx.window.line_height())
|
||||||
.pl(cx.gutter_dimensions.full_width())
|
.pl(cx.margins.gutter.full_width())
|
||||||
.child(deleted_lines_editor.clone())
|
.child(deleted_lines_editor.clone())
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
}),
|
}),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1595,9 +1599,9 @@ fn build_assist_editor_renderer(editor: &Entity<PromptEditor<BufferCodegen>>) ->
|
||||||
let editor = editor.clone();
|
let editor = editor.clone();
|
||||||
|
|
||||||
Arc::new(move |cx: &mut BlockContext| {
|
Arc::new(move |cx: &mut BlockContext| {
|
||||||
let gutter_dimensions = editor.read(cx).gutter_dimensions();
|
let editor_margins = editor.read(cx).editor_margins();
|
||||||
|
|
||||||
*gutter_dimensions.lock() = *cx.gutter_dimensions;
|
*editor_margins.lock() = *cx.margins;
|
||||||
editor.clone().into_any_element()
|
editor.clone().into_any_element()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@ use crate::{CycleNextInlineAssist, CyclePreviousInlineAssist};
|
||||||
use crate::{RemoveAllContext, ToggleContextPicker};
|
use crate::{RemoveAllContext, ToggleContextPicker};
|
||||||
use client::ErrorExt;
|
use client::ErrorExt;
|
||||||
use collections::VecDeque;
|
use collections::VecDeque;
|
||||||
|
use editor::display_map::EditorMargins;
|
||||||
use editor::{
|
use editor::{
|
||||||
ContextMenuOptions, Editor, EditorElement, EditorEvent, EditorMode, EditorStyle,
|
ContextMenuOptions, Editor, EditorElement, EditorEvent, EditorMode, EditorStyle, MultiBuffer,
|
||||||
GutterDimensions, MultiBuffer,
|
|
||||||
actions::{MoveDown, MoveUp},
|
actions::{MoveDown, MoveUp},
|
||||||
};
|
};
|
||||||
use feature_flags::{FeatureFlagAppExt as _, ZedProFeatureFlag};
|
use feature_flags::{FeatureFlagAppExt as _, ZedProFeatureFlag};
|
||||||
|
@ -61,11 +61,13 @@ impl<T: 'static> Render for PromptEditor<T> {
|
||||||
let ui_font_size = ThemeSettings::get_global(cx).ui_font_size(cx);
|
let ui_font_size = ThemeSettings::get_global(cx).ui_font_size(cx);
|
||||||
let mut buttons = Vec::new();
|
let mut buttons = Vec::new();
|
||||||
|
|
||||||
let left_gutter_width = match &self.mode {
|
const RIGHT_PADDING: Pixels = px(9.);
|
||||||
|
|
||||||
|
let (left_gutter_width, right_padding) = match &self.mode {
|
||||||
PromptEditorMode::Buffer {
|
PromptEditorMode::Buffer {
|
||||||
id: _,
|
id: _,
|
||||||
codegen,
|
codegen,
|
||||||
gutter_dimensions,
|
editor_margins,
|
||||||
} => {
|
} => {
|
||||||
let codegen = codegen.read(cx);
|
let codegen = codegen.read(cx);
|
||||||
|
|
||||||
|
@ -73,13 +75,17 @@ impl<T: 'static> Render for PromptEditor<T> {
|
||||||
buttons.push(self.render_cycle_controls(&codegen, cx));
|
buttons.push(self.render_cycle_controls(&codegen, cx));
|
||||||
}
|
}
|
||||||
|
|
||||||
let gutter_dimensions = gutter_dimensions.lock();
|
let editor_margins = editor_margins.lock();
|
||||||
|
let gutter = editor_margins.gutter;
|
||||||
|
|
||||||
gutter_dimensions.full_width() + (gutter_dimensions.margin / 2.0)
|
let left_gutter_width = gutter.full_width() + (gutter.margin / 2.0);
|
||||||
|
let right_padding = editor_margins.right + RIGHT_PADDING;
|
||||||
|
|
||||||
|
(left_gutter_width, right_padding)
|
||||||
}
|
}
|
||||||
PromptEditorMode::Terminal { .. } => {
|
PromptEditorMode::Terminal { .. } => {
|
||||||
// Give the equivalent of the same left-padding that we're using on the right
|
// Give the equivalent of the same left-padding that we're using on the right
|
||||||
Pixels::from(40.0)
|
(Pixels::from(40.0), Pixels::from(24.))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,7 +106,7 @@ impl<T: 'static> Render for PromptEditor<T> {
|
||||||
.size_full()
|
.size_full()
|
||||||
.pt_0p5()
|
.pt_0p5()
|
||||||
.pb(bottom_padding)
|
.pb(bottom_padding)
|
||||||
.pr_6()
|
.pr(right_padding)
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.items_start()
|
.items_start()
|
||||||
|
@ -806,7 +812,7 @@ pub enum PromptEditorMode {
|
||||||
Buffer {
|
Buffer {
|
||||||
id: InlineAssistId,
|
id: InlineAssistId,
|
||||||
codegen: Entity<BufferCodegen>,
|
codegen: Entity<BufferCodegen>,
|
||||||
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
|
editor_margins: Arc<Mutex<EditorMargins>>,
|
||||||
},
|
},
|
||||||
Terminal {
|
Terminal {
|
||||||
id: TerminalInlineAssistId,
|
id: TerminalInlineAssistId,
|
||||||
|
@ -838,7 +844,7 @@ impl InlineAssistId {
|
||||||
impl PromptEditor<BufferCodegen> {
|
impl PromptEditor<BufferCodegen> {
|
||||||
pub fn new_buffer(
|
pub fn new_buffer(
|
||||||
id: InlineAssistId,
|
id: InlineAssistId,
|
||||||
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
|
editor_margins: Arc<Mutex<EditorMargins>>,
|
||||||
prompt_history: VecDeque<String>,
|
prompt_history: VecDeque<String>,
|
||||||
prompt_buffer: Entity<MultiBuffer>,
|
prompt_buffer: Entity<MultiBuffer>,
|
||||||
codegen: Entity<BufferCodegen>,
|
codegen: Entity<BufferCodegen>,
|
||||||
|
@ -855,7 +861,7 @@ impl PromptEditor<BufferCodegen> {
|
||||||
let mode = PromptEditorMode::Buffer {
|
let mode = PromptEditorMode::Buffer {
|
||||||
id,
|
id,
|
||||||
codegen,
|
codegen,
|
||||||
gutter_dimensions,
|
editor_margins,
|
||||||
};
|
};
|
||||||
|
|
||||||
let prompt_editor = cx.new(|cx| {
|
let prompt_editor = cx.new(|cx| {
|
||||||
|
@ -995,11 +1001,9 @@ impl PromptEditor<BufferCodegen> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gutter_dimensions(&self) -> &Arc<Mutex<GutterDimensions>> {
|
pub fn editor_margins(&self) -> &Arc<Mutex<EditorMargins>> {
|
||||||
match &self.mode {
|
match &self.mode {
|
||||||
PromptEditorMode::Buffer {
|
PromptEditorMode::Buffer { editor_margins, .. } => editor_margins,
|
||||||
gutter_dimensions, ..
|
|
||||||
} => gutter_dimensions,
|
|
||||||
PromptEditorMode::Terminal { .. } => unreachable!(),
|
PromptEditorMode::Terminal { .. } => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,11 @@ use client::{ErrorExt, telemetry::Telemetry};
|
||||||
use collections::{HashMap, HashSet, VecDeque, hash_map};
|
use collections::{HashMap, HashSet, VecDeque, hash_map};
|
||||||
use editor::{
|
use editor::{
|
||||||
Anchor, AnchorRangeExt, CodeActionProvider, Editor, EditorElement, EditorEvent, EditorMode,
|
Anchor, AnchorRangeExt, CodeActionProvider, Editor, EditorElement, EditorEvent, EditorMode,
|
||||||
EditorStyle, ExcerptId, ExcerptRange, GutterDimensions, MultiBuffer, MultiBufferSnapshot,
|
EditorStyle, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset as _, ToPoint,
|
||||||
ToOffset as _, ToPoint,
|
|
||||||
actions::{MoveDown, MoveUp, SelectAll},
|
actions::{MoveDown, MoveUp, SelectAll},
|
||||||
display_map::{
|
display_map::{
|
||||||
BlockContext, BlockPlacement, BlockProperties, BlockStyle, CustomBlockId, RenderBlock,
|
BlockContext, BlockPlacement, BlockProperties, BlockStyle, CustomBlockId, EditorMargins,
|
||||||
ToDisplayPoint,
|
RenderBlock, ToDisplayPoint,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use feature_flags::{FeatureFlagAppExt as _, ZedProFeatureFlag};
|
use feature_flags::{FeatureFlagAppExt as _, ZedProFeatureFlag};
|
||||||
|
@ -338,11 +337,11 @@ impl InlineAssistant {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let gutter_dimensions = Arc::new(Mutex::new(GutterDimensions::default()));
|
let editor_margins = Arc::new(Mutex::new(EditorMargins::default()));
|
||||||
let prompt_editor = cx.new(|cx| {
|
let prompt_editor = cx.new(|cx| {
|
||||||
PromptEditor::new(
|
PromptEditor::new(
|
||||||
assist_id,
|
assist_id,
|
||||||
gutter_dimensions.clone(),
|
editor_margins,
|
||||||
self.prompt_history.clone(),
|
self.prompt_history.clone(),
|
||||||
prompt_buffer.clone(),
|
prompt_buffer.clone(),
|
||||||
codegen.clone(),
|
codegen.clone(),
|
||||||
|
@ -447,11 +446,11 @@ impl InlineAssistant {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let gutter_dimensions = Arc::new(Mutex::new(GutterDimensions::default()));
|
let editor_margins = Arc::new(Mutex::new(EditorMargins::default()));
|
||||||
let prompt_editor = cx.new(|cx| {
|
let prompt_editor = cx.new(|cx| {
|
||||||
PromptEditor::new(
|
PromptEditor::new(
|
||||||
assist_id,
|
assist_id,
|
||||||
gutter_dimensions.clone(),
|
editor_margins,
|
||||||
self.prompt_history.clone(),
|
self.prompt_history.clone(),
|
||||||
prompt_buffer.clone(),
|
prompt_buffer.clone(),
|
||||||
codegen.clone(),
|
codegen.clone(),
|
||||||
|
@ -520,6 +519,7 @@ impl InlineAssistant {
|
||||||
height: Some(prompt_editor_height),
|
height: Some(prompt_editor_height),
|
||||||
render: build_assist_editor_renderer(prompt_editor),
|
render: build_assist_editor_renderer(prompt_editor),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: false,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Sticky,
|
style: BlockStyle::Sticky,
|
||||||
|
@ -534,6 +534,7 @@ impl InlineAssistant {
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
}),
|
}),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1271,11 +1272,11 @@ impl InlineAssistant {
|
||||||
|
|
||||||
enum DeletedLines {}
|
enum DeletedLines {}
|
||||||
let mut editor = Editor::for_multibuffer(multi_buffer, None, window, cx);
|
let mut editor = Editor::for_multibuffer(multi_buffer, None, window, cx);
|
||||||
|
editor.disable_scrollbars_and_minimap(cx);
|
||||||
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::None, cx);
|
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::None, cx);
|
||||||
editor.set_show_wrap_guides(false, cx);
|
editor.set_show_wrap_guides(false, cx);
|
||||||
editor.set_show_gutter(false, cx);
|
editor.set_show_gutter(false, cx);
|
||||||
editor.scroll_manager.set_forbid_vertical_scroll(true);
|
editor.scroll_manager.set_forbid_vertical_scroll(true);
|
||||||
editor.set_show_scrollbars(false, cx);
|
|
||||||
editor.set_read_only(true);
|
editor.set_read_only(true);
|
||||||
editor.set_show_edit_predictions(Some(false), window, cx);
|
editor.set_show_edit_predictions(Some(false), window, cx);
|
||||||
editor.highlight_rows::<DeletedLines>(
|
editor.highlight_rows::<DeletedLines>(
|
||||||
|
@ -1299,11 +1300,12 @@ impl InlineAssistant {
|
||||||
.bg(cx.theme().status().deleted_background)
|
.bg(cx.theme().status().deleted_background)
|
||||||
.size_full()
|
.size_full()
|
||||||
.h(height as f32 * cx.window.line_height())
|
.h(height as f32 * cx.window.line_height())
|
||||||
.pl(cx.gutter_dimensions.full_width())
|
.pl(cx.margins.gutter.full_width())
|
||||||
.child(deleted_lines_editor.clone())
|
.child(deleted_lines_editor.clone())
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
}),
|
}),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1410,7 +1412,7 @@ impl InlineAssistGroup {
|
||||||
fn build_assist_editor_renderer(editor: &Entity<PromptEditor>) -> RenderBlock {
|
fn build_assist_editor_renderer(editor: &Entity<PromptEditor>) -> RenderBlock {
|
||||||
let editor = editor.clone();
|
let editor = editor.clone();
|
||||||
Arc::new(move |cx: &mut BlockContext| {
|
Arc::new(move |cx: &mut BlockContext| {
|
||||||
*editor.read(cx).gutter_dimensions.lock() = *cx.gutter_dimensions;
|
*editor.read(cx).editor_margins.lock() = *cx.margins;
|
||||||
editor.clone().into_any_element()
|
editor.clone().into_any_element()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1450,7 +1452,7 @@ struct PromptEditor {
|
||||||
editor: Entity<Editor>,
|
editor: Entity<Editor>,
|
||||||
language_model_selector: Entity<LanguageModelSelector>,
|
language_model_selector: Entity<LanguageModelSelector>,
|
||||||
edited_since_done: bool,
|
edited_since_done: bool,
|
||||||
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
|
editor_margins: Arc<Mutex<EditorMargins>>,
|
||||||
prompt_history: VecDeque<String>,
|
prompt_history: VecDeque<String>,
|
||||||
prompt_history_ix: Option<usize>,
|
prompt_history_ix: Option<usize>,
|
||||||
pending_prompt: String,
|
pending_prompt: String,
|
||||||
|
@ -1474,7 +1476,8 @@ impl EventEmitter<PromptEditorEvent> for PromptEditor {}
|
||||||
|
|
||||||
impl Render for PromptEditor {
|
impl Render for PromptEditor {
|
||||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
let gutter_dimensions = *self.gutter_dimensions.lock();
|
let editor_margins = *self.editor_margins.lock();
|
||||||
|
let gutter_dimensions = editor_margins.gutter;
|
||||||
let codegen = self.codegen.read(cx);
|
let codegen = self.codegen.read(cx);
|
||||||
|
|
||||||
let mut buttons = Vec::new();
|
let mut buttons = Vec::new();
|
||||||
|
@ -1599,6 +1602,7 @@ impl Render for PromptEditor {
|
||||||
.border_y_1()
|
.border_y_1()
|
||||||
.border_color(cx.theme().status().info_border)
|
.border_color(cx.theme().status().info_border)
|
||||||
.size_full()
|
.size_full()
|
||||||
|
.pr(editor_margins.right)
|
||||||
.py(window.line_height() / 2.5)
|
.py(window.line_height() / 2.5)
|
||||||
.on_action(cx.listener(Self::confirm))
|
.on_action(cx.listener(Self::confirm))
|
||||||
.on_action(cx.listener(Self::cancel))
|
.on_action(cx.listener(Self::cancel))
|
||||||
|
@ -1681,7 +1685,7 @@ impl Render for PromptEditor {
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.pr_6()
|
.pr(px(9.))
|
||||||
.children(self.render_token_count(cx))
|
.children(self.render_token_count(cx))
|
||||||
.children(buttons),
|
.children(buttons),
|
||||||
)
|
)
|
||||||
|
@ -1699,7 +1703,7 @@ impl PromptEditor {
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
id: InlineAssistId,
|
id: InlineAssistId,
|
||||||
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
|
editor_margins: Arc<Mutex<EditorMargins>>,
|
||||||
prompt_history: VecDeque<String>,
|
prompt_history: VecDeque<String>,
|
||||||
prompt_buffer: Entity<MultiBuffer>,
|
prompt_buffer: Entity<MultiBuffer>,
|
||||||
codegen: Entity<Codegen>,
|
codegen: Entity<Codegen>,
|
||||||
|
@ -1762,7 +1766,7 @@ impl PromptEditor {
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
edited_since_done: false,
|
edited_since_done: false,
|
||||||
gutter_dimensions,
|
editor_margins,
|
||||||
prompt_history,
|
prompt_history,
|
||||||
prompt_history_ix: None,
|
prompt_history_ix: None,
|
||||||
pending_prompt: String::new(),
|
pending_prompt: String::new(),
|
||||||
|
|
|
@ -242,9 +242,9 @@ impl ContextEditor {
|
||||||
let editor = cx.new(|cx| {
|
let editor = cx.new(|cx| {
|
||||||
let mut editor =
|
let mut editor =
|
||||||
Editor::for_buffer(context.read(cx).buffer().clone(), None, window, cx);
|
Editor::for_buffer(context.read(cx).buffer().clone(), None, window, cx);
|
||||||
|
editor.disable_scrollbars_and_minimap(cx);
|
||||||
editor.set_soft_wrap_mode(SoftWrap::EditorWidth, cx);
|
editor.set_soft_wrap_mode(SoftWrap::EditorWidth, cx);
|
||||||
editor.set_show_line_numbers(false, cx);
|
editor.set_show_line_numbers(false, cx);
|
||||||
editor.set_show_scrollbars(false, cx);
|
|
||||||
editor.set_show_git_diff_gutter(false, cx);
|
editor.set_show_git_diff_gutter(false, cx);
|
||||||
editor.set_show_code_actions(false, cx);
|
editor.set_show_code_actions(false, cx);
|
||||||
editor.set_show_runnables(false, cx);
|
editor.set_show_runnables(false, cx);
|
||||||
|
@ -942,7 +942,7 @@ impl ContextEditor {
|
||||||
let patch_range = range.clone();
|
let patch_range = range.clone();
|
||||||
move |cx: &mut BlockContext| {
|
move |cx: &mut BlockContext| {
|
||||||
let max_width = cx.max_width;
|
let max_width = cx.max_width;
|
||||||
let gutter_width = cx.gutter_dimensions.full_width();
|
let gutter_width = cx.margins.gutter.full_width();
|
||||||
let block_id = cx.block_id;
|
let block_id = cx.block_id;
|
||||||
let selected = cx.selected;
|
let selected = cx.selected;
|
||||||
let window = &mut cx.window;
|
let window = &mut cx.window;
|
||||||
|
@ -1488,7 +1488,7 @@ impl ContextEditor {
|
||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.id(("message_header", message_id.as_u64()))
|
.id(("message_header", message_id.as_u64()))
|
||||||
.pl(cx.gutter_dimensions.full_width())
|
.pl(cx.margins.gutter.full_width())
|
||||||
.h_11()
|
.h_11()
|
||||||
.w_full()
|
.w_full()
|
||||||
.relative()
|
.relative()
|
||||||
|
@ -1583,6 +1583,7 @@ impl ContextEditor {
|
||||||
),
|
),
|
||||||
priority: usize::MAX,
|
priority: usize::MAX,
|
||||||
render: render_block(MessageMetadata::from(message)),
|
render: render_block(MessageMetadata::from(message)),
|
||||||
|
render_in_minimap: false,
|
||||||
};
|
};
|
||||||
let mut new_blocks = vec![];
|
let mut new_blocks = vec![];
|
||||||
let mut block_index_to_message = vec![];
|
let mut block_index_to_message = vec![];
|
||||||
|
@ -2157,12 +2158,12 @@ impl ContextEditor {
|
||||||
let image_size = size_for_image(
|
let image_size = size_for_image(
|
||||||
&image,
|
&image,
|
||||||
size(
|
size(
|
||||||
cx.max_width - cx.gutter_dimensions.full_width(),
|
cx.max_width - cx.margins.gutter.full_width(),
|
||||||
MAX_HEIGHT_IN_LINES as f32 * cx.line_height,
|
MAX_HEIGHT_IN_LINES as f32 * cx.line_height,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
h_flex()
|
h_flex()
|
||||||
.pl(cx.gutter_dimensions.full_width())
|
.pl(cx.margins.gutter.full_width())
|
||||||
.child(
|
.child(
|
||||||
img(image.clone())
|
img(image.clone())
|
||||||
.object_fit(gpui::ObjectFit::ScaleDown)
|
.object_fit(gpui::ObjectFit::ScaleDown)
|
||||||
|
@ -2172,6 +2173,7 @@ impl ContextEditor {
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
}),
|
}),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: false,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
|
@ -360,9 +360,9 @@ impl EditFileToolCard {
|
||||||
editor.set_show_gutter(false, cx);
|
editor.set_show_gutter(false, cx);
|
||||||
editor.disable_inline_diagnostics();
|
editor.disable_inline_diagnostics();
|
||||||
editor.disable_expand_excerpt_buttons(cx);
|
editor.disable_expand_excerpt_buttons(cx);
|
||||||
|
editor.disable_scrollbars_and_minimap(cx);
|
||||||
editor.set_soft_wrap_mode(SoftWrap::None, cx);
|
editor.set_soft_wrap_mode(SoftWrap::None, cx);
|
||||||
editor.scroll_manager.set_forbid_vertical_scroll(true);
|
editor.scroll_manager.set_forbid_vertical_scroll(true);
|
||||||
editor.set_show_scrollbars(false, cx);
|
|
||||||
editor.set_show_indent_guides(false, cx);
|
editor.set_show_indent_guides(false, cx);
|
||||||
editor.set_read_only(true);
|
editor.set_read_only(true);
|
||||||
editor.set_show_breakpoints(false, cx);
|
editor.set_show_breakpoints(false, cx);
|
||||||
|
|
|
@ -145,6 +145,7 @@ impl editor::DiagnosticRenderer for DiagnosticRenderer {
|
||||||
style: BlockStyle::Flex,
|
style: BlockStyle::Flex,
|
||||||
render: Arc::new(move |bcx| block.render_block(editor.clone(), bcx)),
|
render: Arc::new(move |bcx| block.render_block(editor.clone(), bcx)),
|
||||||
priority: 1,
|
priority: 1,
|
||||||
|
render_in_minimap: false,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
|
|
@ -632,6 +632,7 @@ impl ProjectDiagnosticsEditor {
|
||||||
block.render_block(editor.clone(), bcx)
|
block.render_block(editor.clone(), bcx)
|
||||||
}),
|
}),
|
||||||
priority: 1,
|
priority: 1,
|
||||||
|
render_in_minimap: false,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let block_ids = this.editor.update(cx, |editor, cx| {
|
let block_ids = this.editor.update(cx, |editor, cx| {
|
||||||
|
|
|
@ -31,7 +31,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
pub use block_map::{
|
pub use block_map::{
|
||||||
Block, BlockChunks as DisplayChunks, BlockContext, BlockId, BlockMap, BlockPlacement,
|
Block, BlockChunks as DisplayChunks, BlockContext, BlockId, BlockMap, BlockPlacement,
|
||||||
BlockPoint, BlockProperties, BlockRows, BlockStyle, CustomBlockId, RenderBlock,
|
BlockPoint, BlockProperties, BlockRows, BlockStyle, CustomBlockId, EditorMargins, RenderBlock,
|
||||||
StickyHeaderExcerpt,
|
StickyHeaderExcerpt,
|
||||||
};
|
};
|
||||||
use block_map::{BlockRow, BlockSnapshot};
|
use block_map::{BlockRow, BlockSnapshot};
|
||||||
|
@ -258,6 +258,7 @@ impl DisplayMap {
|
||||||
height: Some(height),
|
height: Some(height),
|
||||||
style,
|
style,
|
||||||
priority,
|
priority,
|
||||||
|
render_in_minimap: true,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -950,16 +951,17 @@ impl DisplaySnapshot {
|
||||||
diagnostic_highlight.fade_out = Some(editor_style.unnecessary_code_fade);
|
diagnostic_highlight.fade_out = Some(editor_style.unnecessary_code_fade);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(severity) = chunk.diagnostic_severity {
|
// Omit underlines for HINT/INFO diagnostics on 'unnecessary' code.
|
||||||
// Omit underlines for HINT/INFO diagnostics on 'unnecessary' code.
|
if let Some(severity) = chunk.diagnostic_severity.filter(|severity| {
|
||||||
if severity <= DiagnosticSeverity::WARNING || !chunk.is_unnecessary {
|
editor_style.show_underlines
|
||||||
let diagnostic_color = super::diagnostic_style(severity, &editor_style.status);
|
&& (!chunk.is_unnecessary || *severity <= DiagnosticSeverity::WARNING)
|
||||||
diagnostic_highlight.underline = Some(UnderlineStyle {
|
}) {
|
||||||
color: Some(diagnostic_color),
|
let diagnostic_color = super::diagnostic_style(severity, &editor_style.status);
|
||||||
thickness: 1.0.into(),
|
diagnostic_highlight.underline = Some(UnderlineStyle {
|
||||||
wavy: true,
|
color: Some(diagnostic_color),
|
||||||
});
|
thickness: 1.0.into(),
|
||||||
}
|
wavy: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(highlight_style) = highlight_style.as_mut() {
|
if let Some(highlight_style) = highlight_style.as_mut() {
|
||||||
|
@ -1613,6 +1615,7 @@ pub mod tests {
|
||||||
height: Some(height),
|
height: Some(height),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority,
|
priority,
|
||||||
|
render_in_minimap: true,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -1975,6 +1978,7 @@ pub mod tests {
|
||||||
style: BlockStyle::Sticky,
|
style: BlockStyle::Sticky,
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
}],
|
}],
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
|
@ -2170,6 +2174,7 @@ pub mod tests {
|
||||||
style: BlockStyle::Sticky,
|
style: BlockStyle::Sticky,
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
placement: BlockPlacement::Below(
|
placement: BlockPlacement::Below(
|
||||||
|
@ -2179,6 +2184,7 @@ pub mod tests {
|
||||||
style: BlockStyle::Sticky,
|
style: BlockStyle::Sticky,
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
cx,
|
cx,
|
||||||
|
@ -2284,6 +2290,7 @@ pub mod tests {
|
||||||
style: BlockStyle::Sticky,
|
style: BlockStyle::Sticky,
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
}],
|
}],
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
@ -2358,6 +2365,7 @@ pub mod tests {
|
||||||
style: BlockStyle::Fixed,
|
style: BlockStyle::Fixed,
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
}],
|
}],
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
|
|
|
@ -193,6 +193,7 @@ pub struct CustomBlock {
|
||||||
style: BlockStyle,
|
style: BlockStyle,
|
||||||
render: Arc<Mutex<RenderBlock>>,
|
render: Arc<Mutex<RenderBlock>>,
|
||||||
priority: usize,
|
priority: usize,
|
||||||
|
pub(crate) render_in_minimap: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -204,6 +205,7 @@ pub struct BlockProperties<P> {
|
||||||
pub style: BlockStyle,
|
pub style: BlockStyle,
|
||||||
pub render: RenderBlock,
|
pub render: RenderBlock,
|
||||||
pub priority: usize,
|
pub priority: usize,
|
||||||
|
pub render_in_minimap: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: Debug> Debug for BlockProperties<P> {
|
impl<P: Debug> Debug for BlockProperties<P> {
|
||||||
|
@ -223,6 +225,12 @@ pub enum BlockStyle {
|
||||||
Sticky,
|
Sticky,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct EditorMargins {
|
||||||
|
pub gutter: GutterDimensions,
|
||||||
|
pub right: Pixels,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(gpui::AppContext, gpui::VisualContext)]
|
#[derive(gpui::AppContext, gpui::VisualContext)]
|
||||||
pub struct BlockContext<'a, 'b> {
|
pub struct BlockContext<'a, 'b> {
|
||||||
#[window]
|
#[window]
|
||||||
|
@ -231,7 +239,7 @@ pub struct BlockContext<'a, 'b> {
|
||||||
pub app: &'b mut App,
|
pub app: &'b mut App,
|
||||||
pub anchor_x: Pixels,
|
pub anchor_x: Pixels,
|
||||||
pub max_width: Pixels,
|
pub max_width: Pixels,
|
||||||
pub gutter_dimensions: &'b GutterDimensions,
|
pub margins: &'b EditorMargins,
|
||||||
pub em_width: Pixels,
|
pub em_width: Pixels,
|
||||||
pub line_height: Pixels,
|
pub line_height: Pixels,
|
||||||
pub block_id: BlockId,
|
pub block_id: BlockId,
|
||||||
|
@ -1037,6 +1045,7 @@ impl BlockMapWriter<'_> {
|
||||||
render: Arc::new(Mutex::new(block.render)),
|
render: Arc::new(Mutex::new(block.render)),
|
||||||
style: block.style,
|
style: block.style,
|
||||||
priority: block.priority,
|
priority: block.priority,
|
||||||
|
render_in_minimap: block.render_in_minimap,
|
||||||
});
|
});
|
||||||
self.0.custom_blocks.insert(block_ix, new_block.clone());
|
self.0.custom_blocks.insert(block_ix, new_block.clone());
|
||||||
self.0.custom_blocks_by_id.insert(id, new_block);
|
self.0.custom_blocks_by_id.insert(id, new_block);
|
||||||
|
@ -1071,6 +1080,7 @@ impl BlockMapWriter<'_> {
|
||||||
style: block.style,
|
style: block.style,
|
||||||
render: block.render.clone(),
|
render: block.render.clone(),
|
||||||
priority: block.priority,
|
priority: block.priority,
|
||||||
|
render_in_minimap: block.render_in_minimap,
|
||||||
};
|
};
|
||||||
let new_block = Arc::new(new_block);
|
let new_block = Arc::new(new_block);
|
||||||
*block = new_block.clone();
|
*block = new_block.clone();
|
||||||
|
@ -1967,6 +1977,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Fixed,
|
style: BlockStyle::Fixed,
|
||||||
|
@ -1974,6 +1985,7 @@ mod tests {
|
||||||
height: Some(2),
|
height: Some(2),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Fixed,
|
style: BlockStyle::Fixed,
|
||||||
|
@ -1981,6 +1993,7 @@ mod tests {
|
||||||
height: Some(3),
|
height: Some(3),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -2205,6 +2218,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Fixed,
|
style: BlockStyle::Fixed,
|
||||||
|
@ -2212,6 +2226,7 @@ mod tests {
|
||||||
height: Some(2),
|
height: Some(2),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Fixed,
|
style: BlockStyle::Fixed,
|
||||||
|
@ -2219,6 +2234,7 @@ mod tests {
|
||||||
height: Some(3),
|
height: Some(3),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -2307,6 +2323,7 @@ mod tests {
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Fixed,
|
style: BlockStyle::Fixed,
|
||||||
|
@ -2314,6 +2331,7 @@ mod tests {
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -2353,6 +2371,7 @@ mod tests {
|
||||||
height: Some(4),
|
height: Some(4),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
}])[0];
|
}])[0];
|
||||||
|
|
||||||
let blocks_snapshot = block_map.read(wraps_snapshot, Default::default());
|
let blocks_snapshot = block_map.read(wraps_snapshot, Default::default());
|
||||||
|
@ -2406,6 +2425,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Fixed,
|
style: BlockStyle::Fixed,
|
||||||
|
@ -2413,6 +2433,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Fixed,
|
style: BlockStyle::Fixed,
|
||||||
|
@ -2420,6 +2441,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
let blocks_snapshot = block_map.read(wraps_snapshot.clone(), Default::default());
|
let blocks_snapshot = block_map.read(wraps_snapshot.clone(), Default::default());
|
||||||
|
@ -2434,6 +2456,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Fixed,
|
style: BlockStyle::Fixed,
|
||||||
|
@ -2441,6 +2464,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Fixed,
|
style: BlockStyle::Fixed,
|
||||||
|
@ -2448,6 +2472,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
let blocks_snapshot = block_map.read(wraps_snapshot.clone(), Default::default());
|
let blocks_snapshot = block_map.read(wraps_snapshot.clone(), Default::default());
|
||||||
|
@ -2547,6 +2572,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Fixed,
|
style: BlockStyle::Fixed,
|
||||||
|
@ -2554,6 +2580,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Fixed,
|
style: BlockStyle::Fixed,
|
||||||
|
@ -2561,6 +2588,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
let excerpt_blocks_3 = writer.insert(vec![
|
let excerpt_blocks_3 = writer.insert(vec![
|
||||||
|
@ -2570,6 +2598,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
style: BlockStyle::Fixed,
|
style: BlockStyle::Fixed,
|
||||||
|
@ -2577,6 +2606,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -2624,6 +2654,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
}]);
|
}]);
|
||||||
let blocks_snapshot = block_map.read(wrap_snapshot.clone(), Patch::default());
|
let blocks_snapshot = block_map.read(wrap_snapshot.clone(), Patch::default());
|
||||||
let blocks = blocks_snapshot
|
let blocks = blocks_snapshot
|
||||||
|
@ -2981,6 +3012,7 @@ mod tests {
|
||||||
height: Some(height),
|
height: Some(height),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -3001,6 +3033,7 @@ mod tests {
|
||||||
style: props.style,
|
style: props.style,
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
for (block_properties, block_id) in block_properties.iter().zip(block_ids) {
|
for (block_properties, block_id) in block_properties.iter().zip(block_ids) {
|
||||||
|
@ -3525,6 +3558,7 @@ mod tests {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
}])[0];
|
}])[0];
|
||||||
|
|
||||||
let blocks_snapshot = block_map.read(wraps_snapshot.clone(), Default::default());
|
let blocks_snapshot = block_map.read(wraps_snapshot.clone(), Default::default());
|
||||||
|
|
|
@ -61,11 +61,11 @@ use collections::{BTreeMap, HashMap, HashSet, VecDeque};
|
||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
use display_map::*;
|
use display_map::*;
|
||||||
pub use display_map::{ChunkRenderer, ChunkRendererContext, DisplayPoint, FoldPlaceholder};
|
pub use display_map::{ChunkRenderer, ChunkRendererContext, DisplayPoint, FoldPlaceholder};
|
||||||
use editor_settings::GoToDefinitionFallback;
|
|
||||||
pub use editor_settings::{
|
pub use editor_settings::{
|
||||||
CurrentLineHighlight, EditorSettings, HideMouseMode, ScrollBeyondLastLine, SearchSettings,
|
CurrentLineHighlight, EditorSettings, HideMouseMode, ScrollBeyondLastLine, SearchSettings,
|
||||||
ShowScrollbar,
|
ShowScrollbar,
|
||||||
};
|
};
|
||||||
|
use editor_settings::{GoToDefinitionFallback, Minimap as MinimapSettings};
|
||||||
pub use editor_settings_controls::*;
|
pub use editor_settings_controls::*;
|
||||||
use element::{AcceptEditPredictionBinding, LineWithInvisibles, PositionMap, layout_line};
|
use element::{AcceptEditPredictionBinding, LineWithInvisibles, PositionMap, layout_line};
|
||||||
pub use element::{
|
pub use element::{
|
||||||
|
@ -231,6 +231,7 @@ pub(crate) const SCROLL_CENTER_TOP_BOTTOM_DEBOUNCE_TIMEOUT: Duration = Duration:
|
||||||
pub(crate) const EDIT_PREDICTION_KEY_CONTEXT: &str = "edit_prediction";
|
pub(crate) const EDIT_PREDICTION_KEY_CONTEXT: &str = "edit_prediction";
|
||||||
pub(crate) const EDIT_PREDICTION_CONFLICT_KEY_CONTEXT: &str = "edit_prediction_conflict";
|
pub(crate) const EDIT_PREDICTION_CONFLICT_KEY_CONTEXT: &str = "edit_prediction_conflict";
|
||||||
pub(crate) const MIN_LINE_NUMBER_DIGITS: u32 = 4;
|
pub(crate) const MIN_LINE_NUMBER_DIGITS: u32 = 4;
|
||||||
|
pub(crate) const MINIMAP_FONT_SIZE: AbsoluteLength = AbsoluteLength::Pixels(px(2.));
|
||||||
|
|
||||||
pub type RenderDiffHunkControlsFn = Arc<
|
pub type RenderDiffHunkControlsFn = Arc<
|
||||||
dyn Fn(
|
dyn Fn(
|
||||||
|
@ -465,7 +466,7 @@ pub enum SelectMode {
|
||||||
All,
|
All,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum EditorMode {
|
pub enum EditorMode {
|
||||||
SingleLine {
|
SingleLine {
|
||||||
auto_width: bool,
|
auto_width: bool,
|
||||||
|
@ -481,6 +482,9 @@ pub enum EditorMode {
|
||||||
/// When set to `true`, the editor's height will be determined by its content.
|
/// When set to `true`, the editor's height will be determined by its content.
|
||||||
sized_by_content: bool,
|
sized_by_content: bool,
|
||||||
},
|
},
|
||||||
|
Minimap {
|
||||||
|
parent: WeakEntity<Editor>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditorMode {
|
impl EditorMode {
|
||||||
|
@ -495,6 +499,10 @@ impl EditorMode {
|
||||||
pub fn is_full(&self) -> bool {
|
pub fn is_full(&self) -> bool {
|
||||||
matches!(self, Self::Full { .. })
|
matches!(self, Self::Full { .. })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_minimap(&self) -> bool {
|
||||||
|
matches!(self, Self::Minimap { .. })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -525,6 +533,7 @@ pub struct EditorStyle {
|
||||||
pub inlay_hints_style: HighlightStyle,
|
pub inlay_hints_style: HighlightStyle,
|
||||||
pub inline_completion_styles: InlineCompletionStyles,
|
pub inline_completion_styles: InlineCompletionStyles,
|
||||||
pub unnecessary_code_fade: f32,
|
pub unnecessary_code_fade: f32,
|
||||||
|
pub show_underlines: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for EditorStyle {
|
impl Default for EditorStyle {
|
||||||
|
@ -545,6 +554,7 @@ impl Default for EditorStyle {
|
||||||
whitespace: HighlightStyle::default(),
|
whitespace: HighlightStyle::default(),
|
||||||
},
|
},
|
||||||
unnecessary_code_fade: Default::default(),
|
unnecessary_code_fade: Default::default(),
|
||||||
|
show_underlines: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -871,6 +881,7 @@ pub struct Editor {
|
||||||
show_breadcrumbs: bool,
|
show_breadcrumbs: bool,
|
||||||
show_gutter: bool,
|
show_gutter: bool,
|
||||||
show_scrollbars: bool,
|
show_scrollbars: bool,
|
||||||
|
show_minimap: bool,
|
||||||
disable_expand_excerpt_buttons: bool,
|
disable_expand_excerpt_buttons: bool,
|
||||||
show_line_numbers: Option<bool>,
|
show_line_numbers: Option<bool>,
|
||||||
use_relative_line_numbers: Option<bool>,
|
use_relative_line_numbers: Option<bool>,
|
||||||
|
@ -989,6 +1000,7 @@ pub struct Editor {
|
||||||
serialize_selections: Task<()>,
|
serialize_selections: Task<()>,
|
||||||
serialize_folds: Task<()>,
|
serialize_folds: Task<()>,
|
||||||
mouse_cursor_hidden: bool,
|
mouse_cursor_hidden: bool,
|
||||||
|
minimap: Option<Entity<Self>>,
|
||||||
hide_mouse_mode: HideMouseMode,
|
hide_mouse_mode: HideMouseMode,
|
||||||
pub change_list: ChangeList,
|
pub change_list: ChangeList,
|
||||||
inline_value_cache: InlineValueCache,
|
inline_value_cache: InlineValueCache,
|
||||||
|
@ -1452,7 +1464,7 @@ impl Editor {
|
||||||
|
|
||||||
pub fn clone(&self, window: &mut Window, cx: &mut Context<Self>) -> Self {
|
pub fn clone(&self, window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||||
let mut clone = Self::new(
|
let mut clone = Self::new(
|
||||||
self.mode,
|
self.mode.clone(),
|
||||||
self.buffer.clone(),
|
self.buffer.clone(),
|
||||||
self.project.clone(),
|
self.project.clone(),
|
||||||
window,
|
window,
|
||||||
|
@ -1479,6 +1491,21 @@ impl Editor {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
Editor::new_internal(mode, buffer, project, None, window, cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_internal(
|
||||||
|
mode: EditorMode,
|
||||||
|
buffer: Entity<MultiBuffer>,
|
||||||
|
project: Option<Entity<Project>>,
|
||||||
|
display_map: Option<Entity<DisplayMap>>,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) -> Self {
|
||||||
|
debug_assert!(
|
||||||
|
display_map.is_none() || mode.is_minimap(),
|
||||||
|
"Providing a display map for a new editor is only intended for the minimap and might have unindended side effects otherwise!"
|
||||||
|
);
|
||||||
let style = window.text_style();
|
let style = window.text_style();
|
||||||
let font_size = style.font_size.to_pixels(window.rem_size());
|
let font_size = style.font_size.to_pixels(window.rem_size());
|
||||||
let editor = cx.entity().downgrade();
|
let editor = cx.entity().downgrade();
|
||||||
|
@ -1514,17 +1541,19 @@ impl Editor {
|
||||||
merge_adjacent: true,
|
merge_adjacent: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let display_map = cx.new(|cx| {
|
let display_map = display_map.unwrap_or_else(|| {
|
||||||
DisplayMap::new(
|
cx.new(|cx| {
|
||||||
buffer.clone(),
|
DisplayMap::new(
|
||||||
style.font(),
|
buffer.clone(),
|
||||||
font_size,
|
style.font(),
|
||||||
None,
|
font_size,
|
||||||
FILE_HEADER_HEIGHT,
|
None,
|
||||||
MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
|
FILE_HEADER_HEIGHT,
|
||||||
fold_placeholder,
|
MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
|
||||||
cx,
|
fold_placeholder,
|
||||||
)
|
cx,
|
||||||
|
)
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
|
let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
|
||||||
|
@ -1628,7 +1657,7 @@ impl Editor {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let breakpoint_store = match (mode, project.as_ref()) {
|
let breakpoint_store = match (&mode, project.as_ref()) {
|
||||||
(EditorMode::Full { .. }, Some(project)) => Some(project.read(cx).breakpoint_store()),
|
(EditorMode::Full { .. }, Some(project)) => Some(project.read(cx).breakpoint_store()),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
@ -1649,6 +1678,8 @@ impl Editor {
|
||||||
code_action_providers.push(Rc::new(project) as Rc<_>);
|
code_action_providers.push(Rc::new(project) as Rc<_>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let full_mode = mode.is_full();
|
||||||
|
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
focus_handle,
|
focus_handle,
|
||||||
show_cursor_when_unfocused: false,
|
show_cursor_when_unfocused: false,
|
||||||
|
@ -1678,8 +1709,8 @@ impl Editor {
|
||||||
project,
|
project,
|
||||||
blink_manager: blink_manager.clone(),
|
blink_manager: blink_manager.clone(),
|
||||||
show_local_selections: true,
|
show_local_selections: true,
|
||||||
show_scrollbars: true,
|
show_scrollbars: full_mode,
|
||||||
mode,
|
show_minimap: full_mode,
|
||||||
show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
|
show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
|
||||||
show_gutter: mode.is_full(),
|
show_gutter: mode.is_full(),
|
||||||
show_line_numbers: None,
|
show_line_numbers: None,
|
||||||
|
@ -1727,7 +1758,7 @@ impl Editor {
|
||||||
workspace: None,
|
workspace: None,
|
||||||
input_enabled: true,
|
input_enabled: true,
|
||||||
use_modal_editing: mode.is_full(),
|
use_modal_editing: mode.is_full(),
|
||||||
read_only: false,
|
read_only: mode.is_minimap(),
|
||||||
use_autoclose: true,
|
use_autoclose: true,
|
||||||
use_auto_surround: true,
|
use_auto_surround: true,
|
||||||
auto_replace_emoji_shortcode: false,
|
auto_replace_emoji_shortcode: false,
|
||||||
|
@ -1771,9 +1802,10 @@ impl Editor {
|
||||||
show_git_blame_inline_delay_task: None,
|
show_git_blame_inline_delay_task: None,
|
||||||
git_blame_inline_enabled: ProjectSettings::get_global(cx).git.inline_blame_enabled(),
|
git_blame_inline_enabled: ProjectSettings::get_global(cx).git.inline_blame_enabled(),
|
||||||
render_diff_hunk_controls: Arc::new(render_diff_hunk_controls),
|
render_diff_hunk_controls: Arc::new(render_diff_hunk_controls),
|
||||||
serialize_dirty_buffers: ProjectSettings::get_global(cx)
|
serialize_dirty_buffers: !mode.is_minimap()
|
||||||
.session
|
&& ProjectSettings::get_global(cx)
|
||||||
.restore_unsaved_buffers,
|
.session
|
||||||
|
.restore_unsaved_buffers,
|
||||||
blame: None,
|
blame: None,
|
||||||
blame_subscription: None,
|
blame_subscription: None,
|
||||||
tasks: Default::default(),
|
tasks: Default::default(),
|
||||||
|
@ -1816,10 +1848,12 @@ impl Editor {
|
||||||
load_diff_task: load_uncommitted_diff,
|
load_diff_task: load_uncommitted_diff,
|
||||||
temporary_diff_override: false,
|
temporary_diff_override: false,
|
||||||
mouse_cursor_hidden: false,
|
mouse_cursor_hidden: false,
|
||||||
|
minimap: None,
|
||||||
hide_mouse_mode: EditorSettings::get_global(cx)
|
hide_mouse_mode: EditorSettings::get_global(cx)
|
||||||
.hide_mouse
|
.hide_mouse
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
change_list: ChangeList::new(),
|
change_list: ChangeList::new(),
|
||||||
|
mode,
|
||||||
};
|
};
|
||||||
if let Some(breakpoints) = this.breakpoint_store.as_ref() {
|
if let Some(breakpoints) = this.breakpoint_store.as_ref() {
|
||||||
this._subscriptions
|
this._subscriptions
|
||||||
|
@ -1906,12 +1940,11 @@ impl Editor {
|
||||||
this.scroll_manager.show_scrollbars(window, cx);
|
this.scroll_manager.show_scrollbars(window, cx);
|
||||||
jsx_tag_auto_close::refresh_enabled_in_any_buffer(&mut this, &buffer, cx);
|
jsx_tag_auto_close::refresh_enabled_in_any_buffer(&mut this, &buffer, cx);
|
||||||
|
|
||||||
if mode.is_full() {
|
if full_mode {
|
||||||
let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
|
let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
|
||||||
cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
|
cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
|
||||||
|
|
||||||
if this.git_blame_inline_enabled {
|
if this.git_blame_inline_enabled {
|
||||||
this.git_blame_inline_enabled = true;
|
|
||||||
this.start_git_blame_inline(false, window, cx);
|
this.start_git_blame_inline(false, window, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1926,6 +1959,8 @@ impl Editor {
|
||||||
.insert(buffer.read(cx).remote_id(), handle);
|
.insert(buffer.read(cx).remote_id(), handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.minimap = this.create_minimap(EditorSettings::get_global(cx).minimap, window, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.report_editor_event("Editor Opened", None, cx);
|
this.report_editor_event("Editor Opened", None, cx);
|
||||||
|
@ -1969,6 +2004,7 @@ impl Editor {
|
||||||
let mode = match self.mode {
|
let mode = match self.mode {
|
||||||
EditorMode::SingleLine { .. } => "single_line",
|
EditorMode::SingleLine { .. } => "single_line",
|
||||||
EditorMode::AutoHeight { .. } => "auto_height",
|
EditorMode::AutoHeight { .. } => "auto_height",
|
||||||
|
EditorMode::Minimap { .. } => "minimap",
|
||||||
EditorMode::Full { .. } => "full",
|
EditorMode::Full { .. } => "full",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2215,7 +2251,7 @@ impl Editor {
|
||||||
.flatten();
|
.flatten();
|
||||||
|
|
||||||
EditorSnapshot {
|
EditorSnapshot {
|
||||||
mode: self.mode,
|
mode: self.mode.clone(),
|
||||||
show_gutter: self.show_gutter,
|
show_gutter: self.show_gutter,
|
||||||
show_line_numbers: self.show_line_numbers,
|
show_line_numbers: self.show_line_numbers,
|
||||||
show_git_diff_gutter: self.show_git_diff_gutter,
|
show_git_diff_gutter: self.show_git_diff_gutter,
|
||||||
|
@ -2251,8 +2287,8 @@ impl Editor {
|
||||||
.excerpt_containing(self.selections.newest_anchor().head(), cx)
|
.excerpt_containing(self.selections.newest_anchor().head(), cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mode(&self) -> EditorMode {
|
pub fn mode(&self) -> &EditorMode {
|
||||||
self.mode
|
&self.mode
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_mode(&mut self, mode: EditorMode) {
|
pub fn set_mode(&mut self, mode: EditorMode) {
|
||||||
|
@ -2707,7 +2743,9 @@ impl Editor {
|
||||||
use text::ToOffset as _;
|
use text::ToOffset as _;
|
||||||
use text::ToPoint as _;
|
use text::ToPoint as _;
|
||||||
|
|
||||||
if WorkspaceSettings::get(None, cx).restore_on_startup == RestoreOnStartupBehavior::None {
|
if self.mode.is_minimap()
|
||||||
|
|| WorkspaceSettings::get(None, cx).restore_on_startup == RestoreOnStartupBehavior::None
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7238,6 +7276,7 @@ impl Editor {
|
||||||
&mut self,
|
&mut self,
|
||||||
text_bounds: &Bounds<Pixels>,
|
text_bounds: &Bounds<Pixels>,
|
||||||
content_origin: gpui::Point<Pixels>,
|
content_origin: gpui::Point<Pixels>,
|
||||||
|
right_margin: Pixels,
|
||||||
editor_snapshot: &EditorSnapshot,
|
editor_snapshot: &EditorSnapshot,
|
||||||
visible_row_range: Range<DisplayRow>,
|
visible_row_range: Range<DisplayRow>,
|
||||||
scroll_top: f32,
|
scroll_top: f32,
|
||||||
|
@ -7251,6 +7290,9 @@ impl Editor {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> Option<(AnyElement, gpui::Point<Pixels>)> {
|
) -> Option<(AnyElement, gpui::Point<Pixels>)> {
|
||||||
|
if self.mode().is_minimap() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let active_inline_completion = self.active_inline_completion.as_ref()?;
|
let active_inline_completion = self.active_inline_completion.as_ref()?;
|
||||||
|
|
||||||
if self.edit_prediction_visible_in_cursor_popover(true) {
|
if self.edit_prediction_visible_in_cursor_popover(true) {
|
||||||
|
@ -7328,6 +7370,7 @@ impl Editor {
|
||||||
} => self.render_edit_prediction_diff_popover(
|
} => self.render_edit_prediction_diff_popover(
|
||||||
text_bounds,
|
text_bounds,
|
||||||
content_origin,
|
content_origin,
|
||||||
|
right_margin,
|
||||||
editor_snapshot,
|
editor_snapshot,
|
||||||
visible_row_range,
|
visible_row_range,
|
||||||
line_layouts,
|
line_layouts,
|
||||||
|
@ -7601,6 +7644,7 @@ impl Editor {
|
||||||
self: &Editor,
|
self: &Editor,
|
||||||
text_bounds: &Bounds<Pixels>,
|
text_bounds: &Bounds<Pixels>,
|
||||||
content_origin: gpui::Point<Pixels>,
|
content_origin: gpui::Point<Pixels>,
|
||||||
|
right_margin: Pixels,
|
||||||
editor_snapshot: &EditorSnapshot,
|
editor_snapshot: &EditorSnapshot,
|
||||||
visible_row_range: Range<DisplayRow>,
|
visible_row_range: Range<DisplayRow>,
|
||||||
line_layouts: &[LineWithInvisibles],
|
line_layouts: &[LineWithInvisibles],
|
||||||
|
@ -7710,7 +7754,7 @@ impl Editor {
|
||||||
|
|
||||||
let viewport_bounds =
|
let viewport_bounds =
|
||||||
Bounds::new(Default::default(), window.viewport_size()).extend(Edges {
|
Bounds::new(Default::default(), window.viewport_size()).extend(Edges {
|
||||||
right: -EditorElement::SCROLLBAR_WIDTH,
|
right: -right_margin,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -9286,10 +9330,11 @@ impl Editor {
|
||||||
placement: BlockPlacement::Above(anchor),
|
placement: BlockPlacement::Above(anchor),
|
||||||
height: Some(height),
|
height: Some(height),
|
||||||
render: Arc::new(move |cx| {
|
render: Arc::new(move |cx| {
|
||||||
*cloned_prompt.read(cx).gutter_dimensions.lock() = *cx.gutter_dimensions;
|
*cloned_prompt.read(cx).editor_margins.lock() = *cx.margins;
|
||||||
cloned_prompt.clone().into_any_element()
|
cloned_prompt.clone().into_any_element()
|
||||||
}),
|
}),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let focus_handle = bp_prompt.focus_handle(cx);
|
let focus_handle = bp_prompt.focus_handle(cx);
|
||||||
|
@ -14546,6 +14591,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
}],
|
}],
|
||||||
Some(Autoscroll::fit()),
|
Some(Autoscroll::fit()),
|
||||||
cx,
|
cx,
|
||||||
|
@ -14928,6 +14974,10 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn refresh_active_diagnostics(&mut self, cx: &mut Context<Editor>) {
|
fn refresh_active_diagnostics(&mut self, cx: &mut Context<Editor>) {
|
||||||
|
if self.mode.is_minimap() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if let ActiveDiagnostic::Group(active_diagnostics) = &mut self.active_diagnostics {
|
if let ActiveDiagnostic::Group(active_diagnostics) = &mut self.active_diagnostics {
|
||||||
let buffer = self.buffer.read(cx).snapshot(cx);
|
let buffer = self.buffer.read(cx).snapshot(cx);
|
||||||
let primary_range_start = active_diagnostics.active_range.start.to_offset(&buffer);
|
let primary_range_start = active_diagnostics.active_range.start.to_offset(&buffer);
|
||||||
|
@ -15041,7 +15091,10 @@ impl Editor {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
if !self.inline_diagnostics_enabled || !self.show_inline_diagnostics {
|
if self.mode.is_minimap()
|
||||||
|
|| !self.inline_diagnostics_enabled
|
||||||
|
|| !self.show_inline_diagnostics
|
||||||
|
{
|
||||||
self.inline_diagnostics_update = Task::ready(());
|
self.inline_diagnostics_update = Task::ready(());
|
||||||
self.inline_diagnostics.clear();
|
self.inline_diagnostics.clear();
|
||||||
return;
|
return;
|
||||||
|
@ -16246,6 +16299,55 @@ impl Editor {
|
||||||
.text()
|
.text()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_minimap(
|
||||||
|
&self,
|
||||||
|
minimap_settings: MinimapSettings,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) -> Option<Entity<Self>> {
|
||||||
|
(minimap_settings.minimap_enabled() && self.is_singleton(cx))
|
||||||
|
.then(|| self.initialize_new_minimap(minimap_settings, window, cx))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn initialize_new_minimap(
|
||||||
|
&self,
|
||||||
|
minimap_settings: MinimapSettings,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) -> Entity<Self> {
|
||||||
|
const MINIMAP_FONT_WEIGHT: gpui::FontWeight = gpui::FontWeight::BLACK;
|
||||||
|
|
||||||
|
let mut minimap = Editor::new_internal(
|
||||||
|
EditorMode::Minimap {
|
||||||
|
parent: cx.weak_entity(),
|
||||||
|
},
|
||||||
|
self.buffer.clone(),
|
||||||
|
self.project.clone(),
|
||||||
|
Some(self.display_map.clone()),
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
minimap.scroll_manager.clone_state(&self.scroll_manager);
|
||||||
|
minimap.set_text_style_refinement(TextStyleRefinement {
|
||||||
|
font_size: Some(MINIMAP_FONT_SIZE),
|
||||||
|
font_weight: Some(MINIMAP_FONT_WEIGHT),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
minimap.update_minimap_configuration(minimap_settings, cx);
|
||||||
|
cx.new(|_| minimap)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_minimap_configuration(&mut self, minimap_settings: MinimapSettings, cx: &App) {
|
||||||
|
let current_line_highlight = minimap_settings
|
||||||
|
.current_line_highlight
|
||||||
|
.unwrap_or_else(|| EditorSettings::get_global(cx).current_line_highlight);
|
||||||
|
self.set_current_line_highlight(Some(current_line_highlight));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn minimap(&self) -> Option<&Entity<Self>> {
|
||||||
|
self.minimap.as_ref().filter(|_| self.show_minimap)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn wrap_guides(&self, cx: &App) -> SmallVec<[(usize, bool); 2]> {
|
pub fn wrap_guides(&self, cx: &App) -> SmallVec<[(usize, bool); 2]> {
|
||||||
let mut wrap_guides = smallvec::smallvec![];
|
let mut wrap_guides = smallvec::smallvec![];
|
||||||
|
|
||||||
|
@ -16313,14 +16415,19 @@ impl Editor {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
let rem_size = window.rem_size();
|
// We intentionally do not inform the display map about the minimap style
|
||||||
self.display_map.update(cx, |map, cx| {
|
// so that wrapping is not recalculated and stays consistent for the editor
|
||||||
map.set_font(
|
// and its linked minimap.
|
||||||
style.text.font(),
|
if !self.mode.is_minimap() {
|
||||||
style.text.font_size.to_pixels(rem_size),
|
let rem_size = window.rem_size();
|
||||||
cx,
|
self.display_map.update(cx, |map, cx| {
|
||||||
)
|
map.set_font(
|
||||||
});
|
style.text.font(),
|
||||||
|
style.text.font_size.to_pixels(rem_size),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
self.style = Some(style);
|
self.style = Some(style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16435,6 +16542,16 @@ impl Editor {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_show_minimap(&mut self, show_minimap: bool, cx: &mut Context<Self>) {
|
||||||
|
self.show_minimap = show_minimap;
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disable_scrollbars_and_minimap(&mut self, cx: &mut Context<Self>) {
|
||||||
|
self.set_show_scrollbars(false, cx);
|
||||||
|
self.set_show_minimap(false, cx);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_show_line_numbers(&mut self, show_line_numbers: bool, cx: &mut Context<Self>) {
|
pub fn set_show_line_numbers(&mut self, show_line_numbers: bool, cx: &mut Context<Self>) {
|
||||||
self.show_line_numbers = Some(show_line_numbers);
|
self.show_line_numbers = Some(show_line_numbers);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
@ -16808,7 +16925,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_git_blame_gutter(&self, cx: &App) -> bool {
|
pub fn render_git_blame_gutter(&self, cx: &App) -> bool {
|
||||||
self.show_git_blame_gutter && self.has_blame_entries(cx)
|
!self.mode().is_minimap() && self.show_git_blame_gutter && self.has_blame_entries(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_git_blame_inline(&self, window: &Window, cx: &App) -> bool {
|
pub fn render_git_blame_inline(&self, window: &Window, cx: &App) -> bool {
|
||||||
|
@ -17910,7 +18027,8 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
let project_settings = ProjectSettings::get_global(cx);
|
let project_settings = ProjectSettings::get_global(cx);
|
||||||
self.serialize_dirty_buffers = project_settings.session.restore_unsaved_buffers;
|
self.serialize_dirty_buffers =
|
||||||
|
!self.mode.is_minimap() && project_settings.session.restore_unsaved_buffers;
|
||||||
|
|
||||||
if self.mode.is_full() {
|
if self.mode.is_full() {
|
||||||
let show_inline_diagnostics = project_settings.diagnostics.inline.enabled;
|
let show_inline_diagnostics = project_settings.diagnostics.inline.enabled;
|
||||||
|
@ -17923,6 +18041,15 @@ impl Editor {
|
||||||
if self.git_blame_inline_enabled != inline_blame_enabled {
|
if self.git_blame_inline_enabled != inline_blame_enabled {
|
||||||
self.toggle_git_blame_inline_internal(false, window, cx);
|
self.toggle_git_blame_inline_internal(false, window, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let minimap_settings = EditorSettings::get_global(cx).minimap;
|
||||||
|
if self.minimap.as_ref().is_some() != minimap_settings.minimap_enabled() {
|
||||||
|
self.minimap = self.create_minimap(minimap_settings, window, cx);
|
||||||
|
} else if let Some(minimap_entity) = self.minimap.as_ref() {
|
||||||
|
minimap_entity.update(cx, |minimap_editor, cx| {
|
||||||
|
minimap_editor.update_minimap_configuration(minimap_settings, cx)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
@ -18618,6 +18745,9 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_addon<T: Addon>(&mut self, instance: T) {
|
pub fn register_addon<T: Addon>(&mut self, instance: T) {
|
||||||
|
if self.mode.is_minimap() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
self.addons
|
self.addons
|
||||||
.insert(std::any::TypeId::of::<T>(), Box::new(instance));
|
.insert(std::any::TypeId::of::<T>(), Box::new(instance));
|
||||||
}
|
}
|
||||||
|
@ -18663,6 +18793,7 @@ impl Editor {
|
||||||
cx: &mut Context<Editor>,
|
cx: &mut Context<Editor>,
|
||||||
) {
|
) {
|
||||||
if self.is_singleton(cx)
|
if self.is_singleton(cx)
|
||||||
|
&& !self.mode.is_minimap()
|
||||||
&& WorkspaceSettings::get(None, cx).restore_on_startup != RestoreOnStartupBehavior::None
|
&& WorkspaceSettings::get(None, cx).restore_on_startup != RestoreOnStartupBehavior::None
|
||||||
{
|
{
|
||||||
let buffer_snapshot = OnceCell::new();
|
let buffer_snapshot = OnceCell::new();
|
||||||
|
@ -20268,7 +20399,7 @@ impl Render for Editor {
|
||||||
line_height: relative(settings.buffer_line_height.value()),
|
line_height: relative(settings.buffer_line_height.value()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
EditorMode::Full { .. } => TextStyle {
|
EditorMode::Full { .. } | EditorMode::Minimap { .. } => TextStyle {
|
||||||
color: cx.theme().colors().editor_foreground,
|
color: cx.theme().colors().editor_foreground,
|
||||||
font_family: settings.buffer_font.family.clone(),
|
font_family: settings.buffer_font.family.clone(),
|
||||||
font_features: settings.buffer_font.features.clone(),
|
font_features: settings.buffer_font.features.clone(),
|
||||||
|
@ -20287,8 +20418,11 @@ impl Render for Editor {
|
||||||
EditorMode::SingleLine { .. } => cx.theme().system().transparent,
|
EditorMode::SingleLine { .. } => cx.theme().system().transparent,
|
||||||
EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
|
EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
|
||||||
EditorMode::Full { .. } => cx.theme().colors().editor_background,
|
EditorMode::Full { .. } => cx.theme().colors().editor_background,
|
||||||
|
EditorMode::Minimap { .. } => cx.theme().colors().editor_background.opacity(0.7),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let show_underlines = !self.mode.is_minimap();
|
||||||
|
|
||||||
EditorElement::new(
|
EditorElement::new(
|
||||||
&cx.entity(),
|
&cx.entity(),
|
||||||
EditorStyle {
|
EditorStyle {
|
||||||
|
@ -20301,6 +20435,7 @@ impl Render for Editor {
|
||||||
inlay_hints_style: make_inlay_hints_style(cx),
|
inlay_hints_style: make_inlay_hints_style(cx),
|
||||||
inline_completion_styles: make_suggestion_styles(cx),
|
inline_completion_styles: make_suggestion_styles(cx),
|
||||||
unnecessary_code_fade: ThemeSettings::get_global(cx).unnecessary_code_fade,
|
unnecessary_code_fade: ThemeSettings::get_global(cx).unnecessary_code_fade,
|
||||||
|
show_underlines,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -20912,7 +21047,7 @@ struct BreakpointPromptEditor {
|
||||||
breakpoint: Breakpoint,
|
breakpoint: Breakpoint,
|
||||||
edit_action: BreakpointPromptEditAction,
|
edit_action: BreakpointPromptEditAction,
|
||||||
block_ids: HashSet<CustomBlockId>,
|
block_ids: HashSet<CustomBlockId>,
|
||||||
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
|
editor_margins: Arc<Mutex<EditorMargins>>,
|
||||||
_subscriptions: Vec<Subscription>,
|
_subscriptions: Vec<Subscription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20968,7 +21103,7 @@ impl BreakpointPromptEditor {
|
||||||
breakpoint_anchor,
|
breakpoint_anchor,
|
||||||
breakpoint,
|
breakpoint,
|
||||||
edit_action,
|
edit_action,
|
||||||
gutter_dimensions: Arc::new(Mutex::new(GutterDimensions::default())),
|
editor_margins: Arc::new(Mutex::new(EditorMargins::default())),
|
||||||
block_ids: Default::default(),
|
block_ids: Default::default(),
|
||||||
_subscriptions: vec![],
|
_subscriptions: vec![],
|
||||||
}
|
}
|
||||||
|
@ -21053,7 +21188,8 @@ impl BreakpointPromptEditor {
|
||||||
|
|
||||||
impl Render for BreakpointPromptEditor {
|
impl Render for BreakpointPromptEditor {
|
||||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
let gutter_dimensions = *self.gutter_dimensions.lock();
|
let editor_margins = *self.editor_margins.lock();
|
||||||
|
let gutter_dimensions = editor_margins.gutter;
|
||||||
h_flex()
|
h_flex()
|
||||||
.key_context("Editor")
|
.key_context("Editor")
|
||||||
.bg(cx.theme().colors().editor_background)
|
.bg(cx.theme().colors().editor_background)
|
||||||
|
|
|
@ -15,6 +15,7 @@ pub struct EditorSettings {
|
||||||
pub hover_popover_delay: u64,
|
pub hover_popover_delay: u64,
|
||||||
pub toolbar: Toolbar,
|
pub toolbar: Toolbar,
|
||||||
pub scrollbar: Scrollbar,
|
pub scrollbar: Scrollbar,
|
||||||
|
pub minimap: Minimap,
|
||||||
pub gutter: Gutter,
|
pub gutter: Gutter,
|
||||||
pub scroll_beyond_last_line: ScrollBeyondLastLine,
|
pub scroll_beyond_last_line: ScrollBeyondLastLine,
|
||||||
pub vertical_scroll_margin: f32,
|
pub vertical_scroll_margin: f32,
|
||||||
|
@ -116,6 +117,20 @@ pub struct Scrollbar {
|
||||||
pub axes: ScrollbarAxes,
|
pub axes: ScrollbarAxes,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
pub struct Minimap {
|
||||||
|
pub show: ShowMinimap,
|
||||||
|
pub thumb: MinimapThumb,
|
||||||
|
pub thumb_border: MinimapThumbBorder,
|
||||||
|
pub current_line_highlight: Option<CurrentLineHighlight>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Minimap {
|
||||||
|
pub fn minimap_enabled(&self) -> bool {
|
||||||
|
self.show != ShowMinimap::Never
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||||
pub struct Gutter {
|
pub struct Gutter {
|
||||||
pub line_numbers: bool,
|
pub line_numbers: bool,
|
||||||
|
@ -141,6 +156,53 @@ pub enum ShowScrollbar {
|
||||||
Never,
|
Never,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// When to show the minimap in the editor.
|
||||||
|
///
|
||||||
|
/// Default: never
|
||||||
|
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum ShowMinimap {
|
||||||
|
/// Follow the visibility of the scrollbar.
|
||||||
|
Auto,
|
||||||
|
/// Always show the minimap.
|
||||||
|
Always,
|
||||||
|
/// Never show the minimap.
|
||||||
|
#[default]
|
||||||
|
Never,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// When to show the minimap thumb.
|
||||||
|
///
|
||||||
|
/// Default: always
|
||||||
|
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum MinimapThumb {
|
||||||
|
/// Show the minimap thumb only when the mouse is hovering over the minimap.
|
||||||
|
Hover,
|
||||||
|
/// Always show the minimap thumb.
|
||||||
|
#[default]
|
||||||
|
Always,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Defines the border style for the minimap's scrollbar thumb.
|
||||||
|
///
|
||||||
|
/// Default: left_open
|
||||||
|
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum MinimapThumbBorder {
|
||||||
|
/// Displays a border on all sides of the thumb.
|
||||||
|
Full,
|
||||||
|
/// Displays a border on all sides except the left side of the thumb.
|
||||||
|
#[default]
|
||||||
|
LeftOpen,
|
||||||
|
/// Displays a border on all sides except the right side of the thumb.
|
||||||
|
RightOpen,
|
||||||
|
/// Displays a border only on the left side of the thumb.
|
||||||
|
LeftOnly,
|
||||||
|
/// Displays the thumb without any border.
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
/// Forcefully enable or disable the scrollbar for each axis
|
/// Forcefully enable or disable the scrollbar for each axis
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
|
@ -300,6 +362,8 @@ pub struct EditorSettingsContent {
|
||||||
pub toolbar: Option<ToolbarContent>,
|
pub toolbar: Option<ToolbarContent>,
|
||||||
/// Scrollbar related settings
|
/// Scrollbar related settings
|
||||||
pub scrollbar: Option<ScrollbarContent>,
|
pub scrollbar: Option<ScrollbarContent>,
|
||||||
|
/// Minimap related settings
|
||||||
|
pub minimap: Option<MinimapContent>,
|
||||||
/// Gutter related settings
|
/// Gutter related settings
|
||||||
pub gutter: Option<GutterContent>,
|
pub gutter: Option<GutterContent>,
|
||||||
/// Whether the editor will scroll beyond the last line.
|
/// Whether the editor will scroll beyond the last line.
|
||||||
|
@ -446,6 +510,30 @@ pub struct ScrollbarContent {
|
||||||
pub axes: Option<ScrollbarAxesContent>,
|
pub axes: Option<ScrollbarAxesContent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Minimap related settings
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
pub struct MinimapContent {
|
||||||
|
/// When to show the minimap in the editor.
|
||||||
|
///
|
||||||
|
/// Default: never
|
||||||
|
pub show: Option<ShowMinimap>,
|
||||||
|
|
||||||
|
/// When to show the minimap thumb.
|
||||||
|
///
|
||||||
|
/// Default: always
|
||||||
|
pub thumb: Option<MinimapThumb>,
|
||||||
|
|
||||||
|
/// Defines the border style for the minimap's scrollbar thumb.
|
||||||
|
///
|
||||||
|
/// Default: left_open
|
||||||
|
pub thumb_border: Option<MinimapThumbBorder>,
|
||||||
|
|
||||||
|
/// How to highlight the current line in the minimap.
|
||||||
|
///
|
||||||
|
/// Default: inherits editor line highlights setting
|
||||||
|
pub current_line_highlight: Option<Option<CurrentLineHighlight>>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Forcefully enable or disable the scrollbar for each axis
|
/// Forcefully enable or disable the scrollbar for each axis
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Default)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Default)]
|
||||||
pub struct ScrollbarAxesContent {
|
pub struct ScrollbarAxesContent {
|
||||||
|
|
|
@ -4327,6 +4327,7 @@ fn test_move_line_up_down_with_blocks(cx: &mut TestAppContext) {
|
||||||
height: Some(1),
|
height: Some(1),
|
||||||
render: Arc::new(|_| div().into_any()),
|
render: Arc::new(|_| div().into_any()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
}],
|
}],
|
||||||
Some(Autoscroll::fit()),
|
Some(Autoscroll::fit()),
|
||||||
cx,
|
cx,
|
||||||
|
@ -4369,6 +4370,7 @@ async fn test_selections_and_replace_blocks(cx: &mut TestAppContext) {
|
||||||
style: BlockStyle::Sticky,
|
style: BlockStyle::Sticky,
|
||||||
render: Arc::new(|_| gpui::div().into_any_element()),
|
render: Arc::new(|_| gpui::div().into_any_element()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
}],
|
}],
|
||||||
None,
|
None,
|
||||||
cx,
|
cx,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1225,6 +1225,9 @@ impl SerializableItem for Editor {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> Option<Task<Result<()>>> {
|
) -> Option<Task<Result<()>>> {
|
||||||
|
if self.mode.is_minimap() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let mut serialize_dirty_buffers = self.serialize_dirty_buffers;
|
let mut serialize_dirty_buffers = self.serialize_dirty_buffers;
|
||||||
|
|
||||||
let project = self.project.clone()?;
|
let project = self.project.clone()?;
|
||||||
|
@ -1382,7 +1385,7 @@ impl Editor {
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
write: impl for<'a> FnOnce(&'a mut RestorationData) + 'static,
|
write: impl for<'a> FnOnce(&'a mut RestorationData) + 'static,
|
||||||
) {
|
) {
|
||||||
if !WorkspaceSettings::get(None, cx).restore_on_file_reopen {
|
if self.mode.is_minimap() || !WorkspaceSettings::get(None, cx).restore_on_file_reopen {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -157,6 +157,8 @@ pub struct ScrollManager {
|
||||||
active_scrollbar: Option<ActiveScrollbarState>,
|
active_scrollbar: Option<ActiveScrollbarState>,
|
||||||
visible_line_count: Option<f32>,
|
visible_line_count: Option<f32>,
|
||||||
forbid_vertical_scroll: bool,
|
forbid_vertical_scroll: bool,
|
||||||
|
dragging_minimap: bool,
|
||||||
|
show_minimap_thumb: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScrollManager {
|
impl ScrollManager {
|
||||||
|
@ -172,6 +174,8 @@ impl ScrollManager {
|
||||||
last_autoscroll: None,
|
last_autoscroll: None,
|
||||||
visible_line_count: None,
|
visible_line_count: None,
|
||||||
forbid_vertical_scroll: false,
|
forbid_vertical_scroll: false,
|
||||||
|
dragging_minimap: false,
|
||||||
|
show_minimap_thumb: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,6 +345,24 @@ impl ScrollManager {
|
||||||
self.show_scrollbars
|
self.show_scrollbars
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn show_minimap_thumb(&mut self, cx: &mut Context<Editor>) {
|
||||||
|
if !self.show_minimap_thumb {
|
||||||
|
self.show_minimap_thumb = true;
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hide_minimap_thumb(&mut self, cx: &mut Context<Editor>) {
|
||||||
|
if self.show_minimap_thumb {
|
||||||
|
self.show_minimap_thumb = false;
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn minimap_thumb_visible(&mut self) -> bool {
|
||||||
|
self.show_minimap_thumb
|
||||||
|
}
|
||||||
|
|
||||||
pub fn autoscroll_request(&self) -> Option<Autoscroll> {
|
pub fn autoscroll_request(&self) -> Option<Autoscroll> {
|
||||||
self.autoscroll_request.map(|(autoscroll, _)| autoscroll)
|
self.autoscroll_request.map(|(autoscroll, _)| autoscroll)
|
||||||
}
|
}
|
||||||
|
@ -396,6 +418,15 @@ impl ScrollManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_dragging_minimap(&self) -> bool {
|
||||||
|
self.dragging_minimap
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_is_dragging_minimap(&mut self, dragging: bool, cx: &mut Context<Editor>) {
|
||||||
|
self.dragging_minimap = dragging;
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clamp_scroll_left(&mut self, max: f32) -> bool {
|
pub fn clamp_scroll_left(&mut self, max: f32) -> bool {
|
||||||
if max < self.anchor.offset.x {
|
if max < self.anchor.offset.x {
|
||||||
self.anchor.offset.x = max;
|
self.anchor.offset.x = max;
|
||||||
|
|
|
@ -297,6 +297,7 @@ fn conflicts_updated(
|
||||||
move |cx| render_conflict_buttons(&conflict, excerpt_id, editor_handle.clone(), cx)
|
move |cx| render_conflict_buttons(&conflict, excerpt_id, editor_handle.clone(), cx)
|
||||||
}),
|
}),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let new_block_ids = editor.insert_blocks(blocks, None, cx);
|
let new_block_ids = editor.insert_blocks(blocks, None, cx);
|
||||||
|
@ -387,7 +388,7 @@ fn render_conflict_buttons(
|
||||||
h_flex()
|
h_flex()
|
||||||
.h(cx.line_height)
|
.h(cx.line_height)
|
||||||
.items_end()
|
.items_end()
|
||||||
.ml(cx.gutter_dimensions.width)
|
.ml(cx.margins.gutter.width)
|
||||||
.id(cx.block_id)
|
.id(cx.block_id)
|
||||||
.gap_0p5()
|
.gap_0p5()
|
||||||
.child(
|
.child(
|
||||||
|
|
|
@ -91,7 +91,8 @@ impl CursorPosition {
|
||||||
cursor_position.selected_count.selections = editor.selections.count();
|
cursor_position.selected_count.selections = editor.selections.count();
|
||||||
match editor.mode() {
|
match editor.mode() {
|
||||||
editor::EditorMode::AutoHeight { .. }
|
editor::EditorMode::AutoHeight { .. }
|
||||||
| editor::EditorMode::SingleLine { .. } => {
|
| editor::EditorMode::SingleLine { .. }
|
||||||
|
| editor::EditorMode::Minimap { .. } => {
|
||||||
cursor_position.position = None;
|
cursor_position.position = None;
|
||||||
cursor_position.context = None;
|
cursor_position.context = None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,7 @@ impl EditorBlock {
|
||||||
style: BlockStyle::Sticky,
|
style: BlockStyle::Sticky,
|
||||||
render: Self::create_output_area_renderer(execution_view.clone(), on_close.clone()),
|
render: Self::create_output_area_renderer(execution_view.clone(), on_close.clone()),
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
render_in_minimap: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let block_id = editor.insert_blocks([block], None, cx)[0];
|
let block_id = editor.insert_blocks([block], None, cx)[0];
|
||||||
|
@ -126,7 +127,8 @@ impl EditorBlock {
|
||||||
let execution_view = execution_view.clone();
|
let execution_view = execution_view.clone();
|
||||||
let text_style = crate::outputs::plain::text_style(cx.window, cx.app);
|
let text_style = crate::outputs::plain::text_style(cx.window, cx.app);
|
||||||
|
|
||||||
let gutter = cx.gutter_dimensions;
|
let editor_margins = cx.margins;
|
||||||
|
let gutter = editor_margins.gutter;
|
||||||
|
|
||||||
let block_id = cx.block_id;
|
let block_id = cx.block_id;
|
||||||
let on_close = on_close.clone();
|
let on_close = on_close.clone();
|
||||||
|
@ -184,7 +186,8 @@ impl EditorBlock {
|
||||||
.flex_1()
|
.flex_1()
|
||||||
.size_full()
|
.size_full()
|
||||||
.py(text_line_height / 2.)
|
.py(text_line_height / 2.)
|
||||||
.mr(gutter.width)
|
.mr(editor_margins.right)
|
||||||
|
.pr_2()
|
||||||
.child(execution_view),
|
.child(execution_view),
|
||||||
)
|
)
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
|
|
|
@ -1140,10 +1140,10 @@ impl Vim {
|
||||||
let editor_mode = editor.mode();
|
let editor_mode = editor.mode();
|
||||||
|
|
||||||
if editor_mode.is_full()
|
if editor_mode.is_full()
|
||||||
&& !newest_selection_empty
|
&& !newest_selection_empty
|
||||||
&& self.mode == Mode::Normal
|
&& self.mode == Mode::Normal
|
||||||
// When following someone, don't switch vim mode.
|
// When following someone, don't switch vim mode.
|
||||||
&& editor.leader_id().is_none()
|
&& editor.leader_id().is_none()
|
||||||
{
|
{
|
||||||
if preserve_selection {
|
if preserve_selection {
|
||||||
self.switch_mode(Mode::Visual, true, window, cx);
|
self.switch_mode(Mode::Visual, true, window, cx);
|
||||||
|
|
|
@ -275,9 +275,9 @@ impl RateCompletionModal {
|
||||||
completion,
|
completion,
|
||||||
feedback_editor: cx.new(|cx| {
|
feedback_editor: cx.new(|cx| {
|
||||||
let mut editor = Editor::multi_line(window, cx);
|
let mut editor = Editor::multi_line(window, cx);
|
||||||
|
editor.disable_scrollbars_and_minimap(cx);
|
||||||
editor.set_soft_wrap_mode(language_settings::SoftWrap::EditorWidth, cx);
|
editor.set_soft_wrap_mode(language_settings::SoftWrap::EditorWidth, cx);
|
||||||
editor.set_show_line_numbers(false, cx);
|
editor.set_show_line_numbers(false, cx);
|
||||||
editor.set_show_scrollbars(false, cx);
|
|
||||||
editor.set_show_git_diff_gutter(false, cx);
|
editor.set_show_git_diff_gutter(false, cx);
|
||||||
editor.set_show_code_actions(false, cx);
|
editor.set_show_code_actions(false, cx);
|
||||||
editor.set_show_runnables(false, cx);
|
editor.set_show_runnables(false, cx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue