Assign editors as text input handlers
Co-authored-by: Marshall <marshall@zed.dev>
This commit is contained in:
parent
b2ae08b159
commit
bd12e3edb6
3 changed files with 402 additions and 396 deletions
|
@ -37,9 +37,9 @@ use futures::FutureExt;
|
||||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, px, relative, AnyElement, AppContext, BackgroundExecutor, Context,
|
actions, div, px, relative, AnyElement, AppContext, BackgroundExecutor, Context,
|
||||||
DispatchContext, Div, Element, Entity, EventEmitter, FocusHandle, FontStyle, FontWeight, Hsla,
|
DispatchContext, Div, Element, Entity, EventEmitter, FocusHandle, FontStyle, FontWeight,
|
||||||
Model, Pixels, PlatformInputHandler, Render, Styled, Subscription, Task, TextStyle, View,
|
HighlightStyle, Hsla, InputHandler, Model, Pixels, PlatformInputHandler, Render, Styled,
|
||||||
ViewContext, VisualContext, WeakView, WindowContext,
|
Subscription, Task, TextStyle, View, ViewContext, VisualContext, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
use highlight_matching_bracket::refresh_matching_bracket_highlights;
|
use highlight_matching_bracket::refresh_matching_bracket_highlights;
|
||||||
use hover_popover::{hide_hover, HoverState};
|
use hover_popover::{hide_hover, HoverState};
|
||||||
|
@ -56,6 +56,7 @@ use language::{
|
||||||
use link_go_to_definition::{GoToDefinitionLink, InlayHighlight, LinkGoToDefinitionState};
|
use link_go_to_definition::{GoToDefinitionLink, InlayHighlight, LinkGoToDefinitionState};
|
||||||
use lsp::{DiagnosticSeverity, Documentation, LanguageServerId};
|
use lsp::{DiagnosticSeverity, Documentation, LanguageServerId};
|
||||||
use movement::TextLayoutDetails;
|
use movement::TextLayoutDetails;
|
||||||
|
use multi_buffer::ToOffsetUtf16;
|
||||||
pub use multi_buffer::{
|
pub use multi_buffer::{
|
||||||
Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
|
Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
|
||||||
ToPoint,
|
ToPoint,
|
||||||
|
@ -67,7 +68,7 @@ use rpc::proto::*;
|
||||||
use scroll::{
|
use scroll::{
|
||||||
autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
|
autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
|
||||||
};
|
};
|
||||||
use selections_collection::{MutableSelectionsCollection, SelectionsCollection};
|
use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use settings::{Settings, SettingsStore};
|
use settings::{Settings, SettingsStore};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -2769,197 +2770,197 @@ impl Editor {
|
||||||
// cx.propagate();
|
// cx.propagate();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
|
pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
|
||||||
// let text: Arc<str> = text.into();
|
let text: Arc<str> = text.into();
|
||||||
|
|
||||||
// if self.read_only {
|
if self.read_only {
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// let selections = self.selections.all_adjusted(cx);
|
let selections = self.selections.all_adjusted(cx);
|
||||||
// let mut brace_inserted = false;
|
let mut brace_inserted = false;
|
||||||
// let mut edits = Vec::new();
|
let mut edits = Vec::new();
|
||||||
// let mut new_selections = Vec::with_capacity(selections.len());
|
let mut new_selections = Vec::with_capacity(selections.len());
|
||||||
// let mut new_autoclose_regions = Vec::new();
|
let mut new_autoclose_regions = Vec::new();
|
||||||
// let snapshot = self.buffer.read(cx).read(cx);
|
let snapshot = self.buffer.read(cx).read(cx);
|
||||||
|
|
||||||
// for (selection, autoclose_region) in
|
for (selection, autoclose_region) in
|
||||||
// self.selections_with_autoclose_regions(selections, &snapshot)
|
self.selections_with_autoclose_regions(selections, &snapshot)
|
||||||
// {
|
{
|
||||||
// if let Some(scope) = snapshot.language_scope_at(selection.head()) {
|
if let Some(scope) = snapshot.language_scope_at(selection.head()) {
|
||||||
// // Determine if the inserted text matches the opening or closing
|
// Determine if the inserted text matches the opening or closing
|
||||||
// // bracket of any of this language's bracket pairs.
|
// bracket of any of this language's bracket pairs.
|
||||||
// let mut bracket_pair = None;
|
let mut bracket_pair = None;
|
||||||
// let mut is_bracket_pair_start = false;
|
let mut is_bracket_pair_start = false;
|
||||||
// if !text.is_empty() {
|
if !text.is_empty() {
|
||||||
// // `text` can be empty when an user is using IME (e.g. Chinese Wubi Simplified)
|
// `text` can be empty when an user is using IME (e.g. Chinese Wubi Simplified)
|
||||||
// // and they are removing the character that triggered IME popup.
|
// and they are removing the character that triggered IME popup.
|
||||||
// for (pair, enabled) in scope.brackets() {
|
for (pair, enabled) in scope.brackets() {
|
||||||
// if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
|
if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
|
||||||
// bracket_pair = Some(pair.clone());
|
bracket_pair = Some(pair.clone());
|
||||||
// is_bracket_pair_start = true;
|
is_bracket_pair_start = true;
|
||||||
// break;
|
break;
|
||||||
// } else if pair.end.as_str() == text.as_ref() {
|
} else if pair.end.as_str() == text.as_ref() {
|
||||||
// bracket_pair = Some(pair.clone());
|
bracket_pair = Some(pair.clone());
|
||||||
// break;
|
break;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if let Some(bracket_pair) = bracket_pair {
|
if let Some(bracket_pair) = bracket_pair {
|
||||||
// if selection.is_empty() {
|
if selection.is_empty() {
|
||||||
// if is_bracket_pair_start {
|
if is_bracket_pair_start {
|
||||||
// let prefix_len = bracket_pair.start.len() - text.len();
|
let prefix_len = bracket_pair.start.len() - text.len();
|
||||||
|
|
||||||
// // If the inserted text is a suffix of an opening bracket and the
|
// If the inserted text is a suffix of an opening bracket and the
|
||||||
// // selection is preceded by the rest of the opening bracket, then
|
// selection is preceded by the rest of the opening bracket, then
|
||||||
// // insert the closing bracket.
|
// insert the closing bracket.
|
||||||
// let following_text_allows_autoclose = snapshot
|
let following_text_allows_autoclose = snapshot
|
||||||
// .chars_at(selection.start)
|
.chars_at(selection.start)
|
||||||
// .next()
|
.next()
|
||||||
// .map_or(true, |c| scope.should_autoclose_before(c));
|
.map_or(true, |c| scope.should_autoclose_before(c));
|
||||||
// let preceding_text_matches_prefix = prefix_len == 0
|
let preceding_text_matches_prefix = prefix_len == 0
|
||||||
// || (selection.start.column >= (prefix_len as u32)
|
|| (selection.start.column >= (prefix_len as u32)
|
||||||
// && snapshot.contains_str_at(
|
&& snapshot.contains_str_at(
|
||||||
// Point::new(
|
Point::new(
|
||||||
// selection.start.row,
|
selection.start.row,
|
||||||
// selection.start.column - (prefix_len as u32),
|
selection.start.column - (prefix_len as u32),
|
||||||
// ),
|
),
|
||||||
// &bracket_pair.start[..prefix_len],
|
&bracket_pair.start[..prefix_len],
|
||||||
// ));
|
));
|
||||||
// if following_text_allows_autoclose && preceding_text_matches_prefix {
|
if following_text_allows_autoclose && preceding_text_matches_prefix {
|
||||||
// let anchor = snapshot.anchor_before(selection.end);
|
let anchor = snapshot.anchor_before(selection.end);
|
||||||
// new_selections.push((selection.map(|_| anchor), text.len()));
|
new_selections.push((selection.map(|_| anchor), text.len()));
|
||||||
// new_autoclose_regions.push((
|
new_autoclose_regions.push((
|
||||||
// anchor,
|
anchor,
|
||||||
// text.len(),
|
text.len(),
|
||||||
// selection.id,
|
selection.id,
|
||||||
// bracket_pair.clone(),
|
bracket_pair.clone(),
|
||||||
// ));
|
));
|
||||||
// edits.push((
|
edits.push((
|
||||||
// selection.range(),
|
selection.range(),
|
||||||
// format!("{}{}", text, bracket_pair.end).into(),
|
format!("{}{}", text, bracket_pair.end).into(),
|
||||||
// ));
|
));
|
||||||
// brace_inserted = true;
|
brace_inserted = true;
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if let Some(region) = autoclose_region {
|
if let Some(region) = autoclose_region {
|
||||||
// // If the selection is followed by an auto-inserted closing bracket,
|
// If the selection is followed by an auto-inserted closing bracket,
|
||||||
// // then don't insert that closing bracket again; just move the selection
|
// then don't insert that closing bracket again; just move the selection
|
||||||
// // past the closing bracket.
|
// past the closing bracket.
|
||||||
// let should_skip = selection.end == region.range.end.to_point(&snapshot)
|
let should_skip = selection.end == region.range.end.to_point(&snapshot)
|
||||||
// && text.as_ref() == region.pair.end.as_str();
|
&& text.as_ref() == region.pair.end.as_str();
|
||||||
// if should_skip {
|
if should_skip {
|
||||||
// let anchor = snapshot.anchor_after(selection.end);
|
let anchor = snapshot.anchor_after(selection.end);
|
||||||
// new_selections
|
new_selections
|
||||||
// .push((selection.map(|_| anchor), region.pair.end.len()));
|
.push((selection.map(|_| anchor), region.pair.end.len()));
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// // If an opening bracket is 1 character long and is typed while
|
// If an opening bracket is 1 character long and is typed while
|
||||||
// // text is selected, then surround that text with the bracket pair.
|
// text is selected, then surround that text with the bracket pair.
|
||||||
// else if is_bracket_pair_start && bracket_pair.start.chars().count() == 1 {
|
else if is_bracket_pair_start && bracket_pair.start.chars().count() == 1 {
|
||||||
// edits.push((selection.start..selection.start, text.clone()));
|
edits.push((selection.start..selection.start, text.clone()));
|
||||||
// edits.push((
|
edits.push((
|
||||||
// selection.end..selection.end,
|
selection.end..selection.end,
|
||||||
// bracket_pair.end.as_str().into(),
|
bracket_pair.end.as_str().into(),
|
||||||
// ));
|
));
|
||||||
// brace_inserted = true;
|
brace_inserted = true;
|
||||||
// new_selections.push((
|
new_selections.push((
|
||||||
// Selection {
|
Selection {
|
||||||
// id: selection.id,
|
id: selection.id,
|
||||||
// start: snapshot.anchor_after(selection.start),
|
start: snapshot.anchor_after(selection.start),
|
||||||
// end: snapshot.anchor_before(selection.end),
|
end: snapshot.anchor_before(selection.end),
|
||||||
// reversed: selection.reversed,
|
reversed: selection.reversed,
|
||||||
// goal: selection.goal,
|
goal: selection.goal,
|
||||||
// },
|
},
|
||||||
// 0,
|
0,
|
||||||
// ));
|
));
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // If not handling any auto-close operation, then just replace the selected
|
// If not handling any auto-close operation, then just replace the selected
|
||||||
// // text with the given input and move the selection to the end of the
|
// text with the given input and move the selection to the end of the
|
||||||
// // newly inserted text.
|
// newly inserted text.
|
||||||
// let anchor = snapshot.anchor_after(selection.end);
|
let anchor = snapshot.anchor_after(selection.end);
|
||||||
// new_selections.push((selection.map(|_| anchor), 0));
|
new_selections.push((selection.map(|_| anchor), 0));
|
||||||
// edits.push((selection.start..selection.end, text.clone()));
|
edits.push((selection.start..selection.end, text.clone()));
|
||||||
// }
|
}
|
||||||
|
|
||||||
// drop(snapshot);
|
drop(snapshot);
|
||||||
// self.transact(cx, |this, cx| {
|
self.transact(cx, |this, cx| {
|
||||||
// this.buffer.update(cx, |buffer, cx| {
|
this.buffer.update(cx, |buffer, cx| {
|
||||||
// buffer.edit(edits, this.autoindent_mode.clone(), cx);
|
buffer.edit(edits, this.autoindent_mode.clone(), cx);
|
||||||
// });
|
});
|
||||||
|
|
||||||
// let new_anchor_selections = new_selections.iter().map(|e| &e.0);
|
let new_anchor_selections = new_selections.iter().map(|e| &e.0);
|
||||||
// let new_selection_deltas = new_selections.iter().map(|e| e.1);
|
let new_selection_deltas = new_selections.iter().map(|e| e.1);
|
||||||
// let snapshot = this.buffer.read(cx).read(cx);
|
let snapshot = this.buffer.read(cx).read(cx);
|
||||||
// let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
|
let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
|
||||||
// .zip(new_selection_deltas)
|
.zip(new_selection_deltas)
|
||||||
// .map(|(selection, delta)| Selection {
|
.map(|(selection, delta)| Selection {
|
||||||
// id: selection.id,
|
id: selection.id,
|
||||||
// start: selection.start + delta,
|
start: selection.start + delta,
|
||||||
// end: selection.end + delta,
|
end: selection.end + delta,
|
||||||
// reversed: selection.reversed,
|
reversed: selection.reversed,
|
||||||
// goal: SelectionGoal::None,
|
goal: SelectionGoal::None,
|
||||||
// })
|
})
|
||||||
// .collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// let mut i = 0;
|
let mut i = 0;
|
||||||
// for (position, delta, selection_id, pair) in new_autoclose_regions {
|
for (position, delta, selection_id, pair) in new_autoclose_regions {
|
||||||
// let position = position.to_offset(&snapshot) + delta;
|
let position = position.to_offset(&snapshot) + delta;
|
||||||
// let start = snapshot.anchor_before(position);
|
let start = snapshot.anchor_before(position);
|
||||||
// let end = snapshot.anchor_after(position);
|
let end = snapshot.anchor_after(position);
|
||||||
// while let Some(existing_state) = this.autoclose_regions.get(i) {
|
while let Some(existing_state) = this.autoclose_regions.get(i) {
|
||||||
// match existing_state.range.start.cmp(&start, &snapshot) {
|
match existing_state.range.start.cmp(&start, &snapshot) {
|
||||||
// Ordering::Less => i += 1,
|
Ordering::Less => i += 1,
|
||||||
// Ordering::Greater => break,
|
Ordering::Greater => break,
|
||||||
// Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
|
Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
|
||||||
// Ordering::Less => i += 1,
|
Ordering::Less => i += 1,
|
||||||
// Ordering::Equal => break,
|
Ordering::Equal => break,
|
||||||
// Ordering::Greater => break,
|
Ordering::Greater => break,
|
||||||
// },
|
},
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// this.autoclose_regions.insert(
|
this.autoclose_regions.insert(
|
||||||
// i,
|
i,
|
||||||
// AutocloseRegion {
|
AutocloseRegion {
|
||||||
// selection_id,
|
selection_id,
|
||||||
// range: start..end,
|
range: start..end,
|
||||||
// pair,
|
pair,
|
||||||
// },
|
},
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// drop(snapshot);
|
drop(snapshot);
|
||||||
// let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx);
|
let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx);
|
||||||
// this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
|
this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
|
||||||
|
|
||||||
// if !brace_inserted && EditorSettings>(cx).use_on_type_format {
|
if !brace_inserted && EditorSettings::get_global(cx).use_on_type_format {
|
||||||
// if let Some(on_type_format_task) =
|
if let Some(on_type_format_task) =
|
||||||
// this.trigger_on_type_formatting(text.to_string(), cx)
|
this.trigger_on_type_formatting(text.to_string(), cx)
|
||||||
// {
|
{
|
||||||
// on_type_format_task.detach_and_log_err(cx);
|
on_type_format_task.detach_and_log_err(cx);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if had_active_copilot_suggestion {
|
if had_active_copilot_suggestion {
|
||||||
// this.refresh_copilot_suggestions(true, cx);
|
this.refresh_copilot_suggestions(true, cx);
|
||||||
// if !this.has_active_copilot_suggestion(cx) {
|
if !this.has_active_copilot_suggestion(cx) {
|
||||||
// this.trigger_completion_on_input(&text, cx);
|
this.trigger_completion_on_input(&text, cx);
|
||||||
// }
|
}
|
||||||
// } else {
|
} else {
|
||||||
// this.trigger_completion_on_input(&text, cx);
|
this.trigger_completion_on_input(&text, cx);
|
||||||
// this.refresh_copilot_suggestions(true, cx);
|
this.refresh_copilot_suggestions(true, cx);
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
|
|
||||||
// pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
|
// pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
|
||||||
// self.transact(cx, |this, cx| {
|
// self.transact(cx, |this, cx| {
|
||||||
|
@ -3259,22 +3260,22 @@ impl Editor {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
|
fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
|
||||||
// if !EditorSettings>(cx).show_completions_on_input {
|
if !EditorSettings::get_global(cx).show_completions_on_input {
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// let selection = self.selections.newest_anchor();
|
let selection = self.selections.newest_anchor();
|
||||||
// if self
|
if self
|
||||||
// .buffer
|
.buffer
|
||||||
// .read(cx)
|
.read(cx)
|
||||||
// .is_completion_trigger(selection.head(), text, cx)
|
.is_completion_trigger(selection.head(), text, cx)
|
||||||
// {
|
{
|
||||||
// self.show_completions(&ShowCompletions, cx);
|
self.show_completions(&ShowCompletions, cx);
|
||||||
// } else {
|
} else {
|
||||||
// self.hide_context_menu(cx);
|
self.hide_context_menu(cx);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// /// If any empty selections is touching the start of its innermost containing autoclose
|
// /// If any empty selections is touching the start of its innermost containing autoclose
|
||||||
// /// region, expand it to select the brackets.
|
// /// region, expand it to select the brackets.
|
||||||
|
@ -3305,37 +3306,37 @@ impl Editor {
|
||||||
// self.change_selections(None, cx, |selections| selections.select(new_selections));
|
// self.change_selections(None, cx, |selections| selections.select(new_selections));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// /// Iterate the given selections, and for each one, find the smallest surrounding
|
/// Iterate the given selections, and for each one, find the smallest surrounding
|
||||||
// /// autoclose region. This uses the ordering of the selections and the autoclose
|
/// autoclose region. This uses the ordering of the selections and the autoclose
|
||||||
// /// regions to avoid repeated comparisons.
|
/// regions to avoid repeated comparisons.
|
||||||
// fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
|
fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
|
||||||
// &'a self,
|
&'a self,
|
||||||
// selections: impl IntoIterator<Item = Selection<D>>,
|
selections: impl IntoIterator<Item = Selection<D>>,
|
||||||
// buffer: &'a MultiBufferSnapshot,
|
buffer: &'a MultiBufferSnapshot,
|
||||||
// ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
|
) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
|
||||||
// let mut i = 0;
|
let mut i = 0;
|
||||||
// let mut regions = self.autoclose_regions.as_slice();
|
let mut regions = self.autoclose_regions.as_slice();
|
||||||
// selections.into_iter().map(move |selection| {
|
selections.into_iter().map(move |selection| {
|
||||||
// let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
|
let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
|
||||||
|
|
||||||
// let mut enclosing = None;
|
let mut enclosing = None;
|
||||||
// while let Some(pair_state) = regions.get(i) {
|
while let Some(pair_state) = regions.get(i) {
|
||||||
// if pair_state.range.end.to_offset(buffer) < range.start {
|
if pair_state.range.end.to_offset(buffer) < range.start {
|
||||||
// regions = ®ions[i + 1..];
|
regions = ®ions[i + 1..];
|
||||||
// i = 0;
|
i = 0;
|
||||||
// } else if pair_state.range.start.to_offset(buffer) > range.end {
|
} else if pair_state.range.start.to_offset(buffer) > range.end {
|
||||||
// break;
|
break;
|
||||||
// } else {
|
} else {
|
||||||
// if pair_state.selection_id == selection.id {
|
if pair_state.selection_id == selection.id {
|
||||||
// enclosing = Some(pair_state);
|
enclosing = Some(pair_state);
|
||||||
// }
|
}
|
||||||
// i += 1;
|
i += 1;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// (selection.clone(), enclosing)
|
(selection.clone(), enclosing)
|
||||||
// })
|
})
|
||||||
// }
|
}
|
||||||
|
|
||||||
/// Remove any autoclose regions that no longer contain their selection.
|
/// Remove any autoclose regions that no longer contain their selection.
|
||||||
fn invalidate_autoclose_regions(
|
fn invalidate_autoclose_regions(
|
||||||
|
@ -3537,51 +3538,51 @@ impl Editor {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn trigger_on_type_formatting(
|
fn trigger_on_type_formatting(
|
||||||
// &self,
|
&self,
|
||||||
// input: String,
|
input: String,
|
||||||
// cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
// ) -> Option<Task<Result<()>>> {
|
) -> Option<Task<Result<()>>> {
|
||||||
// if input.len() != 1 {
|
if input.len() != 1 {
|
||||||
// return None;
|
return None;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// let project = self.project.as_ref()?;
|
let project = self.project.as_ref()?;
|
||||||
// let position = self.selections.newest_anchor().head();
|
let position = self.selections.newest_anchor().head();
|
||||||
// let (buffer, buffer_position) = self
|
let (buffer, buffer_position) = self
|
||||||
// .buffer
|
.buffer
|
||||||
// .read(cx)
|
.read(cx)
|
||||||
// .text_anchor_for_position(position.clone(), cx)?;
|
.text_anchor_for_position(position.clone(), cx)?;
|
||||||
|
|
||||||
// // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
|
// OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
|
||||||
// // hence we do LSP request & edit on host side only — add formats to host's history.
|
// hence we do LSP request & edit on host side only — add formats to host's history.
|
||||||
// let push_to_lsp_host_history = true;
|
let push_to_lsp_host_history = true;
|
||||||
// // If this is not the host, append its history with new edits.
|
// If this is not the host, append its history with new edits.
|
||||||
// let push_to_client_history = project.read(cx).is_remote();
|
let push_to_client_history = project.read(cx).is_remote();
|
||||||
|
|
||||||
// let on_type_formatting = project.update(cx, |project, cx| {
|
let on_type_formatting = project.update(cx, |project, cx| {
|
||||||
// project.on_type_format(
|
project.on_type_format(
|
||||||
// buffer.clone(),
|
buffer.clone(),
|
||||||
// buffer_position,
|
buffer_position,
|
||||||
// input,
|
input,
|
||||||
// push_to_lsp_host_history,
|
push_to_lsp_host_history,
|
||||||
// cx,
|
cx,
|
||||||
// )
|
)
|
||||||
// });
|
});
|
||||||
// Some(cx.spawn(|editor, mut cx| async move {
|
Some(cx.spawn(|editor, mut cx| async move {
|
||||||
// if let Some(transaction) = on_type_formatting.await? {
|
if let Some(transaction) = on_type_formatting.await? {
|
||||||
// if push_to_client_history {
|
if push_to_client_history {
|
||||||
// buffer.update(&mut cx, |buffer, _| {
|
buffer.update(&mut cx, |buffer, _| {
|
||||||
// buffer.push_transaction(transaction, Instant::now());
|
buffer.push_transaction(transaction, Instant::now());
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
// editor.update(&mut cx, |editor, cx| {
|
editor.update(&mut cx, |editor, cx| {
|
||||||
// editor.refresh_document_highlights(cx);
|
editor.refresh_document_highlights(cx);
|
||||||
// })?;
|
})?;
|
||||||
// }
|
}
|
||||||
// Ok(())
|
Ok(())
|
||||||
// }))
|
}))
|
||||||
// }
|
}
|
||||||
|
|
||||||
fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
|
fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
|
||||||
if self.pending_rename.is_some() {
|
if self.pending_rename.is_some() {
|
||||||
|
@ -8712,12 +8713,12 @@ impl Editor {
|
||||||
// cx.notify();
|
// cx.notify();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// pub fn text_highlights<'a, T: 'static>(
|
pub fn text_highlights<'a, T: 'static>(
|
||||||
// &'a self,
|
&'a self,
|
||||||
// cx: &'a AppContext,
|
cx: &'a AppContext,
|
||||||
// ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
|
) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
|
||||||
// self.display_map.read(cx).text_highlights(TypeId::of::<T>())
|
self.display_map.read(cx).text_highlights(TypeId::of::<T>())
|
||||||
// }
|
}
|
||||||
|
|
||||||
pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
|
pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
let cleared = self
|
let cleared = self
|
||||||
|
@ -8934,43 +8935,43 @@ impl Editor {
|
||||||
// .detach_and_log_err(cx);
|
// .detach_and_log_err(cx);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
|
fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
|
||||||
// let snapshot = self.buffer.read(cx).read(cx);
|
let snapshot = self.buffer.read(cx).read(cx);
|
||||||
// let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
|
let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
|
||||||
// Some(
|
Some(
|
||||||
// ranges
|
ranges
|
||||||
// .iter()
|
.iter()
|
||||||
// .map(move |range| {
|
.map(move |range| {
|
||||||
// range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
|
range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
|
||||||
// })
|
})
|
||||||
// .collect(),
|
.collect(),
|
||||||
// )
|
)
|
||||||
// }
|
}
|
||||||
|
|
||||||
// fn selection_replacement_ranges(
|
fn selection_replacement_ranges(
|
||||||
// &self,
|
&self,
|
||||||
// range: Range<OffsetUtf16>,
|
range: Range<OffsetUtf16>,
|
||||||
// cx: &AppContext,
|
cx: &AppContext,
|
||||||
// ) -> Vec<Range<OffsetUtf16>> {
|
) -> Vec<Range<OffsetUtf16>> {
|
||||||
// let selections = self.selections.all::<OffsetUtf16>(cx);
|
let selections = self.selections.all::<OffsetUtf16>(cx);
|
||||||
// let newest_selection = selections
|
let newest_selection = selections
|
||||||
// .iter()
|
.iter()
|
||||||
// .max_by_key(|selection| selection.id)
|
.max_by_key(|selection| selection.id)
|
||||||
// .unwrap();
|
.unwrap();
|
||||||
// let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
|
let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
|
||||||
// let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
|
let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
|
||||||
// let snapshot = self.buffer.read(cx).read(cx);
|
let snapshot = self.buffer.read(cx).read(cx);
|
||||||
// selections
|
selections
|
||||||
// .into_iter()
|
.into_iter()
|
||||||
// .map(|mut selection| {
|
.map(|mut selection| {
|
||||||
// selection.start.0 =
|
selection.start.0 =
|
||||||
// (selection.start.0 as isize).saturating_add(start_delta) as usize;
|
(selection.start.0 as isize).saturating_add(start_delta) as usize;
|
||||||
// selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
|
selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
|
||||||
// snapshot.clip_offset_utf16(selection.start, Bias::Left)
|
snapshot.clip_offset_utf16(selection.start, Bias::Left)
|
||||||
// ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
|
..snapshot.clip_offset_utf16(selection.end, Bias::Right)
|
||||||
// })
|
})
|
||||||
// .collect()
|
.collect()
|
||||||
// }
|
}
|
||||||
|
|
||||||
fn report_copilot_event(
|
fn report_copilot_event(
|
||||||
&self,
|
&self,
|
||||||
|
@ -9486,102 +9487,101 @@ impl Render for Editor {
|
||||||
// false
|
// false
|
||||||
// }
|
// }
|
||||||
|
|
||||||
impl PlatformInputHandler for Editor {
|
impl InputHandler for Editor {
|
||||||
fn text_for_range(&self, range_utf16: Range<usize>) -> Option<String> {
|
fn text_for_range(
|
||||||
// Some(
|
&self,
|
||||||
// self.buffer
|
range_utf16: Range<usize>,
|
||||||
// .read(cx)
|
cx: &mut ViewContext<Self>,
|
||||||
// .read(cx)
|
) -> Option<String> {
|
||||||
// .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
|
Some(
|
||||||
// .collect(),
|
self.buffer
|
||||||
// )
|
.read(cx)
|
||||||
todo!()
|
.read(cx)
|
||||||
|
.text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn selected_text_range(&self) -> Option<Range<usize>> {
|
fn selected_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
|
||||||
// Prevent the IME menu from appearing when holding down an alphabetic key
|
// Prevent the IME menu from appearing when holding down an alphabetic key
|
||||||
// while input is disabled.
|
// while input is disabled.
|
||||||
// if !self.input_enabled {
|
if !self.input_enabled {
|
||||||
// return None;
|
return None;
|
||||||
// }
|
|
||||||
|
|
||||||
// let range = self.selections.newest::<OffsetUtf16>(cx).range();
|
|
||||||
// Some(range.start.0..range.end.0)
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
|
let range = self.selections.newest::<OffsetUtf16>(cx).range();
|
||||||
// let snapshot = self.buffer.read(cx).read(cx);
|
Some(range.start.0..range.end.0)
|
||||||
// let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
|
}
|
||||||
// Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
|
|
||||||
todo!()
|
fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
|
||||||
|
let snapshot = self.buffer.read(cx).read(cx);
|
||||||
|
let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
|
||||||
|
Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
|
fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
// self.clear_highlights::<InputComposition>(cx);
|
self.clear_highlights::<InputComposition>(cx);
|
||||||
// self.ime_transaction.take();
|
self.ime_transaction.take();
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace_text_in_range(
|
fn replace_text_in_range(
|
||||||
&mut self,
|
&mut self,
|
||||||
//range_utf16: Option<Range<usize>>,
|
range_utf16: Option<Range<usize>>,
|
||||||
// text: &str,
|
text: &str,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
// if !self.input_enabled {
|
if !self.input_enabled {
|
||||||
// cx.emit(Event::InputIgnored { text: text.into() });
|
cx.emit(Event::InputIgnored { text: text.into() });
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// self.transact(cx, |this, cx| {
|
self.transact(cx, |this, cx| {
|
||||||
// let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
|
let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
|
||||||
// let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
|
let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
|
||||||
// Some(this.selection_replacement_ranges(range_utf16, cx))
|
Some(this.selection_replacement_ranges(range_utf16, cx))
|
||||||
// } else {
|
} else {
|
||||||
// this.marked_text_ranges(cx)
|
this.marked_text_ranges(cx)
|
||||||
// };
|
};
|
||||||
|
|
||||||
// let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
|
let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
|
||||||
// let newest_selection_id = this.selections.newest_anchor().id;
|
let newest_selection_id = this.selections.newest_anchor().id;
|
||||||
// this.selections
|
this.selections
|
||||||
// .all::<OffsetUtf16>(cx)
|
.all::<OffsetUtf16>(cx)
|
||||||
// .iter()
|
.iter()
|
||||||
// .zip(ranges_to_replace.iter())
|
.zip(ranges_to_replace.iter())
|
||||||
// .find_map(|(selection, range)| {
|
.find_map(|(selection, range)| {
|
||||||
// if selection.id == newest_selection_id {
|
if selection.id == newest_selection_id {
|
||||||
// Some(
|
Some(
|
||||||
// (range.start.0 as isize - selection.head().0 as isize)
|
(range.start.0 as isize - selection.head().0 as isize)
|
||||||
// ..(range.end.0 as isize - selection.head().0 as isize),
|
..(range.end.0 as isize - selection.head().0 as isize),
|
||||||
// )
|
)
|
||||||
// } else {
|
} else {
|
||||||
// None
|
None
|
||||||
// }
|
}
|
||||||
// })
|
})
|
||||||
// });
|
});
|
||||||
|
|
||||||
// cx.emit(Event::InputHandled {
|
cx.emit(Event::InputHandled {
|
||||||
// utf16_range_to_replace: range_to_replace,
|
utf16_range_to_replace: range_to_replace,
|
||||||
// text: text.into(),
|
text: text.into(),
|
||||||
// });
|
});
|
||||||
|
|
||||||
// if let Some(new_selected_ranges) = new_selected_ranges {
|
if let Some(new_selected_ranges) = new_selected_ranges {
|
||||||
// this.change_selections(None, cx, |selections| {
|
this.change_selections(None, cx, |selections| {
|
||||||
// selections.select_ranges(new_selected_ranges)
|
selections.select_ranges(new_selected_ranges)
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
|
|
||||||
// this.handle_input(text, cx);
|
this.handle_input(text, cx);
|
||||||
// });
|
});
|
||||||
|
|
||||||
// if let Some(transaction) = self.ime_transaction {
|
if let Some(transaction) = self.ime_transaction {
|
||||||
// self.buffer.update(cx, |buffer, cx| {
|
self.buffer.update(cx, |buffer, cx| {
|
||||||
// buffer.group_until_transaction(transaction, cx);
|
buffer.group_until_transaction(transaction, cx);
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
|
|
||||||
// self.unmark_text(cx);
|
self.unmark_text(cx);
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace_and_mark_text_in_range(
|
fn replace_and_mark_text_in_range(
|
||||||
|
@ -9700,7 +9700,11 @@ impl PlatformInputHandler for Editor {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounds_for_range(&self, range_utf16: Range<usize>) -> Option<gpui::Bounds<f32>> {
|
fn bounds_for_range(
|
||||||
|
&self,
|
||||||
|
range_utf16: Range<usize>,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> Option<gpui::Bounds<f32>> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2624,7 +2624,7 @@ impl Element<Editor> for EditorElement {
|
||||||
});
|
});
|
||||||
|
|
||||||
if editor.focus_handle.is_focused(cx) {
|
if editor.focus_handle.is_focused(cx) {
|
||||||
cx.set_input_handler(editor.handle);
|
cx.handle_text_input();
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.with_content_mask(ContentMask { bounds }, |cx| {
|
cx.with_content_mask(ContentMask { bounds }, |cx| {
|
||||||
|
|
|
@ -679,17 +679,6 @@ impl<'a> WindowContext<'a> {
|
||||||
self.window.requested_cursor_style = Some(style)
|
self.window.requested_cursor_style = Some(style)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_input_handler<V>(&mut self, handler: WeakView<V>, cx: ViewContext<V>)
|
|
||||||
where
|
|
||||||
V: InputHandler + 'static,
|
|
||||||
{
|
|
||||||
self.window.requested_input_handler = Some(Box::new(WindowInputHandler {
|
|
||||||
cx: cx.app.this.clone(),
|
|
||||||
window: cx.window_handle(),
|
|
||||||
handler,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Called during painting to invoke the given closure in a new stacking context. The given
|
/// Called during painting to invoke the given closure in a new stacking context. The given
|
||||||
/// z-index is interpreted relative to the previous call to `stack`.
|
/// z-index is interpreted relative to the previous call to `stack`.
|
||||||
pub fn stack<R>(&mut self, z_index: u32, f: impl FnOnce(&mut Self) -> R) -> R {
|
pub fn stack<R>(&mut self, z_index: u32, f: impl FnOnce(&mut Self) -> R) -> R {
|
||||||
|
@ -2009,6 +1998,19 @@ impl<'a, V: 'static> ViewContext<'a, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V> ViewContext<'_, V>
|
||||||
|
where
|
||||||
|
V: InputHandler + 'static,
|
||||||
|
{
|
||||||
|
pub fn handle_text_input(&mut self) {
|
||||||
|
self.window.requested_input_handler = Some(Box::new(WindowInputHandler {
|
||||||
|
cx: self.app.this.clone(),
|
||||||
|
window: self.window_handle(),
|
||||||
|
handler: self.view().downgrade(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<V> ViewContext<'_, V>
|
impl<V> ViewContext<'_, V>
|
||||||
where
|
where
|
||||||
V: EventEmitter,
|
V: EventEmitter,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue