Refine inline transformation UX (#12939)

https://github.com/zed-industries/zed/assets/482957/1790e32e-1f59-4831-8a4c-722cf441e7e9



Release Notes:

- N/A

---------

Co-authored-by: Richard <richard@zed.dev>
Co-authored-by: Nathan <nathan@zed.dev>
This commit is contained in:
Antonio Scandurra
2024-06-13 08:35:22 +02:00
committed by GitHub
co-authored by Richard Nathan
parent 9e3c5f3e12
commit e1f4dfc068
20 changed files with 419 additions and 219 deletions
+74 -46
View File
@@ -116,15 +116,16 @@ use serde::{Deserialize, Serialize};
use settings::{update_settings_file, Settings, SettingsStore};
use smallvec::SmallVec;
use snippet::Snippet;
use std::ops::Not as _;
use std::{
any::TypeId,
borrow::Cow,
cell::RefCell,
cmp::{self, Ordering, Reverse},
mem,
num::NonZeroU32,
ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
ops::{ControlFlow, Deref, DerefMut, Not as _, Range, RangeInclusive},
path::Path,
rc::Rc,
sync::Arc,
time::{Duration, Instant},
};
@@ -377,6 +378,19 @@ impl Default for EditorStyle {
type CompletionId = usize;
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug, Default)]
struct EditorActionId(usize);
impl EditorActionId {
pub fn post_inc(&mut self) -> Self {
let answer = self.0;
*self = Self(answer + 1);
Self(answer)
}
}
// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
@@ -512,7 +526,8 @@ pub struct Editor {
gutter_dimensions: GutterDimensions,
pub vim_replace_map: HashMap<Range<usize>, String>,
style: Option<EditorStyle>,
editor_actions: Vec<Box<dyn Fn(&mut ViewContext<Self>)>>,
next_editor_action_id: EditorActionId,
editor_actions: Rc<RefCell<BTreeMap<EditorActionId, Box<dyn Fn(&mut ViewContext<Self>)>>>>,
use_autoclose: bool,
auto_replace_emoji_shortcode: bool,
show_git_blame_gutter: bool,
@@ -1805,7 +1820,8 @@ impl Editor {
style: None,
show_cursor_names: false,
hovered_cursors: Default::default(),
editor_actions: Default::default(),
next_editor_action_id: EditorActionId::default(),
editor_actions: Rc::default(),
vim_replace_map: Default::default(),
show_inline_completions: mode == EditorMode::Full,
custom_context_menu: None,
@@ -6448,29 +6464,9 @@ impl Editor {
return;
}
if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
self.change_selections(None, cx, |s| {
s.select_anchors(selections.to_vec());
});
}
self.request_autoscroll(Autoscroll::fit(), cx);
self.unmark_text(cx);
self.refresh_inline_completion(true, cx);
cx.emit(EditorEvent::Edited);
cx.emit(EditorEvent::TransactionUndone {
transaction_id: tx_id,
});
}
}
pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
if self.read_only(cx) {
return;
}
if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
if let Some((selections, _)) =
self.selection_history.transaction(transaction_id).cloned()
{
self.change_selections(None, cx, |s| {
s.select_anchors(selections.to_vec());
@@ -6479,7 +6475,28 @@ impl Editor {
self.request_autoscroll(Autoscroll::fit(), cx);
self.unmark_text(cx);
self.refresh_inline_completion(true, cx);
cx.emit(EditorEvent::Edited);
cx.emit(EditorEvent::Edited { transaction_id });
cx.emit(EditorEvent::TransactionUndone { transaction_id });
}
}
pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
if self.read_only(cx) {
return;
}
if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
if let Some((_, Some(selections))) =
self.selection_history.transaction(transaction_id).cloned()
{
self.change_selections(None, cx, |s| {
s.select_anchors(selections.to_vec());
});
}
self.request_autoscroll(Autoscroll::fit(), cx);
self.unmark_text(cx);
self.refresh_inline_completion(true, cx);
cx.emit(EditorEvent::Edited { transaction_id });
}
}
@@ -9590,18 +9607,20 @@ impl Editor {
now: Instant,
cx: &mut ViewContext<Self>,
) -> Option<TransactionId> {
if let Some(tx_id) = self
if let Some(transaction_id) = self
.buffer
.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
{
if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
if let Some((_, end_selections)) =
self.selection_history.transaction_mut(transaction_id)
{
*end_selections = Some(self.selections.disjoint_anchors());
} else {
log::error!("unexpectedly ended a transaction that wasn't started by this editor");
}
cx.emit(EditorEvent::Edited);
Some(tx_id)
cx.emit(EditorEvent::Edited { transaction_id });
Some(transaction_id)
} else {
None
}
@@ -11293,21 +11312,28 @@ impl Editor {
pub fn register_action<A: Action>(
&mut self,
listener: impl Fn(&A, &mut WindowContext) + 'static,
) -> &mut Self {
) -> Subscription {
let id = self.next_editor_action_id.post_inc();
let listener = Arc::new(listener);
self.editor_actions.borrow_mut().insert(
id,
Box::new(move |cx| {
let _view = cx.view().clone();
let cx = cx.window_context();
let listener = listener.clone();
cx.on_action(TypeId::of::<A>(), move |action, phase, cx| {
let action = action.downcast_ref().unwrap();
if phase == DispatchPhase::Bubble {
listener(action, cx)
}
})
}),
);
self.editor_actions.push(Box::new(move |cx| {
let _view = cx.view().clone();
let cx = cx.window_context();
let listener = listener.clone();
cx.on_action(TypeId::of::<A>(), move |action, phase, cx| {
let action = action.downcast_ref().unwrap();
if phase == DispatchPhase::Bubble {
listener(action, cx)
}
})
}));
self
let editor_actions = self.editor_actions.clone();
Subscription::new(move || {
editor_actions.borrow_mut().remove(&id);
})
}
pub fn file_header_size(&self) -> u8 {
@@ -11764,7 +11790,9 @@ pub enum EditorEvent {
ids: Vec<ExcerptId>,
},
BufferEdited,
Edited,
Edited {
transaction_id: clock::Lamport,
},
Reparsed,
Focused,
Blurred,