Assign editors as text input handlers

Co-authored-by: Marshall <marshall@zed.dev>
This commit is contained in:
Max Brunsfeld 2023-11-07 15:44:00 -08:00
parent b2ae08b159
commit bd12e3edb6
3 changed files with 402 additions and 396 deletions

View file

@ -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 = &regions[i + 1..]; regions = &regions[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(); let range = self.selections.newest::<OffsetUtf16>(cx).range();
// Some(range.start.0..range.end.0) Some(range.start.0..range.end.0)
todo!()
} }
fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> { fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
// let snapshot = self.buffer.read(cx).read(cx); let snapshot = self.buffer.read(cx).read(cx);
// let range = self.text_highlights::<InputComposition>(cx)?.1.get(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) Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
todo!()
} }
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!()
} }
} }

View file

@ -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| {

View file

@ -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,