diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index ebe78d95b3ea942e3cdcbcfb5a1b2dad5c09ed89..3a5b150520cc76842f6eafb87bc64ab2c674e28e 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -40,7 +40,7 @@ use fuzzy::{StringMatch, StringMatchCandidate}; use git::diff_hunk_to_display; use gpui::{ action, actions, div, point, px, relative, rems, size, uniform_list, AnyElement, AppContext, - AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Component, Context, + AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Component, Context, Entity, EventEmitter, FocusHandle, FontFeatures, FontStyle, FontWeight, HighlightStyle, Hsla, InputHandler, KeyContext, Model, MouseButton, ParentElement, Pixels, Render, StatefulInteractive, StatelessInteractive, Styled, Subscription, Task, TextStyle, @@ -100,7 +100,9 @@ use theme::{ use ui::{v_stack, HighlightedLabel, IconButton, StyledExt, TextTooltip}; use util::{post_inc, RangeExt, ResultExt, TryFutureExt}; use workspace::{ - item::ItemEvent, searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace, + item::{ItemEvent, ItemHandle}, + searchable::SearchEvent, + ItemNavHistory, SplitDirection, ViewId, Workspace, }; const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500); @@ -7690,183 +7692,183 @@ impl Editor { } } - // pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext) -> Option>> { - // use language::ToOffset as _; + pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext) -> Option>> { + use language::ToOffset as _; - // let project = self.project.clone()?; - // let selection = self.selections.newest_anchor().clone(); - // let (cursor_buffer, cursor_buffer_position) = self - // .buffer - // .read(cx) - // .text_anchor_for_position(selection.head(), cx)?; - // let (tail_buffer, _) = self - // .buffer - // .read(cx) - // .text_anchor_for_position(selection.tail(), cx)?; - // if tail_buffer != cursor_buffer { - // return None; - // } + let project = self.project.clone()?; + let selection = self.selections.newest_anchor().clone(); + let (cursor_buffer, cursor_buffer_position) = self + .buffer + .read(cx) + .text_anchor_for_position(selection.head(), cx)?; + let (tail_buffer, _) = self + .buffer + .read(cx) + .text_anchor_for_position(selection.tail(), cx)?; + if tail_buffer != cursor_buffer { + return None; + } - // let snapshot = cursor_buffer.read(cx).snapshot(); - // let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot); - // let prepare_rename = project.update(cx, |project, cx| { - // project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx) - // }); + let snapshot = cursor_buffer.read(cx).snapshot(); + let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot); + let prepare_rename = project.update(cx, |project, cx| { + project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx) + }); - // Some(cx.spawn(|this, mut cx| async move { - // let rename_range = if let Some(range) = prepare_rename.await? { - // Some(range) - // } else { - // this.update(&mut cx, |this, cx| { - // let buffer = this.buffer.read(cx).snapshot(cx); - // let mut buffer_highlights = this - // .document_highlights_for_position(selection.head(), &buffer) - // .filter(|highlight| { - // highlight.start.excerpt_id == selection.head().excerpt_id - // && highlight.end.excerpt_id == selection.head().excerpt_id - // }); - // buffer_highlights - // .next() - // .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor) - // })? - // }; - // if let Some(rename_range) = rename_range { - // let rename_buffer_range = rename_range.to_offset(&snapshot); - // let cursor_offset_in_rename_range = - // cursor_buffer_offset.saturating_sub(rename_buffer_range.start); - - // this.update(&mut cx, |this, cx| { - // this.take_rename(false, cx); - // let buffer = this.buffer.read(cx).read(cx); - // let cursor_offset = selection.head().to_offset(&buffer); - // let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range); - // let rename_end = rename_start + rename_buffer_range.len(); - // let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end); - // let mut old_highlight_id = None; - // let old_name: Arc = buffer - // .chunks(rename_start..rename_end, true) - // .map(|chunk| { - // if old_highlight_id.is_none() { - // old_highlight_id = chunk.syntax_highlight_id; - // } - // chunk.text - // }) - // .collect::() - // .into(); - - // drop(buffer); - - // // Position the selection in the rename editor so that it matches the current selection. - // this.show_local_selections = false; - // let rename_editor = cx.build_view(|cx| { - // let mut editor = Editor::single_line(cx); - // if let Some(old_highlight_id) = old_highlight_id { - // editor.override_text_style = - // Some(Box::new(move |style| old_highlight_id.style(&style.syntax))); - // } - // editor.buffer.update(cx, |buffer, cx| { - // buffer.edit([(0..0, old_name.clone())], None, cx) - // }); - // editor.select_all(&SelectAll, cx); - // editor - // }); + Some(cx.spawn(|this, mut cx| async move { + let rename_range = if let Some(range) = prepare_rename.await? { + Some(range) + } else { + this.update(&mut cx, |this, cx| { + let buffer = this.buffer.read(cx).snapshot(cx); + let mut buffer_highlights = this + .document_highlights_for_position(selection.head(), &buffer) + .filter(|highlight| { + highlight.start.excerpt_id == selection.head().excerpt_id + && highlight.end.excerpt_id == selection.head().excerpt_id + }); + buffer_highlights + .next() + .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor) + })? + }; + if let Some(rename_range) = rename_range { + let rename_buffer_range = rename_range.to_offset(&snapshot); + let cursor_offset_in_rename_range = + cursor_buffer_offset.saturating_sub(rename_buffer_range.start); - // let ranges = this - // .clear_background_highlights::(cx) - // .into_iter() - // .flat_map(|(_, ranges)| ranges.into_iter()) - // .chain( - // this.clear_background_highlights::(cx) - // .into_iter() - // .flat_map(|(_, ranges)| ranges.into_iter()), - // ) - // .collect(); - - // this.highlight_text::( - // ranges, - // HighlightStyle { - // fade_out: Some(style.rename_fade), - // ..Default::default() - // }, - // cx, - // ); - // cx.focus(&rename_editor); - // let block_id = this.insert_blocks( - // [BlockProperties { - // style: BlockStyle::Flex, - // position: range.start.clone(), - // height: 1, - // render: Arc::new({ - // let editor = rename_editor.clone(); - // move |cx: &mut BlockContext| { - // ChildView::new(&editor, cx) - // .contained() - // .with_padding_left(cx.anchor_x) - // .into_any() - // } - // }), - // disposition: BlockDisposition::Below, - // }], - // Some(Autoscroll::fit()), - // cx, - // )[0]; - // this.pending_rename = Some(RenameState { - // range, - // old_name, - // editor: rename_editor, - // block_id, - // }); - // })?; - // } + this.update(&mut cx, |this, cx| { + this.take_rename(false, cx); + let buffer = this.buffer.read(cx).read(cx); + let cursor_offset = selection.head().to_offset(&buffer); + let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range); + let rename_end = rename_start + rename_buffer_range.len(); + let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end); + let mut old_highlight_id = None; + let old_name: Arc = buffer + .chunks(rename_start..rename_end, true) + .map(|chunk| { + if old_highlight_id.is_none() { + old_highlight_id = chunk.syntax_highlight_id; + } + chunk.text + }) + .collect::() + .into(); - // Ok(()) - // })) - // } + drop(buffer); - // pub fn confirm_rename( - // workspace: &mut Workspace, - // _: &ConfirmRename, - // cx: &mut ViewContext, - // ) -> Option>> { - // let editor = workspace.active_item(cx)?.act_as::(cx)?; - - // let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| { - // let rename = editor.take_rename(false, cx)?; - // let buffer = editor.buffer.read(cx); - // let (start_buffer, start) = - // buffer.text_anchor_for_position(rename.range.start.clone(), cx)?; - // let (end_buffer, end) = - // buffer.text_anchor_for_position(rename.range.end.clone(), cx)?; - // if start_buffer == end_buffer { - // let new_name = rename.editor.read(cx).text(cx); - // Some((start_buffer, start..end, rename.old_name, new_name)) - // } else { - // None - // } - // })?; + // Position the selection in the rename editor so that it matches the current selection. + this.show_local_selections = false; + let rename_editor = cx.build_view(|cx| { + let mut editor = Editor::single_line(cx); + editor.buffer.update(cx, |buffer, cx| { + buffer.edit([(0..0, old_name.clone())], None, cx) + }); + editor.select_all(&SelectAll, cx); + editor + }); - // let rename = workspace.project().clone().update(cx, |project, cx| { - // project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx) - // }); + let ranges = this + .clear_background_highlights::(cx) + .into_iter() + .flat_map(|(_, ranges)| ranges.into_iter()) + .chain( + this.clear_background_highlights::(cx) + .into_iter() + .flat_map(|(_, ranges)| ranges.into_iter()), + ) + .collect(); - // let editor = editor.downgrade(); - // Some(cx.spawn(|workspace, mut cx| async move { - // let project_transaction = rename.await?; - // Self::open_project_transaction( - // &editor, - // workspace, - // project_transaction, - // format!("Rename: {} → {}", old_name, new_name), - // cx.clone(), - // ) - // .await?; + this.highlight_text::( + ranges, + HighlightStyle { + fade_out: Some(0.6), + ..Default::default() + }, + cx, + ); + let rename_focus_handle = rename_editor.focus_handle(cx); + cx.focus(&rename_focus_handle); + let block_id = this.insert_blocks( + [BlockProperties { + style: BlockStyle::Flex, + position: range.start.clone(), + height: 1, + render: Arc::new({ + let editor = rename_editor.clone(); + move |cx: &mut BlockContext| { + div().pl(cx.anchor_x).child(editor.clone()).render() + } + }), + disposition: BlockDisposition::Below, + }], + Some(Autoscroll::fit()), + cx, + )[0]; + this.pending_rename = Some(RenameState { + range, + old_name, + editor: rename_editor, + block_id, + }); + })?; + } - // editor.update(&mut cx, |editor, cx| { - // editor.refresh_document_highlights(cx); - // })?; - // Ok(()) - // })) - // } + Ok(()) + })) + } + + pub fn confirm_rename( + &mut self, + _: &ConfirmRename, + cx: &mut ViewContext, + ) -> Option>> { + let rename = self.take_rename(false, cx)?; + let workspace = self.workspace()?; + let (start_buffer, start) = self + .buffer + .read(cx) + .text_anchor_for_position(rename.range.start.clone(), cx)?; + let (end_buffer, end) = self + .buffer + .read(cx) + .text_anchor_for_position(rename.range.end.clone(), cx)?; + if start_buffer != end_buffer { + return None; + } + + let buffer = start_buffer; + let range = start..end; + let old_name = rename.old_name; + let new_name = rename.editor.read(cx).text(cx); + + let rename = workspace + .read(cx) + .project() + .clone() + .update(cx, |project, cx| { + project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx) + }); + let workspace = workspace.downgrade(); + + Some(cx.spawn(|editor, mut cx| async move { + let project_transaction = rename.await?; + Self::open_project_transaction( + &editor, + workspace, + project_transaction, + format!("Rename: {} → {}", old_name, new_name), + cx.clone(), + ) + .await?; + + editor.update(&mut cx, |editor, cx| { + editor.refresh_document_highlights(cx); + })?; + Ok(()) + })) + } fn take_rename( &mut self, diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 638ed3389191e364d0a382c285b0af456db3ee92..b8e7439ff16be1ed9723cc5ce2d57104554c8b88 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2007,7 +2007,6 @@ impl EditorElement { anchor_x, gutter_padding, line_height, - // scroll_x, gutter_width, em_width, block_id, @@ -2569,8 +2568,16 @@ impl Element for EditorElement { .confirm_code_action(action, cx) .map(|task| task.detach_and_log_err(cx)); }); - // on_action(cx, Editor::rename); todo!() - // on_action(cx, Editor::confirm_rename); todo!() + register_action(cx, |editor, action, cx| { + editor + .rename(action, cx) + .map(|task| task.detach_and_log_err(cx)); + }); + register_action(cx, |editor, action, cx| { + editor + .confirm_rename(action, cx) + .map(|task| task.detach_and_log_err(cx)); + }); register_action(cx, |editor, action, cx| { editor .find_all_references(action, cx)