@@ -480,7 +480,9 @@ struct SnippetState {
struct RenameState {
range: Range<Anchor>,
- first_transaction: Option<TransactionId>,
+ old_name: String,
+ editor: ViewHandle<Editor>,
+ block_id: BlockId,
}
struct InvalidationStack<T>(Vec<T>);
@@ -3161,6 +3163,26 @@ impl Editor {
}
pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
+ 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::<String>();
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::<Rename>(
+ vec![Anchor::min()..Anchor::max()],
+ settings.style.diff_background_inserted,
+ cx,
+ );
+ editor
});
- this.select_ranges([start..end], None, cx);
this.highlight_ranges::<Rename>(
- 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<Task<Result<()>>> {
let editor = workspace.active_item(cx)?.act_as::<Editor>(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<Self>) -> Option<(Range<Anchor>, String)> {
+ fn take_rename(
+ &mut self,
+ cx: &mut ViewContext<Self>,
+ ) -> Option<(Range<Anchor>, 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::<String>();
-
+ 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::<Point>(&buffer);
+ self.remove_blocks([rename.block_id].into_iter().collect(), cx);
self.clear_highlighted_ranges::<Rename>(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(),
@@ -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<u32, bool>,
@@ -1135,7 +1144,6 @@ pub struct LayoutState {
em_advance: f32,
highlighted_ranges: Vec<(Range<DisplayPoint>, Color)>,
selections: HashMap<ReplicaId, Vec<text::Selection<DisplayPoint>>>,
- text_offset: Vector2F,
context_menu: Option<(DisplayPoint, ElementBox)>,
code_actions_indicator: Option<(u32, ElementBox)>,
}
@@ -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<SelectionStyle>,
@@ -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(),