Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Truncate line when accepting inline suggestions for Supermaven #13884

Merged
merged 9 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions crates/copilot/src/copilot_completion_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use language::{
Buffer, OffsetRangeExt, ToOffset,
};
use settings::Settings;
use std::{path::Path, sync::Arc, time::Duration};
use std::{ops::Range, path::Path, sync::Arc, time::Duration};

pub const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);

Expand Down Expand Up @@ -239,7 +239,7 @@ impl InlineCompletionProvider for CopilotCompletionProvider {
buffer: &Model<Buffer>,
cursor_position: language::Anchor,
cx: &'a AppContext,
) -> Option<&'a str> {
) -> Option<(&'a str, Option<Range<language::Anchor>>)> {
let buffer_id = buffer.entity_id();
let buffer = buffer.read(cx);
let completion = self.active_completion()?;
Expand Down Expand Up @@ -269,7 +269,7 @@ impl InlineCompletionProvider for CopilotCompletionProvider {
if completion_text.trim().is_empty() {
None
} else {
Some(completion_text)
Some((completion_text, None))
}
} else {
None
Expand Down
44 changes: 34 additions & 10 deletions crates/editor/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ pub struct Editor {
gutter_hovered: bool,
hovered_link_state: Option<HoveredLinkState>,
inline_completion_provider: Option<RegisteredInlineCompletionProvider>,
active_inline_completion: Option<Inlay>,
active_inline_completion: Option<(Inlay, Option<Range<Anchor>>)>,
show_inline_completions: bool,
inlay_hint_cache: InlayHintCache,
expanded_hunks: ExpandedHunks,
Expand Down Expand Up @@ -4953,7 +4953,7 @@ impl Editor {
_: &AcceptInlineCompletion,
cx: &mut ViewContext<Self>,
) {
let Some(completion) = self.take_active_inline_completion(cx) else {
let Some((completion, delete_range)) = self.take_active_inline_completion(cx) else {
return;
};
if let Some(provider) = self.inline_completion_provider() {
Expand All @@ -4964,6 +4964,10 @@ impl Editor {
utf16_range_to_replace: None,
text: completion.text.to_string().into(),
});

if let Some(range) = delete_range {
self.change_selections(None, cx, |s| s.select_ranges([range]))
}
self.insert_with_autoindent_mode(&completion.text.to_string(), None, cx);
self.refresh_inline_completion(true, cx);
cx.notify();
Expand All @@ -4975,7 +4979,7 @@ impl Editor {
cx: &mut ViewContext<Self>,
) {
if self.selections.count() == 1 && self.has_active_inline_completion(cx) {
if let Some(completion) = self.take_active_inline_completion(cx) {
if let Some((completion, delete_range)) = self.take_active_inline_completion(cx) {
let mut partial_completion = completion
.text
.chars()
Expand All @@ -4995,7 +4999,12 @@ impl Editor {
utf16_range_to_replace: None,
text: partial_completion.clone().into(),
});

if let Some(range) = delete_range {
self.change_selections(None, cx, |s| s.select_ranges([range]))
}
self.insert_with_autoindent_mode(&partial_completion, None, cx);

self.refresh_inline_completion(true, cx);
cx.notify();
}
Expand All @@ -5017,20 +5026,23 @@ impl Editor {
pub fn has_active_inline_completion(&self, cx: &AppContext) -> bool {
if let Some(completion) = self.active_inline_completion.as_ref() {
let buffer = self.buffer.read(cx).read(cx);
completion.position.is_valid(&buffer)
completion.0.position.is_valid(&buffer)
} else {
false
}
}

fn take_active_inline_completion(&mut self, cx: &mut ViewContext<Self>) -> Option<Inlay> {
fn take_active_inline_completion(
&mut self,
cx: &mut ViewContext<Self>,
) -> Option<(Inlay, Option<Range<Anchor>>)> {
let completion = self.active_inline_completion.take()?;
self.display_map.update(cx, |map, cx| {
map.splice_inlays(vec![completion.id], Default::default(), cx);
map.splice_inlays(vec![completion.0.id], Default::default(), cx);
});
let buffer = self.buffer.read(cx).read(cx);

if completion.position.is_valid(&buffer) {
if completion.0.position.is_valid(&buffer) {
Some(completion)
} else {
None
Expand All @@ -5041,6 +5053,8 @@ impl Editor {
let selection = self.selections.newest_anchor();
let cursor = selection.head();

let excerpt_id = cursor.excerpt_id;

if self.context_menu.read().is_none()
&& self.completion_tasks.is_empty()
&& selection.start == selection.end
Expand All @@ -5049,18 +5063,28 @@ impl Editor {
if let Some((buffer, cursor_buffer_position)) =
self.buffer.read(cx).text_anchor_for_position(cursor, cx)
{
if let Some(text) =
if let Some((text, text_anchor_range)) =
provider.active_completion_text(&buffer, cursor_buffer_position, cx)
{
let text = Rope::from(text);
let mut to_remove = Vec::new();
if let Some(completion) = self.active_inline_completion.take() {
to_remove.push(completion.id);
to_remove.push(completion.0.id);
}

let completion_inlay =
Inlay::suggestion(post_inc(&mut self.next_inlay_id), cursor, text);
self.active_inline_completion = Some(completion_inlay.clone());

let multibuffer_anchor_range = text_anchor_range.and_then(|range| {
let snapshot = self.buffer.read(cx).snapshot(cx);
Some(
snapshot.anchor_in_excerpt(excerpt_id, range.start)?
..snapshot.anchor_in_excerpt(excerpt_id, range.end)?,
)
});
self.active_inline_completion =
Some((completion_inlay.clone(), multibuffer_anchor_range));

self.display_map.update(cx, move |map, cx| {
map.splice_inlays(to_remove, vec![completion_inlay], cx)
});
Expand Down
7 changes: 4 additions & 3 deletions crates/editor/src/inline_completion_provider.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::Direction;
use gpui::{AppContext, Model, ModelContext};
use language::Buffer;
use std::ops::Range;

pub trait InlineCompletionProvider: 'static + Sized {
fn name() -> &'static str;
Expand Down Expand Up @@ -31,7 +32,7 @@ pub trait InlineCompletionProvider: 'static + Sized {
buffer: &Model<Buffer>,
cursor_position: language::Anchor,
cx: &'a AppContext,
) -> Option<&'a str>;
) -> Option<(&'a str, Option<Range<language::Anchor>>)>;
}

pub trait InlineCompletionProviderHandle {
Expand Down Expand Up @@ -62,7 +63,7 @@ pub trait InlineCompletionProviderHandle {
buffer: &Model<Buffer>,
cursor_position: language::Anchor,
cx: &'a AppContext,
) -> Option<&'a str>;
) -> Option<(&'a str, Option<Range<language::Anchor>>)>;
}

impl<T> InlineCompletionProviderHandle for Model<T>
Expand Down Expand Up @@ -117,7 +118,7 @@ where
buffer: &Model<Buffer>,
cursor_position: language::Anchor,
cx: &'a AppContext,
) -> Option<&'a str> {
) -> Option<(&'a str, Option<Range<language::Anchor>>)> {
self.read(cx)
.active_completion_text(buffer, cursor_position, cx)
}
Expand Down
1 change: 1 addition & 0 deletions crates/supermaven/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ serde_json.workspace = true
settings.workspace = true
supermaven_api.workspace = true
smol.workspace = true
text.workspace = true
ui.workspace = true
util.workspace = true

Expand Down
11 changes: 8 additions & 3 deletions crates/supermaven/src/supermaven_completion_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use editor::{Direction, InlineCompletionProvider};
use futures::StreamExt as _;
use gpui::{AppContext, EntityId, Model, ModelContext, Task};
use language::{language_settings::all_language_settings, Anchor, Buffer};
use std::{path::Path, sync::Arc, time::Duration};
use std::{ops::Range, path::Path, sync::Arc, time::Duration};
use text::ToPoint;

pub const DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);

Expand Down Expand Up @@ -139,7 +140,7 @@ impl InlineCompletionProvider for SupermavenCompletionProvider {
buffer: &Model<Buffer>,
cursor_position: Anchor,
cx: &'a AppContext,
) -> Option<&'a str> {
) -> Option<(&'a str, Option<Range<Anchor>>)> {
let completion_text = self
.supermaven
.read(cx)
Expand All @@ -150,7 +151,11 @@ impl InlineCompletionProvider for SupermavenCompletionProvider {
let completion_text = completion_text.trim_end();

if !completion_text.trim().is_empty() {
Some(completion_text)
let snapshot = buffer.read(cx).snapshot();
let mut point = cursor_position.to_point(&snapshot);
point.column = snapshot.line_len(point.row);
let range = cursor_position..snapshot.anchor_after(point);
Some((completion_text, Some(range)))
} else {
None
}
Expand Down
Loading