Detailed changes
@@ -15,7 +15,8 @@ use language::{Buffer, CodeLabel, HighlightId};
use lsp::CompletionContext;
use project::lsp_store::CompletionDocumentation;
use project::{
- Completion, CompletionIntent, CompletionResponse, Project, ProjectPath, Symbol, WorktreeId,
+ Completion, CompletionDisplayOptions, CompletionIntent, CompletionResponse, Project,
+ ProjectPath, Symbol, WorktreeId,
};
use prompt_store::PromptStore;
use rope::Point;
@@ -771,6 +772,7 @@ impl CompletionProvider for ContextPickerCompletionProvider {
Ok(vec![CompletionResponse {
completions,
+ display_options: CompletionDisplayOptions::default(),
// Since this does its own filtering (see `filter_completions()` returns false),
// there is no benefit to computing whether this set of completions is incomplete.
is_incomplete: true,
@@ -862,6 +864,7 @@ impl CompletionProvider for ContextPickerCompletionProvider {
Ok(vec![CompletionResponse {
completions,
+ display_options: CompletionDisplayOptions::default(),
// Since this does its own filtering (see `filter_completions()` returns false),
// there is no benefit to computing whether this set of completions is incomplete.
is_incomplete: true,
@@ -13,7 +13,10 @@ use http_client::HttpClientWithUrl;
use itertools::Itertools;
use language::{Buffer, CodeLabel, HighlightId};
use lsp::CompletionContext;
-use project::{Completion, CompletionIntent, CompletionResponse, ProjectPath, Symbol, WorktreeId};
+use project::{
+ Completion, CompletionDisplayOptions, CompletionIntent, CompletionResponse, ProjectPath,
+ Symbol, WorktreeId,
+};
use prompt_store::PromptStore;
use rope::Point;
use text::{Anchor, OffsetRangeExt, ToPoint};
@@ -897,6 +900,7 @@ impl CompletionProvider for ContextPickerCompletionProvider {
Ok(vec![CompletionResponse {
completions,
+ display_options: CompletionDisplayOptions::default(),
// Since this does its own filtering (see `filter_completions()` returns false),
// there is no benefit to computing whether this set of completions is incomplete.
is_incomplete: true,
@@ -7,7 +7,10 @@ use fuzzy::{StringMatchCandidate, match_strings};
use gpui::{App, AppContext as _, Context, Entity, Task, WeakEntity, Window};
use language::{Anchor, Buffer, ToPoint};
use parking_lot::Mutex;
-use project::{CompletionIntent, CompletionSource, lsp_store::CompletionDocumentation};
+use project::{
+ CompletionDisplayOptions, CompletionIntent, CompletionSource,
+ lsp_store::CompletionDocumentation,
+};
use rope::Point;
use std::{
ops::Range,
@@ -133,6 +136,7 @@ impl SlashCommandCompletionProvider {
vec![project::CompletionResponse {
completions,
+ display_options: CompletionDisplayOptions::default(),
is_incomplete: false,
}]
})
@@ -237,6 +241,7 @@ impl SlashCommandCompletionProvider {
Ok(vec![project::CompletionResponse {
completions,
+ display_options: CompletionDisplayOptions::default(),
// TODO: Could have slash commands indicate whether their completions are incomplete.
is_incomplete: true,
}])
@@ -244,6 +249,7 @@ impl SlashCommandCompletionProvider {
} else {
Task::ready(Ok(vec![project::CompletionResponse {
completions: Vec::new(),
+ display_options: CompletionDisplayOptions::default(),
is_incomplete: true,
}]))
}
@@ -305,6 +311,7 @@ impl CompletionProvider for SlashCommandCompletionProvider {
else {
return Task::ready(Ok(vec![project::CompletionResponse {
completions: Vec::new(),
+ display_options: CompletionDisplayOptions::default(),
is_incomplete: false,
}]));
};
@@ -12,7 +12,9 @@ use language::{
Anchor, Buffer, BufferSnapshot, CodeLabel, LanguageRegistry, ToOffset,
language_settings::SoftWrap,
};
-use project::{Completion, CompletionResponse, CompletionSource, search::SearchQuery};
+use project::{
+ Completion, CompletionDisplayOptions, CompletionResponse, CompletionSource, search::SearchQuery,
+};
use settings::Settings;
use std::{
ops::Range,
@@ -275,6 +277,7 @@ impl MessageEditor {
Task::ready(Ok(vec![CompletionResponse {
completions: Vec::new(),
+ display_options: CompletionDisplayOptions::default(),
is_incomplete: false,
}]))
}
@@ -317,6 +320,7 @@ impl MessageEditor {
CompletionResponse {
is_incomplete: completions.len() >= LIMIT,
+ display_options: CompletionDisplayOptions::default(),
completions,
}
}
@@ -15,7 +15,7 @@ use gpui::{
use language::{Anchor, Buffer, CodeLabel, TextBufferSnapshot, ToOffset};
use menu::{Confirm, SelectNext, SelectPrevious};
use project::{
- Completion, CompletionResponse,
+ Completion, CompletionDisplayOptions, CompletionResponse,
debugger::session::{CompletionsQuery, OutputToken, Session},
lsp_store::CompletionDocumentation,
search_history::{SearchHistory, SearchHistoryCursor},
@@ -685,6 +685,7 @@ impl ConsoleQueryBarCompletionProvider {
Ok(vec![project::CompletionResponse {
is_incomplete: completions.len() >= LIMIT,
+ display_options: CompletionDisplayOptions::default(),
completions,
}])
})
@@ -797,6 +798,7 @@ impl ConsoleQueryBarCompletionProvider {
Ok(vec![project::CompletionResponse {
completions,
+ display_options: CompletionDisplayOptions::default(),
is_incomplete: false,
}])
})
@@ -11,9 +11,9 @@ use language::{Buffer, LanguageName, LanguageRegistry};
use markdown::{Markdown, MarkdownElement};
use multi_buffer::{Anchor, ExcerptId};
use ordered_float::OrderedFloat;
-use project::CompletionSource;
use project::lsp_store::CompletionDocumentation;
use project::{CodeAction, Completion, TaskSourceKind};
+use project::{CompletionDisplayOptions, CompletionSource};
use task::DebugScenario;
use task::TaskContext;
@@ -232,6 +232,7 @@ pub struct CompletionsMenu {
markdown_cache: Rc<RefCell<VecDeque<(MarkdownCacheKey, Entity<Markdown>)>>>,
language_registry: Option<Arc<LanguageRegistry>>,
language: Option<LanguageName>,
+ display_options: CompletionDisplayOptions,
snippet_sort_order: SnippetSortOrder,
}
@@ -271,6 +272,7 @@ impl CompletionsMenu {
is_incomplete: bool,
buffer: Entity<Buffer>,
completions: Box<[Completion]>,
+ display_options: CompletionDisplayOptions,
snippet_sort_order: SnippetSortOrder,
language_registry: Option<Arc<LanguageRegistry>>,
language: Option<LanguageName>,
@@ -304,6 +306,7 @@ impl CompletionsMenu {
markdown_cache: RefCell::new(VecDeque::new()).into(),
language_registry,
language,
+ display_options,
snippet_sort_order,
};
@@ -375,6 +378,7 @@ impl CompletionsMenu {
markdown_cache: RefCell::new(VecDeque::new()).into(),
language_registry: None,
language: None,
+ display_options: CompletionDisplayOptions::default(),
snippet_sort_order,
}
}
@@ -737,6 +741,33 @@ impl CompletionsMenu {
cx: &mut Context<Editor>,
) -> AnyElement {
let show_completion_documentation = self.show_completion_documentation;
+ let widest_completion_ix = if self.display_options.dynamic_width {
+ let completions = self.completions.borrow();
+ let widest_completion_ix = self
+ .entries
+ .borrow()
+ .iter()
+ .enumerate()
+ .max_by_key(|(_, mat)| {
+ let completion = &completions[mat.candidate_id];
+ let documentation = &completion.documentation;
+
+ let mut len = completion.label.text.chars().count();
+ if let Some(CompletionDocumentation::SingleLine(text)) = documentation {
+ if show_completion_documentation {
+ len += text.chars().count();
+ }
+ }
+
+ len
+ })
+ .map(|(ix, _)| ix);
+ drop(completions);
+ widest_completion_ix
+ } else {
+ None
+ };
+
let selected_item = self.selected_item;
let completions = self.completions.clone();
let entries = self.entries.clone();
@@ -863,7 +894,13 @@ impl CompletionsMenu {
.max_h(max_height_in_lines as f32 * window.line_height())
.track_scroll(self.scroll_handle.clone())
.with_sizing_behavior(ListSizingBehavior::Infer)
- .w(rems(34.));
+ .map(|this| {
+ if self.display_options.dynamic_width {
+ this.with_width_from_item(widest_completion_ix)
+ } else {
+ this.w(rems(34.))
+ }
+ });
Popover::new().child(list).into_any_element()
}
@@ -147,21 +147,22 @@ use multi_buffer::{
use parking_lot::Mutex;
use persistence::DB;
use project::{
- BreakpointWithPosition, CodeAction, Completion, CompletionIntent, CompletionResponse,
- CompletionSource, DisableAiSettings, DocumentHighlight, InlayHint, Location, LocationLink,
- PrepareRenameResponse, Project, ProjectItem, ProjectPath, ProjectTransaction, TaskSourceKind,
- debugger::breakpoint_store::Breakpoint,
+ BreakpointWithPosition, CodeAction, Completion, CompletionDisplayOptions, CompletionIntent,
+ CompletionResponse, CompletionSource, DisableAiSettings, DocumentHighlight, InlayHint,
+ Location, LocationLink, PrepareRenameResponse, Project, ProjectItem, ProjectPath,
+ ProjectTransaction, TaskSourceKind,
debugger::{
breakpoint_store::{
- BreakpointEditAction, BreakpointSessionState, BreakpointState, BreakpointStore,
- BreakpointStoreEvent,
+ Breakpoint, BreakpointEditAction, BreakpointSessionState, BreakpointState,
+ BreakpointStore, BreakpointStoreEvent,
},
session::{Session, SessionEvent},
},
git_store::{GitStoreEvent, RepositoryEvent},
lsp_store::{CompletionDocumentation, FormatTrigger, LspFormatTarget, OpenLspBufferHandle},
- project_settings::{DiagnosticSeverity, GoToDiagnosticSeverityFilter},
- project_settings::{GitGutterSetting, ProjectSettings},
+ project_settings::{
+ DiagnosticSeverity, GitGutterSetting, GoToDiagnosticSeverityFilter, ProjectSettings,
+ },
};
use rand::{seq::SliceRandom, thread_rng};
use rpc::{ErrorCode, ErrorExt, proto::PeerId};
@@ -5635,17 +5636,25 @@ impl Editor {
// that having one source with `is_incomplete: true` doesn't cause all to be re-queried.
let mut completions = Vec::new();
let mut is_incomplete = false;
+ let mut display_options: Option<CompletionDisplayOptions> = None;
if let Some(provider_responses) = provider_responses.await.log_err()
&& !provider_responses.is_empty()
{
for response in provider_responses {
completions.extend(response.completions);
is_incomplete = is_incomplete || response.is_incomplete;
+ match display_options.as_mut() {
+ None => {
+ display_options = Some(response.display_options);
+ }
+ Some(options) => options.merge(&response.display_options),
+ }
}
if completion_settings.words == WordsCompletionMode::Fallback {
words = Task::ready(BTreeMap::default());
}
}
+ let display_options = display_options.unwrap_or_default();
let mut words = words.await;
if let Some(word_to_exclude) = &word_to_exclude {
@@ -5687,6 +5696,7 @@ impl Editor {
is_incomplete,
buffer.clone(),
completions.into(),
+ display_options,
snippet_sort_order,
languages,
language,
@@ -22260,6 +22270,7 @@ fn snippet_completions(
if scopes.is_empty() {
return Task::ready(Ok(CompletionResponse {
completions: vec![],
+ display_options: CompletionDisplayOptions::default(),
is_incomplete: false,
}));
}
@@ -22284,6 +22295,7 @@ fn snippet_completions(
if last_word.is_empty() {
return Ok(CompletionResponse {
completions: vec![],
+ display_options: CompletionDisplayOptions::default(),
is_incomplete: true,
});
}
@@ -22405,6 +22417,7 @@ fn snippet_completions(
Ok(CompletionResponse {
completions,
+ display_options: CompletionDisplayOptions::default(),
is_incomplete,
})
})
@@ -14,7 +14,10 @@ use language::{
DiagnosticSeverity, LanguageServerId, Point, ToOffset as _, ToPoint as _,
};
use project::lsp_store::CompletionDocumentation;
-use project::{Completion, CompletionResponse, CompletionSource, Project, ProjectPath};
+use project::{
+ Completion, CompletionDisplayOptions, CompletionResponse, CompletionSource, Project,
+ ProjectPath,
+};
use std::fmt::Write as _;
use std::ops::Range;
use std::path::Path;
@@ -664,6 +667,7 @@ impl CompletionProvider for RustStyleCompletionProvider {
confirm: None,
})
.collect(),
+ display_options: CompletionDisplayOptions::default(),
is_incomplete: false,
}]))
}
@@ -22,7 +22,7 @@ use gpui::{
};
use language::{Language, LanguageConfig, ToOffset as _};
use notifications::status_toast::{StatusToast, ToastIcon};
-use project::Project;
+use project::{CompletionDisplayOptions, Project};
use settings::{BaseKeymap, KeybindSource, KeymapFile, Settings as _, SettingsAssets};
use ui::{
ActiveTheme as _, App, Banner, BorrowAppContext, ContextMenu, IconButtonShape, Indicator,
@@ -2911,6 +2911,7 @@ impl CompletionProvider for KeyContextCompletionProvider {
confirm: None,
})
.collect(),
+ display_options: CompletionDisplayOptions::default(),
is_incomplete: false,
}]))
}
@@ -16,10 +16,10 @@ pub mod lsp_ext_command;
pub mod rust_analyzer_ext;
use crate::{
- CodeAction, ColorPresentation, Completion, CompletionResponse, CompletionSource,
- CoreCompletion, DocumentColor, Hover, InlayHint, LocationLink, LspAction, LspPullDiagnostics,
- ManifestProvidersStore, Project, ProjectItem, ProjectPath, ProjectTransaction,
- PulledDiagnostics, ResolveState, Symbol,
+ CodeAction, ColorPresentation, Completion, CompletionDisplayOptions, CompletionResponse,
+ CompletionSource, CoreCompletion, DocumentColor, Hover, InlayHint, LocationLink, LspAction,
+ LspPullDiagnostics, ManifestProvidersStore, Project, ProjectItem, ProjectPath,
+ ProjectTransaction, PulledDiagnostics, ResolveState, Symbol,
buffer_store::{BufferStore, BufferStoreEvent},
environment::ProjectEnvironment,
lsp_command::{self, *},
@@ -5828,6 +5828,7 @@ impl LspStore {
.await;
Ok(vec![CompletionResponse {
completions,
+ display_options: CompletionDisplayOptions::default(),
is_incomplete: completion_response.is_incomplete,
}])
})
@@ -5920,6 +5921,7 @@ impl LspStore {
.await;
Some(CompletionResponse {
completions,
+ display_options: CompletionDisplayOptions::default(),
is_incomplete: completion_response.is_incomplete,
})
});
@@ -574,11 +574,23 @@ impl std::fmt::Debug for Completion {
/// Response from a source of completions.
pub struct CompletionResponse {
pub completions: Vec<Completion>,
+ pub display_options: CompletionDisplayOptions,
/// When false, indicates that the list is complete and so does not need to be re-queried if it
/// can be filtered instead.
pub is_incomplete: bool,
}
+#[derive(Default)]
+pub struct CompletionDisplayOptions {
+ pub dynamic_width: bool,
+}
+
+impl CompletionDisplayOptions {
+ pub fn merge(&mut self, other: &CompletionDisplayOptions) {
+ self.dynamic_width = self.dynamic_width && other.dynamic_width;
+ }
+}
+
/// Response from language server completion request.
#[derive(Clone, Debug, Default)]
pub(crate) struct CoreCompletionResponse {