diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 465cbac3ca55df830ed2020b3797a442a24fc231..cdcd1655e734fd4ae1663206adad7280241995ad 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -480,7 +480,9 @@ struct SnippetState { struct RenameState { range: Range, - first_transaction: Option, + old_name: String, + editor: ViewHandle, + block_id: BlockId, } struct InvalidationStack(Vec); @@ -3161,6 +3163,26 @@ impl Editor { } pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext) { + if let Some((range, column, _, _)) = self.take_rename(cx) { + let snapshot = self.buffer.read(cx).snapshot(cx); + let position = snapshot.clip_point( + range.start.to_point(&snapshot) + Point::new(0, column), + Bias::Left, + ); + self.update_selections( + vec![Selection { + id: self.newest_anchor_selection().id, + start: position, + end: position, + reversed: false, + goal: SelectionGoal::None, + }], + None, + cx, + ); + return; + } + if let Some(context_menu) = self.context_menu.as_mut() { if context_menu.select_prev(cx) { return; @@ -4118,20 +4140,51 @@ impl Editor { let start = offset - lookbehind; let end = offset + lookahead; let rename_range = buffer.anchor_before(start)..buffer.anchor_after(end); + let old_name = buffer.text_for_range(start..end).collect::(); drop(buffer); - this.buffer - .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx)); - this.pending_rename = Some(RenameState { - range: rename_range.clone(), - first_transaction: None, + let editor = cx.add_view(|cx| { + let mut editor = Editor::single_line(this.build_settings.clone(), cx); + editor + .buffer + .update(cx, |buffer, cx| buffer.edit([0..0], &old_name, cx)); + editor.select_ranges([0..old_name.len()], None, cx); + editor.highlight_ranges::( + vec![Anchor::min()..Anchor::max()], + settings.style.diff_background_inserted, + cx, + ); + editor }); - this.select_ranges([start..end], None, cx); this.highlight_ranges::( - vec![rename_range], - settings.style.highlighted_line_background, + vec![rename_range.clone()], + settings.style.diff_background_deleted, cx, ); + cx.focus(&editor); + let block_id = this.insert_blocks( + [BlockProperties { + position: rename_range.start.clone(), + height: 1, + render: Arc::new({ + let editor = editor.clone(); + move |cx: &BlockContext| { + ChildView::new(editor.clone()) + .contained() + .with_padding_left(cx.anchor_x) + .boxed() + } + }), + disposition: BlockDisposition::Below, + }], + cx, + )[0]; + this.pending_rename = Some(RenameState { + range: rename_range, + old_name, + editor, + block_id, + }); }); } @@ -4146,13 +4199,13 @@ impl Editor { ) -> Option>> { let editor = workspace.active_item(cx)?.act_as::(cx)?; - let (buffer, range, new_name) = editor.update(cx, |editor, cx| { - let (range, new_name) = editor.take_rename(cx)?; + let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| { + let (range, _, old_name, new_name) = editor.take_rename(cx)?; let buffer = editor.buffer.read(cx); let (start_buffer, start) = buffer.text_anchor_for_position(range.start.clone(), cx)?; let (end_buffer, end) = buffer.text_anchor_for_position(range.end.clone(), cx)?; if start_buffer == end_buffer { - Some((start_buffer, start..end, new_name)) + Some((start_buffer, start..end, old_name, new_name)) } else { None } @@ -4168,55 +4221,36 @@ impl Editor { ) }); - let transaction = buffer.update(cx, |buffer, cx| { - buffer.finalize_last_transaction(); - buffer.start_transaction(); - buffer.edit([range], &new_name, cx); - if buffer.end_transaction(cx).is_some() { - let transaction = buffer.finalize_last_transaction().unwrap().clone(); - buffer.forget_transaction(transaction.id); - Some(transaction) - } else { - None - } - }); - - Some(cx.spawn(|workspace, mut cx| async move { + Some(cx.spawn(|workspace, cx| async move { let project_transaction = rename.await?; - if let Some(transaction) = transaction { - buffer.update(&mut cx, |buffer, cx| { - buffer.push_transaction(transaction, Instant::now()); - buffer.undo(cx); - }); - } Self::open_project_transaction( editor, workspace, project_transaction, - format!("Rename: {}", new_name), + format!("Rename: {} → {}", old_name, new_name), cx, ) .await })) } - fn take_rename(&mut self, cx: &mut ViewContext) -> Option<(Range, String)> { + fn take_rename( + &mut self, + cx: &mut ViewContext, + ) -> Option<(Range, u32, String, String)> { let rename = self.pending_rename.take()?; - let new_name = self - .buffer - .read(cx) - .read(cx) - .text_for_range(rename.range.clone()) - .collect::(); - + let editor = rename.editor.read(cx); + let new_name = editor.text(cx); + let buffer = editor.buffer.read(cx).snapshot(cx); + let rename_position = editor.newest_selection::(&buffer); + self.remove_blocks([rename.block_id].into_iter().collect(), cx); self.clear_highlighted_ranges::(cx); - if let Some(transaction_id) = rename.first_transaction { - self.buffer.update(cx, |buffer, cx| { - buffer.undo_to_transaction(transaction_id, false, cx) - }); - } - - Some((rename.range, new_name)) + Some(( + rename.range, + rename_position.head().column, + rename.old_name, + new_name, + )) } fn invalidate_rename_range( @@ -4722,12 +4756,6 @@ impl Editor { .buffer .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx)) { - if let Some(rename) = self.pending_rename.as_mut() { - if rename.first_transaction.is_none() { - rename.first_transaction = Some(tx_id); - } - } - if let Some((_, end_selections)) = self.selection_history.get_mut(&tx_id) { *end_selections = Some(self.selections.clone()); } else { @@ -5146,6 +5174,8 @@ impl EditorSettings { gutter_padding_factor: 2., active_line_background: Default::default(), highlighted_line_background: Default::default(), + diff_background_deleted: Default::default(), + diff_background_inserted: Default::default(), line_number: Default::default(), line_number_active: Default::default(), selection: Default::default(), diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index f72320be42a2973d9502be4a509ddc349ca13652..10a7656f733f9bac27f1f17284a2c4bc5de9201f 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -299,7 +299,7 @@ impl EditorElement { if let Some((row, indicator)) = layout.code_actions_indicator.as_mut() { let mut x = bounds.width() - layout.gutter_padding; let mut y = *row as f32 * layout.line_height - scroll_top; - x += ((layout.gutter_padding + layout.text_offset.x()) - indicator.size().x()) / 2.; + x += ((layout.gutter_padding + layout.gutter_margin) - indicator.size().x()) / 2.; y += (layout.line_height - indicator.size().y()) / 2.; indicator.paint(bounds.origin() + vec2f(x, y), visible_bounds, cx); } @@ -321,7 +321,7 @@ impl EditorElement { let end_row = ((scroll_top + bounds.height()) / layout.line_height).ceil() as u32 + 1; // Add 1 to ensure selections bleed off screen let max_glyph_width = layout.em_width; let scroll_left = scroll_position.x() * max_glyph_width; - let content_origin = bounds.origin() + layout.text_offset; + let content_origin = bounds.origin() + layout.gutter_margin; cx.scene.push_layer(Some(bounds)); @@ -776,22 +776,24 @@ impl Element for EditorElement { let gutter_padding; let gutter_width; + let gutter_margin; if snapshot.mode == EditorMode::Full { gutter_padding = style.text.em_width(cx.font_cache) * style.gutter_padding_factor; gutter_width = self.max_line_number_width(&snapshot, cx) + gutter_padding * 2.0; + gutter_margin = -style.text.descent(cx.font_cache); } else { gutter_padding = 0.0; - gutter_width = 0.0 + gutter_width = 0.0; + gutter_margin = 0.0; }; let text_width = size.x() - gutter_width; - let text_offset = vec2f(-style.text.descent(cx.font_cache), 0.); let em_width = style.text.em_width(cx.font_cache); let em_advance = style.text.em_advance(cx.font_cache); let overscroll = vec2f(em_width, 0.); let wrap_width = match self.settings.soft_wrap { SoftWrap::None => None, - SoftWrap::EditorWidth => Some(text_width - text_offset.x() - overscroll.x() - em_width), + SoftWrap::EditorWidth => Some(text_width - gutter_margin - overscroll.x() - em_width), SoftWrap::Column(column) => Some(column as f32 * em_advance), }; let snapshot = self.update_view(cx.app, |view, cx| { @@ -991,7 +993,7 @@ impl Element for EditorElement { gutter_padding, gutter_width, em_width, - gutter_width + text_offset.x(), + gutter_width + gutter_margin, line_height, &style, &line_layouts, @@ -1006,7 +1008,7 @@ impl Element for EditorElement { gutter_size, gutter_padding, text_size, - text_offset, + gutter_margin, snapshot, active_rows, highlighted_rows, @@ -1080,6 +1082,12 @@ impl Element for EditorElement { } } + for (_, block) in &mut layout.blocks { + if block.dispatch_event(event, cx) { + return true; + } + } + match event { Event::LeftMouseDown { position, @@ -1123,6 +1131,7 @@ pub struct LayoutState { scroll_max: Vector2F, gutter_size: Vector2F, gutter_padding: f32, + gutter_margin: f32, text_size: Vector2F, snapshot: EditorSnapshot, active_rows: BTreeMap, @@ -1135,7 +1144,6 @@ pub struct LayoutState { em_advance: f32, highlighted_ranges: Vec<(Range, Color)>, selections: HashMap>>, - text_offset: Vector2F, context_menu: Option<(DisplayPoint, ElementBox)>, code_actions_indicator: Option<(u32, ElementBox)>, } diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index db078cd862e5f055550971ccbad0aa169dc244e9..1e63830792f2e5c9e84a7e2261a171cf60318f70 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -278,6 +278,8 @@ pub struct EditorStyle { pub gutter_padding_factor: f32, pub active_line_background: Color, pub highlighted_line_background: Color, + pub diff_background_deleted: Color, + pub diff_background_inserted: Color, pub line_number: Color, pub line_number_active: Color, pub guest_selections: Vec, @@ -383,6 +385,8 @@ impl InputEditorStyle { gutter_padding_factor: Default::default(), active_line_background: Default::default(), highlighted_line_background: Default::default(), + diff_background_deleted: Default::default(), + diff_background_inserted: Default::default(), line_number: Default::default(), line_number_active: Default::default(), guest_selections: Default::default(), diff --git a/crates/zed/assets/themes/_base.toml b/crates/zed/assets/themes/_base.toml index 389f4571070cc3dd2274fd1cfc9ed5f30f75699d..5d03b96e7447c1f07928c8233a022130b1d8de85 100644 --- a/crates/zed/assets/themes/_base.toml +++ b/crates/zed/assets/themes/_base.toml @@ -188,7 +188,7 @@ corner_radius = 6 [project_panel] extends = "$panel" -padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2 +padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2 [project_panel.entry] text = "$text.1" @@ -248,6 +248,8 @@ gutter_background = "$surface.1" gutter_padding_factor = 2.5 active_line_background = "$state.active_line" highlighted_line_background = "$state.highlighted_line" +diff_background_deleted = "$state.deleted_line" +diff_background_inserted = "$state.inserted_line" line_number = "$text.2.color" line_number_active = "$text.0.color" selection = "$selection.host" diff --git a/crates/zed/assets/themes/black.toml b/crates/zed/assets/themes/black.toml index bc9f6c75d6430b65571ecea79c2d3c8bba9f1be8..8bc60207ae91c17f358de540aec319a949b5db01 100644 --- a/crates/zed/assets/themes/black.toml +++ b/crates/zed/assets/themes/black.toml @@ -39,6 +39,8 @@ bad = "#b7372e" [state] active_line = "#161313" highlighted_line = "#faca5033" +deleted_line = "#dd000022" +inserted_line = "#00dd0022" hover = "#00000033" selected = "#00000088" diff --git a/crates/zed/assets/themes/dark.toml b/crates/zed/assets/themes/dark.toml index acfbf083c0a03d296502448d272aab6eb50b93aa..678127e21fc31635b815a7f3d5a512a663145fa8 100644 --- a/crates/zed/assets/themes/dark.toml +++ b/crates/zed/assets/themes/dark.toml @@ -39,6 +39,8 @@ bad = "#b7372e" [state] active_line = "#00000022" highlighted_line = "#faca5033" +deleted_line = "#dd000044" +inserted_line = "#00dd0044" hover = "#00000033" selected = "#00000088" diff --git a/crates/zed/assets/themes/light.toml b/crates/zed/assets/themes/light.toml index cf8ebe34e608605ee57254b1b92310c173ddadc1..934dc59a6dd8d80fab3cc19c9bec51eb749c9a2e 100644 --- a/crates/zed/assets/themes/light.toml +++ b/crates/zed/assets/themes/light.toml @@ -39,6 +39,8 @@ bad = "#b7372e" [state] active_line = "#00000008" highlighted_line = "#faca5033" +deleted_line = "#dd000044" +inserted_line = "#00dd0044" hover = "#0000000D" selected = "#0000001c"