Auto-fix clippy::collapsible_if violations (#36428)
Release Notes: - N/A
This commit is contained in:
parent
9e8ec72bd5
commit
8f567383e4
281 changed files with 6628 additions and 7089 deletions
|
@ -830,6 +830,7 @@ module_inception = { level = "deny" }
|
||||||
question_mark = { level = "deny" }
|
question_mark = { level = "deny" }
|
||||||
redundant_closure = { level = "deny" }
|
redundant_closure = { level = "deny" }
|
||||||
declare_interior_mutable_const = { level = "deny" }
|
declare_interior_mutable_const = { level = "deny" }
|
||||||
|
collapsible_if = { level = "warn"}
|
||||||
needless_borrow = { level = "warn"}
|
needless_borrow = { level = "warn"}
|
||||||
# Individual rules that have violations in the codebase:
|
# Individual rules that have violations in the codebase:
|
||||||
type_complexity = "allow"
|
type_complexity = "allow"
|
||||||
|
|
|
@ -249,15 +249,14 @@ impl ToolCall {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(raw_output) = raw_output {
|
if let Some(raw_output) = raw_output {
|
||||||
if self.content.is_empty() {
|
if self.content.is_empty()
|
||||||
if let Some(markdown) = markdown_for_raw_output(&raw_output, &language_registry, cx)
|
&& let Some(markdown) = markdown_for_raw_output(&raw_output, &language_registry, cx)
|
||||||
{
|
{
|
||||||
self.content
|
self.content
|
||||||
.push(ToolCallContent::ContentBlock(ContentBlock::Markdown {
|
.push(ToolCallContent::ContentBlock(ContentBlock::Markdown {
|
||||||
markdown,
|
markdown,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self.raw_output = Some(raw_output);
|
self.raw_output = Some(raw_output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -430,12 +429,12 @@ impl ContentBlock {
|
||||||
language_registry: &Arc<LanguageRegistry>,
|
language_registry: &Arc<LanguageRegistry>,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) {
|
) {
|
||||||
if matches!(self, ContentBlock::Empty) {
|
if matches!(self, ContentBlock::Empty)
|
||||||
if let acp::ContentBlock::ResourceLink(resource_link) = block {
|
&& let acp::ContentBlock::ResourceLink(resource_link) = block
|
||||||
|
{
|
||||||
*self = ContentBlock::ResourceLink { resource_link };
|
*self = ContentBlock::ResourceLink { resource_link };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let new_content = self.block_string_contents(block);
|
let new_content = self.block_string_contents(block);
|
||||||
|
|
||||||
|
|
|
@ -614,11 +614,11 @@ impl ActionLog {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if tracked_buffer.unreviewed_edits.is_empty() {
|
if tracked_buffer.unreviewed_edits.is_empty()
|
||||||
if let TrackedBufferStatus::Created { .. } = &mut tracked_buffer.status {
|
&& let TrackedBufferStatus::Created { .. } = &mut tracked_buffer.status
|
||||||
|
{
|
||||||
tracked_buffer.status = TrackedBufferStatus::Modified;
|
tracked_buffer.status = TrackedBufferStatus::Modified;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
tracked_buffer.schedule_diff_update(ChangeAuthor::User, cx);
|
tracked_buffer.schedule_diff_update(ChangeAuthor::User, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -458,8 +458,9 @@ impl ActivityIndicator {
|
||||||
.map(|r| r.read(cx))
|
.map(|r| r.read(cx))
|
||||||
.and_then(Repository::current_job);
|
.and_then(Repository::current_job);
|
||||||
// Show any long-running git command
|
// Show any long-running git command
|
||||||
if let Some(job_info) = current_job {
|
if let Some(job_info) = current_job
|
||||||
if Instant::now() - job_info.start >= GIT_OPERATION_DELAY {
|
&& Instant::now() - job_info.start >= GIT_OPERATION_DELAY
|
||||||
|
{
|
||||||
return Some(Content {
|
return Some(Content {
|
||||||
icon: Some(
|
icon: Some(
|
||||||
Icon::new(IconName::ArrowCircle)
|
Icon::new(IconName::ArrowCircle)
|
||||||
|
@ -467,9 +468,7 @@ impl ActivityIndicator {
|
||||||
.with_animation(
|
.with_animation(
|
||||||
"arrow-circle",
|
"arrow-circle",
|
||||||
Animation::new(Duration::from_secs(2)).repeat(),
|
Animation::new(Duration::from_secs(2)).repeat(),
|
||||||
|icon, delta| {
|
|icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
|
||||||
icon.transform(Transformation::rotate(percentage(delta)))
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
),
|
),
|
||||||
|
@ -478,7 +477,6 @@ impl ActivityIndicator {
|
||||||
tooltip_message: None,
|
tooltip_message: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Show any language server installation info.
|
// Show any language server installation info.
|
||||||
let mut downloading = SmallVec::<[_; 3]>::new();
|
let mut downloading = SmallVec::<[_; 3]>::new();
|
||||||
|
@ -740,8 +738,8 @@ impl ActivityIndicator {
|
||||||
|
|
||||||
if let Some(extension_store) =
|
if let Some(extension_store) =
|
||||||
ExtensionStore::try_global(cx).map(|extension_store| extension_store.read(cx))
|
ExtensionStore::try_global(cx).map(|extension_store| extension_store.read(cx))
|
||||||
|
&& let Some(extension_id) = extension_store.outstanding_operations().keys().next()
|
||||||
{
|
{
|
||||||
if let Some(extension_id) = extension_store.outstanding_operations().keys().next() {
|
|
||||||
return Some(Content {
|
return Some(Content {
|
||||||
icon: Some(
|
icon: Some(
|
||||||
Icon::new(IconName::Download)
|
Icon::new(IconName::Download)
|
||||||
|
@ -755,7 +753,6 @@ impl ActivityIndicator {
|
||||||
tooltip_message: None,
|
tooltip_message: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,8 +201,9 @@ impl FileContextHandle {
|
||||||
parse_status.changed().await.log_err();
|
parse_status.changed().await.log_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(snapshot) = buffer.read_with(cx, |buffer, _| buffer.snapshot()) {
|
if let Ok(snapshot) = buffer.read_with(cx, |buffer, _| buffer.snapshot())
|
||||||
if let Some(outline) = snapshot.outline(None) {
|
&& let Some(outline) = snapshot.outline(None)
|
||||||
|
{
|
||||||
let items = outline
|
let items = outline
|
||||||
.items
|
.items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -222,7 +223,6 @@ impl FileContextHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to full content if we couldn't build an outline
|
// Fallback to full content if we couldn't build an outline
|
||||||
// (or didn't need to because the file was small enough)
|
// (or didn't need to because the file was small enough)
|
||||||
|
|
|
@ -338,12 +338,10 @@ impl ContextStore {
|
||||||
image_task,
|
image_task,
|
||||||
context_id: self.next_context_id.post_inc(),
|
context_id: self.next_context_id.post_inc(),
|
||||||
});
|
});
|
||||||
if self.has_context(&context) {
|
if self.has_context(&context) && remove_if_exists {
|
||||||
if remove_if_exists {
|
|
||||||
self.remove_context(&context, cx);
|
self.remove_context(&context, cx);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.insert_context(context.clone(), cx);
|
self.insert_context(context.clone(), cx);
|
||||||
Some(context)
|
Some(context)
|
||||||
|
|
|
@ -1967,13 +1967,11 @@ impl Thread {
|
||||||
|
|
||||||
if let Some(prev_message) =
|
if let Some(prev_message) =
|
||||||
thread.messages.get(ix - 1)
|
thread.messages.get(ix - 1)
|
||||||
{
|
&& prev_message.role == Role::Assistant {
|
||||||
if prev_message.role == Role::Assistant {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for message_id in messages_to_remove {
|
for message_id in messages_to_remove {
|
||||||
thread.delete_message(message_id, cx);
|
thread.delete_message(message_id, cx);
|
||||||
|
@ -2476,14 +2474,14 @@ impl Thread {
|
||||||
.ok()?;
|
.ok()?;
|
||||||
|
|
||||||
// Save thread so its summary can be reused later
|
// Save thread so its summary can be reused later
|
||||||
if let Some(thread) = thread.upgrade() {
|
if let Some(thread) = thread.upgrade()
|
||||||
if let Ok(Ok(save_task)) = cx.update(|cx| {
|
&& let Ok(Ok(save_task)) = cx.update(|cx| {
|
||||||
thread_store
|
thread_store
|
||||||
.update(cx, |thread_store, cx| thread_store.save_thread(&thread, cx))
|
.update(cx, |thread_store, cx| thread_store.save_thread(&thread, cx))
|
||||||
}) {
|
})
|
||||||
|
{
|
||||||
save_task.await.log_err();
|
save_task.await.log_err();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Some(())
|
Some(())
|
||||||
});
|
});
|
||||||
|
@ -2730,13 +2728,12 @@ impl Thread {
|
||||||
window: Option<AnyWindowHandle>,
|
window: Option<AnyWindowHandle>,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
if self.all_tools_finished() {
|
if self.all_tools_finished()
|
||||||
if let Some(ConfiguredModel { model, .. }) = self.configured_model.as_ref() {
|
&& let Some(ConfiguredModel { model, .. }) = self.configured_model.as_ref()
|
||||||
if !canceled {
|
&& !canceled
|
||||||
|
{
|
||||||
self.send_to_model(model.clone(), CompletionIntent::ToolResults, window, cx);
|
self.send_to_model(model.clone(), CompletionIntent::ToolResults, window, cx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cx.emit(ThreadEvent::ToolFinished {
|
cx.emit(ThreadEvent::ToolFinished {
|
||||||
tool_use_id,
|
tool_use_id,
|
||||||
|
@ -2922,13 +2919,13 @@ impl Thread {
|
||||||
let buffer_store = project.read(app_cx).buffer_store();
|
let buffer_store = project.read(app_cx).buffer_store();
|
||||||
for buffer_handle in buffer_store.read(app_cx).buffers() {
|
for buffer_handle in buffer_store.read(app_cx).buffers() {
|
||||||
let buffer = buffer_handle.read(app_cx);
|
let buffer = buffer_handle.read(app_cx);
|
||||||
if buffer.is_dirty() {
|
if buffer.is_dirty()
|
||||||
if let Some(file) = buffer.file() {
|
&& let Some(file) = buffer.file()
|
||||||
|
{
|
||||||
let path = file.path().to_string_lossy().to_string();
|
let path = file.path().to_string_lossy().to_string();
|
||||||
unsaved_buffers.push(path);
|
unsaved_buffers.push(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
|
@ -3178,14 +3175,14 @@ impl Thread {
|
||||||
.model
|
.model
|
||||||
.max_token_count_for_mode(self.completion_mode().into());
|
.max_token_count_for_mode(self.completion_mode().into());
|
||||||
|
|
||||||
if let Some(exceeded_error) = &self.exceeded_window_error {
|
if let Some(exceeded_error) = &self.exceeded_window_error
|
||||||
if model.model.id() == exceeded_error.model_id {
|
&& model.model.id() == exceeded_error.model_id
|
||||||
|
{
|
||||||
return Some(TotalTokenUsage {
|
return Some(TotalTokenUsage {
|
||||||
total: exceeded_error.token_count,
|
total: exceeded_error.token_count,
|
||||||
max,
|
max,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let total = self
|
let total = self
|
||||||
.token_usage_at_last_message()
|
.token_usage_at_last_message()
|
||||||
|
|
|
@ -581,8 +581,8 @@ impl ThreadStore {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if protocol.capable(context_server::protocol::ServerCapability::Tools) {
|
if protocol.capable(context_server::protocol::ServerCapability::Tools)
|
||||||
if let Some(response) = protocol
|
&& let Some(response) = protocol
|
||||||
.request::<context_server::types::requests::ListTools>(())
|
.request::<context_server::types::requests::ListTools>(())
|
||||||
.await
|
.await
|
||||||
.log_err()
|
.log_err()
|
||||||
|
@ -609,7 +609,6 @@ impl ThreadStore {
|
||||||
.log_err();
|
.log_err();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
@ -697,14 +696,15 @@ impl SerializedThreadV0_1_0 {
|
||||||
let mut messages: Vec<SerializedMessage> = Vec::with_capacity(self.0.messages.len());
|
let mut messages: Vec<SerializedMessage> = Vec::with_capacity(self.0.messages.len());
|
||||||
|
|
||||||
for message in self.0.messages {
|
for message in self.0.messages {
|
||||||
if message.role == Role::User && !message.tool_results.is_empty() {
|
if message.role == Role::User
|
||||||
if let Some(last_message) = messages.last_mut() {
|
&& !message.tool_results.is_empty()
|
||||||
|
&& let Some(last_message) = messages.last_mut()
|
||||||
|
{
|
||||||
debug_assert!(last_message.role == Role::Assistant);
|
debug_assert!(last_message.role == Role::Assistant);
|
||||||
|
|
||||||
last_message.tool_results = message.tool_results;
|
last_message.tool_results = message.tool_results;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
messages.push(message);
|
messages.push(message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,23 +112,17 @@ impl ToolUseState {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(window) = &mut window {
|
if let Some(window) = &mut window
|
||||||
if let Some(tool) = this.tools.read(cx).tool(tool_use, cx) {
|
&& let Some(tool) = this.tools.read(cx).tool(tool_use, cx)
|
||||||
if let Some(output) = tool_result.output.clone() {
|
&& let Some(output) = tool_result.output.clone()
|
||||||
if let Some(card) = tool.deserialize_card(
|
&& let Some(card) =
|
||||||
output,
|
tool.deserialize_card(output, project.clone(), window, cx)
|
||||||
project.clone(),
|
{
|
||||||
window,
|
|
||||||
cx,
|
|
||||||
) {
|
|
||||||
this.tool_result_cards.insert(tool_use_id, card);
|
this.tool_result_cards.insert(tool_use_id, card);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Role::System | Role::User => {}
|
Role::System | Role::User => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1037,13 +1037,13 @@ impl Thread {
|
||||||
log::info!("Running tool {}", tool_use.name);
|
log::info!("Running tool {}", tool_use.name);
|
||||||
Some(cx.foreground_executor().spawn(async move {
|
Some(cx.foreground_executor().spawn(async move {
|
||||||
let tool_result = tool_result.await.and_then(|output| {
|
let tool_result = tool_result.await.and_then(|output| {
|
||||||
if let LanguageModelToolResultContent::Image(_) = &output.llm_output {
|
if let LanguageModelToolResultContent::Image(_) = &output.llm_output
|
||||||
if !supports_images {
|
&& !supports_images
|
||||||
|
{
|
||||||
return Err(anyhow!(
|
return Err(anyhow!(
|
||||||
"Attempted to read an image, but this model doesn't support it.",
|
"Attempted to read an image, but this model doesn't support it.",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(output)
|
Ok(output)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -156,14 +156,14 @@ impl EditFileTool {
|
||||||
|
|
||||||
// It's also possible that the global config dir is configured to be inside the project,
|
// It's also possible that the global config dir is configured to be inside the project,
|
||||||
// so check for that edge case too.
|
// so check for that edge case too.
|
||||||
if let Ok(canonical_path) = std::fs::canonicalize(&input.path) {
|
if let Ok(canonical_path) = std::fs::canonicalize(&input.path)
|
||||||
if canonical_path.starts_with(paths::config_dir()) {
|
&& canonical_path.starts_with(paths::config_dir())
|
||||||
|
{
|
||||||
return event_stream.authorize(
|
return event_stream.authorize(
|
||||||
format!("{} (global settings)", input.display_description),
|
format!("{} (global settings)", input.display_description),
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Check if path is inside the global config directory
|
// Check if path is inside the global config directory
|
||||||
// First check if it's already inside project - if not, try to canonicalize
|
// First check if it's already inside project - if not, try to canonicalize
|
||||||
|
|
|
@ -179,15 +179,14 @@ impl AgentTool for GrepTool {
|
||||||
// Check if this file should be excluded based on its worktree settings
|
// Check if this file should be excluded based on its worktree settings
|
||||||
if let Ok(Some(project_path)) = project.read_with(cx, |project, cx| {
|
if let Ok(Some(project_path)) = project.read_with(cx, |project, cx| {
|
||||||
project.find_project_path(&path, cx)
|
project.find_project_path(&path, cx)
|
||||||
}) {
|
})
|
||||||
if cx.update(|cx| {
|
&& cx.update(|cx| {
|
||||||
let worktree_settings = WorktreeSettings::get(Some((&project_path).into()), cx);
|
let worktree_settings = WorktreeSettings::get(Some((&project_path).into()), cx);
|
||||||
worktree_settings.is_path_excluded(&project_path.path)
|
worktree_settings.is_path_excluded(&project_path.path)
|
||||||
|| worktree_settings.is_path_private(&project_path.path)
|
|| worktree_settings.is_path_private(&project_path.path)
|
||||||
}).unwrap_or(false) {
|
}).unwrap_or(false) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
while *parse_status.borrow() != ParseStatus::Idle {
|
while *parse_status.borrow() != ParseStatus::Idle {
|
||||||
parse_status.changed().await?;
|
parse_status.changed().await?;
|
||||||
|
@ -275,12 +274,11 @@ impl AgentTool for GrepTool {
|
||||||
output.extend(snapshot.text_for_range(range));
|
output.extend(snapshot.text_for_range(range));
|
||||||
output.push_str("\n```\n");
|
output.push_str("\n```\n");
|
||||||
|
|
||||||
if let Some(ancestor_range) = ancestor_range {
|
if let Some(ancestor_range) = ancestor_range
|
||||||
if end_row < ancestor_range.end.row {
|
&& end_row < ancestor_range.end.row {
|
||||||
let remaining_lines = ancestor_range.end.row - end_row;
|
let remaining_lines = ancestor_range.end.row - end_row;
|
||||||
writeln!(output, "\n{} lines remaining in ancestor node. Read the file to see all.", remaining_lines)?;
|
writeln!(output, "\n{} lines remaining in ancestor node. Read the file to see all.", remaining_lines)?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
matches_found += 1;
|
matches_found += 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,8 +203,9 @@ impl AgentConnection for ClaudeAgentConnection {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(status) = child.status().await.log_err() {
|
if let Some(status) = child.status().await.log_err()
|
||||||
if let Some(thread) = thread_rx.recv().await.ok() {
|
&& let Some(thread) = thread_rx.recv().await.ok()
|
||||||
|
{
|
||||||
thread
|
thread
|
||||||
.update(cx, |thread, cx| {
|
.update(cx, |thread, cx| {
|
||||||
thread.emit_server_exited(status, cx);
|
thread.emit_server_exited(status, cx);
|
||||||
|
@ -212,7 +213,6 @@ impl AgentConnection for ClaudeAgentConnection {
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let thread = cx.new(|cx| {
|
let thread = cx.new(|cx| {
|
||||||
|
|
|
@ -116,16 +116,16 @@ pub struct LanguageModelParameters {
|
||||||
|
|
||||||
impl LanguageModelParameters {
|
impl LanguageModelParameters {
|
||||||
pub fn matches(&self, model: &Arc<dyn LanguageModel>) -> bool {
|
pub fn matches(&self, model: &Arc<dyn LanguageModel>) -> bool {
|
||||||
if let Some(provider) = &self.provider {
|
if let Some(provider) = &self.provider
|
||||||
if provider.0 != model.provider_id().0 {
|
&& provider.0 != model.provider_id().0
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
if let Some(setting_model) = &self.model
|
||||||
if let Some(setting_model) = &self.model {
|
&& *setting_model != model.id().0
|
||||||
if *setting_model != model.id().0 {
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -371,8 +371,9 @@ impl AcpThreadView {
|
||||||
let provider_id = provider_id.clone();
|
let provider_id = provider_id.clone();
|
||||||
let this = this.clone();
|
let this = this.clone();
|
||||||
move |_, ev, window, cx| {
|
move |_, ev, window, cx| {
|
||||||
if let language_model::Event::ProviderStateChanged(updated_provider_id) = &ev {
|
if let language_model::Event::ProviderStateChanged(updated_provider_id) = &ev
|
||||||
if &provider_id == updated_provider_id {
|
&& &provider_id == updated_provider_id
|
||||||
|
{
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
this.thread_state = Self::initial_state(
|
this.thread_state = Self::initial_state(
|
||||||
agent.clone(),
|
agent.clone(),
|
||||||
|
@ -386,7 +387,6 @@ impl AcpThreadView {
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let view = registry.read(cx).provider(&provider_id).map(|provider| {
|
let view = registry.read(cx).provider(&provider_id).map(|provider| {
|
||||||
|
@ -547,12 +547,12 @@ impl AcpThreadView {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
fn send(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
if let Some(thread) = self.thread() {
|
if let Some(thread) = self.thread()
|
||||||
if thread.read(cx).status() != ThreadStatus::Idle {
|
&& thread.read(cx).status() != ThreadStatus::Idle
|
||||||
|
{
|
||||||
self.stop_current_and_send_new_message(window, cx);
|
self.stop_current_and_send_new_message(window, cx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let contents = self
|
let contents = self
|
||||||
.message_editor
|
.message_editor
|
||||||
|
@ -628,8 +628,8 @@ impl AcpThreadView {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(index) = self.editing_message.take() {
|
if let Some(index) = self.editing_message.take()
|
||||||
if let Some(editor) = self
|
&& let Some(editor) = self
|
||||||
.entry_view_state
|
.entry_view_state
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.entry(index)
|
.entry(index)
|
||||||
|
@ -646,7 +646,6 @@ impl AcpThreadView {
|
||||||
editor.set_message(user_message.chunks.clone(), window, cx);
|
editor.set_message(user_message.chunks.clone(), window, cx);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
|
||||||
};
|
};
|
||||||
self.focus_handle(cx).focus(window);
|
self.focus_handle(cx).focus(window);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
@ -3265,8 +3264,8 @@ impl AcpThreadView {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.log_err()
|
.log_err()
|
||||||
|
&& let Some(pop_up) = screen_window.entity(cx).log_err()
|
||||||
{
|
{
|
||||||
if let Some(pop_up) = screen_window.entity(cx).log_err() {
|
|
||||||
self.notification_subscriptions
|
self.notification_subscriptions
|
||||||
.entry(screen_window)
|
.entry(screen_window)
|
||||||
.or_insert_with(Vec::new)
|
.or_insert_with(Vec::new)
|
||||||
|
@ -3311,18 +3310,17 @@ impl AcpThreadView {
|
||||||
let pop_up_weak = pop_up.downgrade();
|
let pop_up_weak = pop_up.downgrade();
|
||||||
|
|
||||||
cx.observe_window_activation(window, move |_, window, cx| {
|
cx.observe_window_activation(window, move |_, window, cx| {
|
||||||
if window.is_window_active() {
|
if window.is_window_active()
|
||||||
if let Some(pop_up) = pop_up_weak.upgrade() {
|
&& let Some(pop_up) = pop_up_weak.upgrade()
|
||||||
|
{
|
||||||
pop_up.update(cx, |_, cx| {
|
pop_up.update(cx, |_, cx| {
|
||||||
cx.emit(AgentNotificationEvent::Dismissed);
|
cx.emit(AgentNotificationEvent::Dismissed);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn dismiss_notifications(&mut self, cx: &mut Context<Self>) {
|
fn dismiss_notifications(&mut self, cx: &mut Context<Self>) {
|
||||||
for window in self.notifications.drain(..) {
|
for window in self.notifications.drain(..) {
|
||||||
|
|
|
@ -1072,8 +1072,8 @@ impl ActiveThread {
|
||||||
}
|
}
|
||||||
ThreadEvent::MessageEdited(message_id) => {
|
ThreadEvent::MessageEdited(message_id) => {
|
||||||
self.clear_last_error();
|
self.clear_last_error();
|
||||||
if let Some(index) = self.messages.iter().position(|id| id == message_id) {
|
if let Some(index) = self.messages.iter().position(|id| id == message_id)
|
||||||
if let Some(rendered_message) = self.thread.update(cx, |thread, cx| {
|
&& let Some(rendered_message) = self.thread.update(cx, |thread, cx| {
|
||||||
thread.message(*message_id).map(|message| {
|
thread.message(*message_id).map(|message| {
|
||||||
let mut rendered_message = RenderedMessage {
|
let mut rendered_message = RenderedMessage {
|
||||||
language_registry: self.language_registry.clone(),
|
language_registry: self.language_registry.clone(),
|
||||||
|
@ -1084,7 +1084,8 @@ impl ActiveThread {
|
||||||
}
|
}
|
||||||
rendered_message
|
rendered_message
|
||||||
})
|
})
|
||||||
}) {
|
})
|
||||||
|
{
|
||||||
self.list_state.splice(index..index + 1, 1);
|
self.list_state.splice(index..index + 1, 1);
|
||||||
self.rendered_messages_by_id
|
self.rendered_messages_by_id
|
||||||
.insert(*message_id, rendered_message);
|
.insert(*message_id, rendered_message);
|
||||||
|
@ -1093,7 +1094,6 @@ impl ActiveThread {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ThreadEvent::MessageDeleted(message_id) => {
|
ThreadEvent::MessageDeleted(message_id) => {
|
||||||
self.deleted_message(message_id);
|
self.deleted_message(message_id);
|
||||||
self.save_thread(cx);
|
self.save_thread(cx);
|
||||||
|
@ -1272,8 +1272,8 @@ impl ActiveThread {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.log_err()
|
.log_err()
|
||||||
|
&& let Some(pop_up) = screen_window.entity(cx).log_err()
|
||||||
{
|
{
|
||||||
if let Some(pop_up) = screen_window.entity(cx).log_err() {
|
|
||||||
self.notification_subscriptions
|
self.notification_subscriptions
|
||||||
.entry(screen_window)
|
.entry(screen_window)
|
||||||
.or_insert_with(Vec::new)
|
.or_insert_with(Vec::new)
|
||||||
|
@ -1318,18 +1318,17 @@ impl ActiveThread {
|
||||||
let pop_up_weak = pop_up.downgrade();
|
let pop_up_weak = pop_up.downgrade();
|
||||||
|
|
||||||
cx.observe_window_activation(window, move |_, window, cx| {
|
cx.observe_window_activation(window, move |_, window, cx| {
|
||||||
if window.is_window_active() {
|
if window.is_window_active()
|
||||||
if let Some(pop_up) = pop_up_weak.upgrade() {
|
&& let Some(pop_up) = pop_up_weak.upgrade()
|
||||||
|
{
|
||||||
pop_up.update(cx, |_, cx| {
|
pop_up.update(cx, |_, cx| {
|
||||||
cx.emit(AgentNotificationEvent::Dismissed);
|
cx.emit(AgentNotificationEvent::Dismissed);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Spawns a task to save the active thread.
|
/// Spawns a task to save the active thread.
|
||||||
///
|
///
|
||||||
|
@ -2269,8 +2268,8 @@ impl ActiveThread {
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
if let Some(last_restore_checkpoint) =
|
if let Some(last_restore_checkpoint) =
|
||||||
self.thread.read(cx).last_restore_checkpoint()
|
self.thread.read(cx).last_restore_checkpoint()
|
||||||
|
&& last_restore_checkpoint.message_id() == message_id
|
||||||
{
|
{
|
||||||
if last_restore_checkpoint.message_id() == message_id {
|
|
||||||
match last_restore_checkpoint {
|
match last_restore_checkpoint {
|
||||||
LastRestoreCheckpoint::Pending { .. } => is_pending = true,
|
LastRestoreCheckpoint::Pending { .. } => is_pending = true,
|
||||||
LastRestoreCheckpoint::Error { error: err, .. } => {
|
LastRestoreCheckpoint::Error { error: err, .. } => {
|
||||||
|
@ -2278,7 +2277,6 @@ impl ActiveThread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let restore_checkpoint_button =
|
let restore_checkpoint_button =
|
||||||
Button::new(("restore-checkpoint", ix), "Restore Checkpoint")
|
Button::new(("restore-checkpoint", ix), "Restore Checkpoint")
|
||||||
|
|
|
@ -163,11 +163,11 @@ impl ConfigurationSource {
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.text(cx);
|
.text(cx);
|
||||||
let settings = serde_json_lenient::from_str::<serde_json::Value>(&text)?;
|
let settings = serde_json_lenient::from_str::<serde_json::Value>(&text)?;
|
||||||
if let Some(settings_validator) = settings_validator {
|
if let Some(settings_validator) = settings_validator
|
||||||
if let Err(error) = settings_validator.validate(&settings) {
|
&& let Err(error) = settings_validator.validate(&settings)
|
||||||
|
{
|
||||||
return Err(anyhow::anyhow!(error.to_string()));
|
return Err(anyhow::anyhow!(error.to_string()));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok((
|
Ok((
|
||||||
id.clone(),
|
id.clone(),
|
||||||
ContextServerSettings::Extension {
|
ContextServerSettings::Extension {
|
||||||
|
@ -716,26 +716,26 @@ fn wait_for_context_server(
|
||||||
project::context_server_store::Event::ServerStatusChanged { server_id, status } => {
|
project::context_server_store::Event::ServerStatusChanged { server_id, status } => {
|
||||||
match status {
|
match status {
|
||||||
ContextServerStatus::Running => {
|
ContextServerStatus::Running => {
|
||||||
if server_id == &context_server_id {
|
if server_id == &context_server_id
|
||||||
if let Some(tx) = tx.lock().unwrap().take() {
|
&& let Some(tx) = tx.lock().unwrap().take()
|
||||||
|
{
|
||||||
let _ = tx.send(Ok(()));
|
let _ = tx.send(Ok(()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ContextServerStatus::Stopped => {
|
ContextServerStatus::Stopped => {
|
||||||
if server_id == &context_server_id {
|
if server_id == &context_server_id
|
||||||
if let Some(tx) = tx.lock().unwrap().take() {
|
&& let Some(tx) = tx.lock().unwrap().take()
|
||||||
|
{
|
||||||
let _ = tx.send(Err("Context server stopped running".into()));
|
let _ = tx.send(Err("Context server stopped running".into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ContextServerStatus::Error(error) => {
|
ContextServerStatus::Error(error) => {
|
||||||
if server_id == &context_server_id {
|
if server_id == &context_server_id
|
||||||
if let Some(tx) = tx.lock().unwrap().take() {
|
&& let Some(tx) = tx.lock().unwrap().take()
|
||||||
|
{
|
||||||
let _ = tx.send(Err(error.clone()));
|
let _ = tx.send(Err(error.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,12 +191,12 @@ impl PickerDelegate for ToolPickerDelegate {
|
||||||
BTreeMap::default();
|
BTreeMap::default();
|
||||||
|
|
||||||
for item in all_items.iter() {
|
for item in all_items.iter() {
|
||||||
if let PickerItem::Tool { server_id, name } = item.clone() {
|
if let PickerItem::Tool { server_id, name } = item.clone()
|
||||||
if name.contains(&query) {
|
&& name.contains(&query)
|
||||||
|
{
|
||||||
tools_by_provider.entry(server_id).or_default().push(name);
|
tools_by_provider.entry(server_id).or_default().push(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
|
|
||||||
|
|
|
@ -1043,8 +1043,9 @@ impl ToolbarItemView for AgentDiffToolbar {
|
||||||
return self.location(cx);
|
return self.location(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(editor) = item.act_as::<Editor>(cx) {
|
if let Some(editor) = item.act_as::<Editor>(cx)
|
||||||
if editor.read(cx).mode().is_full() {
|
&& editor.read(cx).mode().is_full()
|
||||||
|
{
|
||||||
let agent_diff = AgentDiff::global(cx);
|
let agent_diff = AgentDiff::global(cx);
|
||||||
|
|
||||||
self.active_item = Some(AgentDiffToolbarItem::Editor {
|
self.active_item = Some(AgentDiffToolbarItem::Editor {
|
||||||
|
@ -1056,7 +1057,6 @@ impl ToolbarItemView for AgentDiffToolbar {
|
||||||
return self.location(cx);
|
return self.location(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.active_item = None;
|
self.active_item = None;
|
||||||
return self.location(cx);
|
return self.location(cx);
|
||||||
|
@ -1538,16 +1538,10 @@ impl AgentDiff {
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
workspace::Event::ItemAdded { item } => {
|
workspace::Event::ItemAdded { item } => {
|
||||||
if let Some(editor) = item.downcast::<Editor>() {
|
if let Some(editor) = item.downcast::<Editor>()
|
||||||
if let Some(buffer) = Self::full_editor_buffer(editor.read(cx), cx) {
|
&& let Some(buffer) = Self::full_editor_buffer(editor.read(cx), cx)
|
||||||
self.register_editor(
|
{
|
||||||
workspace.downgrade(),
|
self.register_editor(workspace.downgrade(), buffer.clone(), editor, window, cx);
|
||||||
buffer.clone(),
|
|
||||||
editor,
|
|
||||||
window,
|
|
||||||
cx,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -1850,8 +1844,9 @@ impl AgentDiff {
|
||||||
|
|
||||||
let thread = thread.upgrade()?;
|
let thread = thread.upgrade()?;
|
||||||
|
|
||||||
if let PostReviewState::AllReviewed = review(&editor, &thread, window, cx) {
|
if let PostReviewState::AllReviewed = review(&editor, &thread, window, cx)
|
||||||
if let Some(curr_buffer) = editor.read(cx).buffer().read(cx).as_singleton() {
|
&& let Some(curr_buffer) = editor.read(cx).buffer().read(cx).as_singleton()
|
||||||
|
{
|
||||||
let changed_buffers = thread.action_log(cx).read(cx).changed_buffers(cx);
|
let changed_buffers = thread.action_log(cx).read(cx).changed_buffers(cx);
|
||||||
|
|
||||||
let mut keys = changed_buffers.keys().cycle();
|
let mut keys = changed_buffers.keys().cycle();
|
||||||
|
@ -1867,7 +1862,6 @@ impl AgentDiff {
|
||||||
return Some(task);
|
return Some(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return Some(Task::ready(Ok(())));
|
return Some(Task::ready(Ok(())));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1398,15 +1398,14 @@ impl AgentPanel {
|
||||||
if LanguageModelRegistry::read_global(cx)
|
if LanguageModelRegistry::read_global(cx)
|
||||||
.default_model()
|
.default_model()
|
||||||
.map_or(true, |model| model.provider.id() != provider.id())
|
.map_or(true, |model| model.provider.id() != provider.id())
|
||||||
|
&& let Some(model) = provider.default_model(cx)
|
||||||
{
|
{
|
||||||
if let Some(model) = provider.default_model(cx) {
|
|
||||||
update_settings_file::<AgentSettings>(
|
update_settings_file::<AgentSettings>(
|
||||||
self.fs.clone(),
|
self.fs.clone(),
|
||||||
cx,
|
cx,
|
||||||
move |settings, _| settings.set_model(model),
|
move |settings, _| settings.set_model(model),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.new_thread(&NewThread::default(), window, cx);
|
self.new_thread(&NewThread::default(), window, cx);
|
||||||
if let Some((thread, model)) =
|
if let Some((thread, model)) =
|
||||||
|
|
|
@ -352,14 +352,14 @@ impl CodegenAlternative {
|
||||||
event: &multi_buffer::Event,
|
event: &multi_buffer::Event,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
if let multi_buffer::Event::TransactionUndone { transaction_id } = event {
|
if let multi_buffer::Event::TransactionUndone { transaction_id } = event
|
||||||
if self.transformation_transaction_id == Some(*transaction_id) {
|
&& self.transformation_transaction_id == Some(*transaction_id)
|
||||||
|
{
|
||||||
self.transformation_transaction_id = None;
|
self.transformation_transaction_id = None;
|
||||||
self.generation = Task::ready(());
|
self.generation = Task::ready(());
|
||||||
cx.emit(CodegenEvent::Undone);
|
cx.emit(CodegenEvent::Undone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn last_equal_ranges(&self) -> &[Range<Anchor>] {
|
pub fn last_equal_ranges(&self) -> &[Range<Anchor>] {
|
||||||
&self.last_equal_ranges
|
&self.last_equal_ranges
|
||||||
|
@ -576,8 +576,8 @@ impl CodegenAlternative {
|
||||||
let mut lines = chunk.split('\n').peekable();
|
let mut lines = chunk.split('\n').peekable();
|
||||||
while let Some(line) = lines.next() {
|
while let Some(line) = lines.next() {
|
||||||
new_text.push_str(line);
|
new_text.push_str(line);
|
||||||
if line_indent.is_none() {
|
if line_indent.is_none()
|
||||||
if let Some(non_whitespace_ch_ix) =
|
&& let Some(non_whitespace_ch_ix) =
|
||||||
new_text.find(|ch: char| !ch.is_whitespace())
|
new_text.find(|ch: char| !ch.is_whitespace())
|
||||||
{
|
{
|
||||||
line_indent = Some(non_whitespace_ch_ix);
|
line_indent = Some(non_whitespace_ch_ix);
|
||||||
|
@ -585,8 +585,7 @@ impl CodegenAlternative {
|
||||||
|
|
||||||
let line_indent = line_indent.unwrap();
|
let line_indent = line_indent.unwrap();
|
||||||
let base_indent = base_indent.unwrap();
|
let base_indent = base_indent.unwrap();
|
||||||
let indent_delta =
|
let indent_delta = line_indent as i32 - base_indent as i32;
|
||||||
line_indent as i32 - base_indent as i32;
|
|
||||||
let mut corrected_indent_len = cmp::max(
|
let mut corrected_indent_len = cmp::max(
|
||||||
0,
|
0,
|
||||||
suggested_line_indent.len as i32 + indent_delta,
|
suggested_line_indent.len as i32 + indent_delta,
|
||||||
|
@ -594,9 +593,7 @@ impl CodegenAlternative {
|
||||||
as usize;
|
as usize;
|
||||||
if first_line {
|
if first_line {
|
||||||
corrected_indent_len = corrected_indent_len
|
corrected_indent_len = corrected_indent_len
|
||||||
.saturating_sub(
|
.saturating_sub(selection_start.column as usize);
|
||||||
selection_start.column as usize,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let indent_char = suggested_line_indent.char();
|
let indent_char = suggested_line_indent.char();
|
||||||
|
@ -608,7 +605,6 @@ impl CodegenAlternative {
|
||||||
&indent_str.repeat(corrected_indent_len),
|
&indent_str.repeat(corrected_indent_len),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if line_indent.is_some() {
|
if line_indent.is_some() {
|
||||||
let char_ops = diff.push_new(&new_text);
|
let char_ops = diff.push_new(&new_text);
|
||||||
|
|
|
@ -368,12 +368,12 @@ impl ContextStrip {
|
||||||
_window: &mut Window,
|
_window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
if let Some(suggested) = self.suggested_context(cx) {
|
if let Some(suggested) = self.suggested_context(cx)
|
||||||
if self.is_suggested_focused(&self.added_contexts(cx)) {
|
&& self.is_suggested_focused(&self.added_contexts(cx))
|
||||||
|
{
|
||||||
self.add_suggested_context(&suggested, cx);
|
self.add_suggested_context(&suggested, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn add_suggested_context(&mut self, suggested: &SuggestedContext, cx: &mut Context<Self>) {
|
fn add_suggested_context(&mut self, suggested: &SuggestedContext, cx: &mut Context<Self>) {
|
||||||
self.context_store.update(cx, |context_store, cx| {
|
self.context_store.update(cx, |context_store, cx| {
|
||||||
|
|
|
@ -182,8 +182,9 @@ impl InlineAssistant {
|
||||||
match event {
|
match event {
|
||||||
workspace::Event::UserSavedItem { item, .. } => {
|
workspace::Event::UserSavedItem { item, .. } => {
|
||||||
// When the user manually saves an editor, automatically accepts all finished transformations.
|
// When the user manually saves an editor, automatically accepts all finished transformations.
|
||||||
if let Some(editor) = item.upgrade().and_then(|item| item.act_as::<Editor>(cx)) {
|
if let Some(editor) = item.upgrade().and_then(|item| item.act_as::<Editor>(cx))
|
||||||
if let Some(editor_assists) = self.assists_by_editor.get(&editor.downgrade()) {
|
&& let Some(editor_assists) = self.assists_by_editor.get(&editor.downgrade())
|
||||||
|
{
|
||||||
for assist_id in editor_assists.assist_ids.clone() {
|
for assist_id in editor_assists.assist_ids.clone() {
|
||||||
let assist = &self.assists[&assist_id];
|
let assist = &self.assists[&assist_id];
|
||||||
if let CodegenStatus::Done = assist.codegen.read(cx).status(cx) {
|
if let CodegenStatus::Done = assist.codegen.read(cx).status(cx) {
|
||||||
|
@ -192,7 +193,6 @@ impl InlineAssistant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
workspace::Event::ItemAdded { item } => {
|
workspace::Event::ItemAdded { item } => {
|
||||||
self.register_workspace_item(&workspace, item.as_ref(), window, cx);
|
self.register_workspace_item(&workspace, item.as_ref(), window, cx);
|
||||||
}
|
}
|
||||||
|
@ -342,14 +342,12 @@ impl InlineAssistant {
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.ok();
|
.ok();
|
||||||
if let Some(answer) = answer {
|
if let Some(answer) = answer
|
||||||
if answer == 0 {
|
&& answer == 0
|
||||||
cx.update(|window, cx| {
|
{
|
||||||
window.dispatch_action(Box::new(OpenSettings), cx)
|
cx.update(|window, cx| window.dispatch_action(Box::new(OpenSettings), cx))
|
||||||
})
|
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
anyhow::Ok(())
|
anyhow::Ok(())
|
||||||
})
|
})
|
||||||
.detach_and_log_err(cx);
|
.detach_and_log_err(cx);
|
||||||
|
@ -435,12 +433,12 @@ impl InlineAssistant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(prev_selection) = selections.last_mut() {
|
if let Some(prev_selection) = selections.last_mut()
|
||||||
if selection.start <= prev_selection.end {
|
&& selection.start <= prev_selection.end
|
||||||
|
{
|
||||||
prev_selection.end = selection.end;
|
prev_selection.end = selection.end;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let latest_selection = newest_selection.get_or_insert_with(|| selection.clone());
|
let latest_selection = newest_selection.get_or_insert_with(|| selection.clone());
|
||||||
if selection.id > latest_selection.id {
|
if selection.id > latest_selection.id {
|
||||||
|
@ -985,8 +983,8 @@ impl InlineAssistant {
|
||||||
EditorEvent::SelectionsChanged { .. } => {
|
EditorEvent::SelectionsChanged { .. } => {
|
||||||
for assist_id in editor_assists.assist_ids.clone() {
|
for assist_id in editor_assists.assist_ids.clone() {
|
||||||
let assist = &self.assists[&assist_id];
|
let assist = &self.assists[&assist_id];
|
||||||
if let Some(decorations) = assist.decorations.as_ref() {
|
if let Some(decorations) = assist.decorations.as_ref()
|
||||||
if decorations
|
&& decorations
|
||||||
.prompt_editor
|
.prompt_editor
|
||||||
.focus_handle(cx)
|
.focus_handle(cx)
|
||||||
.is_focused(window)
|
.is_focused(window)
|
||||||
|
@ -994,7 +992,6 @@ impl InlineAssistant {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
editor_assists.scroll_lock = None;
|
editor_assists.scroll_lock = None;
|
||||||
}
|
}
|
||||||
|
@ -1503,21 +1500,19 @@ impl InlineAssistant {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> Option<InlineAssistTarget> {
|
) -> Option<InlineAssistTarget> {
|
||||||
if let Some(terminal_panel) = workspace.panel::<TerminalPanel>(cx) {
|
if let Some(terminal_panel) = workspace.panel::<TerminalPanel>(cx)
|
||||||
if terminal_panel
|
&& terminal_panel
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.focus_handle(cx)
|
.focus_handle(cx)
|
||||||
.contains_focused(window, cx)
|
.contains_focused(window, cx)
|
||||||
{
|
&& let Some(terminal_view) = terminal_panel.read(cx).pane().and_then(|pane| {
|
||||||
if let Some(terminal_view) = terminal_panel.read(cx).pane().and_then(|pane| {
|
|
||||||
pane.read(cx)
|
pane.read(cx)
|
||||||
.active_item()
|
.active_item()
|
||||||
.and_then(|t| t.downcast::<TerminalView>())
|
.and_then(|t| t.downcast::<TerminalView>())
|
||||||
}) {
|
})
|
||||||
|
{
|
||||||
return Some(InlineAssistTarget::Terminal(terminal_view));
|
return Some(InlineAssistTarget::Terminal(terminal_view));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let context_editor = agent_panel
|
let context_editor = agent_panel
|
||||||
.and_then(|panel| panel.read(cx).active_context_editor())
|
.and_then(|panel| panel.read(cx).active_context_editor())
|
||||||
|
@ -1741,23 +1736,21 @@ impl InlineAssist {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let CodegenStatus::Error(error) = codegen.read(cx).status(cx) {
|
if let CodegenStatus::Error(error) = codegen.read(cx).status(cx)
|
||||||
if assist.decorations.is_none() {
|
&& assist.decorations.is_none()
|
||||||
if let Some(workspace) = assist.workspace.upgrade() {
|
&& let Some(workspace) = assist.workspace.upgrade()
|
||||||
|
{
|
||||||
let error = format!("Inline assistant error: {}", error);
|
let error = format!("Inline assistant error: {}", error);
|
||||||
workspace.update(cx, |workspace, cx| {
|
workspace.update(cx, |workspace, cx| {
|
||||||
struct InlineAssistantError;
|
struct InlineAssistantError;
|
||||||
|
|
||||||
let id =
|
let id = NotificationId::composite::<InlineAssistantError>(
|
||||||
NotificationId::composite::<InlineAssistantError>(
|
|
||||||
assist_id.0,
|
assist_id.0,
|
||||||
);
|
);
|
||||||
|
|
||||||
workspace.show_toast(Toast::new(id, error), cx);
|
workspace.show_toast(Toast::new(id, error), cx);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if assist.decorations.is_none() {
|
if assist.decorations.is_none() {
|
||||||
this.finish_assist(assist_id, false, window, cx);
|
this.finish_assist(assist_id, false, window, cx);
|
||||||
|
@ -1821,19 +1814,19 @@ impl CodeActionProvider for AssistantCodeActionProvider {
|
||||||
has_diagnostics = true;
|
has_diagnostics = true;
|
||||||
}
|
}
|
||||||
if has_diagnostics {
|
if has_diagnostics {
|
||||||
if let Some(symbols_containing_start) = snapshot.symbols_containing(range.start, None) {
|
if let Some(symbols_containing_start) = snapshot.symbols_containing(range.start, None)
|
||||||
if let Some(symbol) = symbols_containing_start.last() {
|
&& let Some(symbol) = symbols_containing_start.last()
|
||||||
|
{
|
||||||
range.start = cmp::min(range.start, symbol.range.start.to_point(&snapshot));
|
range.start = cmp::min(range.start, symbol.range.start.to_point(&snapshot));
|
||||||
range.end = cmp::max(range.end, symbol.range.end.to_point(&snapshot));
|
range.end = cmp::max(range.end, symbol.range.end.to_point(&snapshot));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(symbols_containing_end) = snapshot.symbols_containing(range.end, None) {
|
if let Some(symbols_containing_end) = snapshot.symbols_containing(range.end, None)
|
||||||
if let Some(symbol) = symbols_containing_end.last() {
|
&& let Some(symbol) = symbols_containing_end.last()
|
||||||
|
{
|
||||||
range.start = cmp::min(range.start, symbol.range.start.to_point(&snapshot));
|
range.start = cmp::min(range.start, symbol.range.start.to_point(&snapshot));
|
||||||
range.end = cmp::max(range.end, symbol.range.end.to_point(&snapshot));
|
range.end = cmp::max(range.end, symbol.range.end.to_point(&snapshot));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Task::ready(Ok(vec![CodeAction {
|
Task::ready(Ok(vec![CodeAction {
|
||||||
server_id: language::LanguageServerId(0),
|
server_id: language::LanguageServerId(0),
|
||||||
|
|
|
@ -388,8 +388,9 @@ impl TerminalInlineAssistant {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) {
|
) {
|
||||||
if let Some(assist) = self.assists.get_mut(&assist_id) {
|
if let Some(assist) = self.assists.get_mut(&assist_id)
|
||||||
if let Some(prompt_editor) = assist.prompt_editor.as_ref().cloned() {
|
&& let Some(prompt_editor) = assist.prompt_editor.as_ref().cloned()
|
||||||
|
{
|
||||||
assist
|
assist
|
||||||
.terminal
|
.terminal
|
||||||
.update(cx, |terminal, cx| {
|
.update(cx, |terminal, cx| {
|
||||||
|
@ -403,7 +404,6 @@ impl TerminalInlineAssistant {
|
||||||
.log_err();
|
.log_err();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TerminalInlineAssist {
|
struct TerminalInlineAssist {
|
||||||
|
@ -450,24 +450,21 @@ impl TerminalInlineAssist {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let CodegenStatus::Error(error) = &codegen.read(cx).status {
|
if let CodegenStatus::Error(error) = &codegen.read(cx).status
|
||||||
if assist.prompt_editor.is_none() {
|
&& assist.prompt_editor.is_none()
|
||||||
if let Some(workspace) = assist.workspace.upgrade() {
|
&& let Some(workspace) = assist.workspace.upgrade()
|
||||||
let error =
|
{
|
||||||
format!("Terminal inline assistant error: {}", error);
|
let error = format!("Terminal inline assistant error: {}", error);
|
||||||
workspace.update(cx, |workspace, cx| {
|
workspace.update(cx, |workspace, cx| {
|
||||||
struct InlineAssistantError;
|
struct InlineAssistantError;
|
||||||
|
|
||||||
let id =
|
let id = NotificationId::composite::<InlineAssistantError>(
|
||||||
NotificationId::composite::<InlineAssistantError>(
|
|
||||||
assist_id.0,
|
assist_id.0,
|
||||||
);
|
);
|
||||||
|
|
||||||
workspace.show_toast(Toast::new(id, error), cx);
|
workspace.show_toast(Toast::new(id, error), cx);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if assist.prompt_editor.is_none() {
|
if assist.prompt_editor.is_none() {
|
||||||
this.finish_assist(assist_id, false, false, window, cx);
|
this.finish_assist(assist_id, false, false, window, cx);
|
||||||
|
|
|
@ -745,8 +745,8 @@ impl TextThreadEditor {
|
||||||
) {
|
) {
|
||||||
if let Some(invoked_slash_command) =
|
if let Some(invoked_slash_command) =
|
||||||
self.context.read(cx).invoked_slash_command(&command_id)
|
self.context.read(cx).invoked_slash_command(&command_id)
|
||||||
|
&& let InvokedSlashCommandStatus::Finished = invoked_slash_command.status
|
||||||
{
|
{
|
||||||
if let InvokedSlashCommandStatus::Finished = invoked_slash_command.status {
|
|
||||||
let run_commands_in_ranges = invoked_slash_command.run_commands_in_ranges.clone();
|
let run_commands_in_ranges = invoked_slash_command.run_commands_in_ranges.clone();
|
||||||
for range in run_commands_in_ranges {
|
for range in run_commands_in_ranges {
|
||||||
let commands = self.context.update(cx, |context, cx| {
|
let commands = self.context.update(cx, |context, cx| {
|
||||||
|
@ -769,7 +769,6 @@ impl TextThreadEditor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.editor.update(cx, |editor, cx| {
|
self.editor.update(cx, |editor, cx| {
|
||||||
if let Some(invoked_slash_command) =
|
if let Some(invoked_slash_command) =
|
||||||
|
|
|
@ -166,8 +166,8 @@ impl ThreadHistory {
|
||||||
this.all_entries.len().saturating_sub(1),
|
this.all_entries.len().saturating_sub(1),
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
} else if let Some(prev_id) = previously_selected_entry {
|
} else if let Some(prev_id) = previously_selected_entry
|
||||||
if let Some(new_ix) = this
|
&& let Some(new_ix) = this
|
||||||
.all_entries
|
.all_entries
|
||||||
.iter()
|
.iter()
|
||||||
.position(|probe| probe.id() == prev_id)
|
.position(|probe| probe.id() == prev_id)
|
||||||
|
@ -175,7 +175,6 @@ impl ThreadHistory {
|
||||||
this.set_selected_entry_index(new_ix, cx);
|
this.set_selected_entry_index(new_ix, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
SearchState::Searching { query, .. } | SearchState::Searched { query, .. } => {
|
SearchState::Searching { query, .. } | SearchState::Searched { query, .. } => {
|
||||||
this.search(query.clone(), cx);
|
this.search(query.clone(), cx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1076,8 +1076,9 @@ impl AssistantContext {
|
||||||
timestamp,
|
timestamp,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if let Some(slash_command) = self.invoked_slash_commands.get_mut(&id) {
|
if let Some(slash_command) = self.invoked_slash_commands.get_mut(&id)
|
||||||
if timestamp > slash_command.timestamp {
|
&& timestamp > slash_command.timestamp
|
||||||
|
{
|
||||||
slash_command.timestamp = timestamp;
|
slash_command.timestamp = timestamp;
|
||||||
match error_message {
|
match error_message {
|
||||||
Some(message) => {
|
Some(message) => {
|
||||||
|
@ -1091,7 +1092,6 @@ impl AssistantContext {
|
||||||
cx.emit(ContextEvent::InvokedSlashCommandChanged { command_id: id });
|
cx.emit(ContextEvent::InvokedSlashCommandChanged { command_id: id });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ContextOperation::BufferOperation(_) => unreachable!(),
|
ContextOperation::BufferOperation(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1368,11 +1368,11 @@ impl AssistantContext {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(last_anchor) = last_anchor {
|
if let Some(last_anchor) = last_anchor
|
||||||
if message.id == last_anchor {
|
&& message.id == last_anchor
|
||||||
|
{
|
||||||
hit_last_anchor = true;
|
hit_last_anchor = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
new_anchor_needs_caching = new_anchor_needs_caching
|
new_anchor_needs_caching = new_anchor_needs_caching
|
||||||
|| (invalidated_caches.contains(&message.id) && anchors.contains(&message.id));
|
|| (invalidated_caches.contains(&message.id) && anchors.contains(&message.id));
|
||||||
|
@ -1406,11 +1406,11 @@ impl AssistantContext {
|
||||||
if !self.pending_completions.is_empty() {
|
if !self.pending_completions.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Some(cache_configuration) = cache_configuration {
|
if let Some(cache_configuration) = cache_configuration
|
||||||
if !cache_configuration.should_speculate {
|
&& !cache_configuration.should_speculate
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let request = {
|
let request = {
|
||||||
let mut req = self.to_completion_request(Some(model), cx);
|
let mut req = self.to_completion_request(Some(model), cx);
|
||||||
|
@ -1552,16 +1552,16 @@ impl AssistantContext {
|
||||||
})
|
})
|
||||||
.map(ToOwned::to_owned)
|
.map(ToOwned::to_owned)
|
||||||
.collect::<SmallVec<_>>();
|
.collect::<SmallVec<_>>();
|
||||||
if let Some(command) = self.slash_commands.command(name, cx) {
|
if let Some(command) = self.slash_commands.command(name, cx)
|
||||||
if !command.requires_argument() || !arguments.is_empty() {
|
&& (!command.requires_argument() || !arguments.is_empty())
|
||||||
|
{
|
||||||
let start_ix = offset + command_line.name.start - 1;
|
let start_ix = offset + command_line.name.start - 1;
|
||||||
let end_ix = offset
|
let end_ix = offset
|
||||||
+ command_line
|
+ command_line
|
||||||
.arguments
|
.arguments
|
||||||
.last()
|
.last()
|
||||||
.map_or(command_line.name.end, |argument| argument.end);
|
.map_or(command_line.name.end, |argument| argument.end);
|
||||||
let source_range =
|
let source_range = buffer.anchor_after(start_ix)..buffer.anchor_after(end_ix);
|
||||||
buffer.anchor_after(start_ix)..buffer.anchor_after(end_ix);
|
|
||||||
let pending_command = ParsedSlashCommand {
|
let pending_command = ParsedSlashCommand {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
arguments,
|
arguments,
|
||||||
|
@ -1572,7 +1572,6 @@ impl AssistantContext {
|
||||||
new_commands.push(pending_command);
|
new_commands.push(pending_command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
offset = lines.offset();
|
offset = lines.offset();
|
||||||
}
|
}
|
||||||
|
@ -1799,8 +1798,8 @@ impl AssistantContext {
|
||||||
});
|
});
|
||||||
|
|
||||||
let end = this.buffer.read(cx).anchor_before(insert_position);
|
let end = this.buffer.read(cx).anchor_before(insert_position);
|
||||||
if run_commands_in_text {
|
if run_commands_in_text
|
||||||
if let Some(invoked_slash_command) =
|
&& let Some(invoked_slash_command) =
|
||||||
this.invoked_slash_commands.get_mut(&command_id)
|
this.invoked_slash_commands.get_mut(&command_id)
|
||||||
{
|
{
|
||||||
invoked_slash_command
|
invoked_slash_command
|
||||||
|
@ -1808,7 +1807,6 @@ impl AssistantContext {
|
||||||
.push(start..end);
|
.push(start..end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
SlashCommandEvent::EndSection => {
|
SlashCommandEvent::EndSection => {
|
||||||
if let Some(pending_section) = pending_section_stack.pop() {
|
if let Some(pending_section) = pending_section_stack.pop() {
|
||||||
let offset_range = (pending_section.start..insert_position)
|
let offset_range = (pending_section.start..insert_position)
|
||||||
|
@ -2741,11 +2739,11 @@ impl AssistantContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.read_with(cx, |this, _cx| {
|
this.read_with(cx, |this, _cx| {
|
||||||
if let Some(summary) = this.summary.content() {
|
if let Some(summary) = this.summary.content()
|
||||||
if summary.text.is_empty() {
|
&& summary.text.is_empty()
|
||||||
|
{
|
||||||
bail!("Model generated an empty summary");
|
bail!("Model generated an empty summary");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})??;
|
})??;
|
||||||
|
|
||||||
|
@ -2924,8 +2922,9 @@ impl AssistantContext {
|
||||||
fs.create_dir(contexts_dir().as_ref()).await?;
|
fs.create_dir(contexts_dir().as_ref()).await?;
|
||||||
|
|
||||||
// rename before write ensures that only one file exists
|
// rename before write ensures that only one file exists
|
||||||
if let Some(old_path) = old_path.as_ref() {
|
if let Some(old_path) = old_path.as_ref()
|
||||||
if new_path.as_path() != old_path.as_ref() {
|
&& new_path.as_path() != old_path.as_ref()
|
||||||
|
{
|
||||||
fs.rename(
|
fs.rename(
|
||||||
old_path,
|
old_path,
|
||||||
&new_path,
|
&new_path,
|
||||||
|
@ -2936,7 +2935,6 @@ impl AssistantContext {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// update path before write in case it fails
|
// update path before write in case it fails
|
||||||
this.update(cx, {
|
this.update(cx, {
|
||||||
|
|
|
@ -894,8 +894,8 @@ impl ContextStore {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if protocol.capable(context_server::protocol::ServerCapability::Prompts) {
|
if protocol.capable(context_server::protocol::ServerCapability::Prompts)
|
||||||
if let Some(response) = protocol
|
&& let Some(response) = protocol
|
||||||
.request::<context_server::types::requests::PromptsList>(())
|
.request::<context_server::types::requests::PromptsList>(())
|
||||||
.await
|
.await
|
||||||
.log_err()
|
.log_err()
|
||||||
|
@ -922,7 +922,6 @@ impl ContextStore {
|
||||||
})
|
})
|
||||||
.log_err();
|
.log_err();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,11 +39,11 @@ impl SlashCommand for ContextServerSlashCommand {
|
||||||
|
|
||||||
fn label(&self, cx: &App) -> language::CodeLabel {
|
fn label(&self, cx: &App) -> language::CodeLabel {
|
||||||
let mut parts = vec![self.prompt.name.as_str()];
|
let mut parts = vec![self.prompt.name.as_str()];
|
||||||
if let Some(args) = &self.prompt.arguments {
|
if let Some(args) = &self.prompt.arguments
|
||||||
if let Some(arg) = args.first() {
|
&& let Some(arg) = args.first()
|
||||||
|
{
|
||||||
parts.push(arg.name.as_str());
|
parts.push(arg.name.as_str());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
create_label_for_command(parts[0], &parts[1..], cx)
|
create_label_for_command(parts[0], &parts[1..], cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,8 +66,8 @@ impl SlashCommand for DeltaSlashCommand {
|
||||||
.metadata
|
.metadata
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|value| serde_json::from_value::<FileCommandMetadata>(value.clone()).ok())
|
.and_then(|value| serde_json::from_value::<FileCommandMetadata>(value.clone()).ok())
|
||||||
|
&& paths.insert(metadata.path.clone())
|
||||||
{
|
{
|
||||||
if paths.insert(metadata.path.clone()) {
|
|
||||||
file_command_old_outputs.push(
|
file_command_old_outputs.push(
|
||||||
context_buffer
|
context_buffer
|
||||||
.as_rope()
|
.as_rope()
|
||||||
|
@ -84,7 +84,6 @@ impl SlashCommand for DeltaSlashCommand {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
cx.background_spawn(async move {
|
cx.background_spawn(async move {
|
||||||
let mut output = SlashCommandOutput::default();
|
let mut output = SlashCommandOutput::default();
|
||||||
|
@ -95,28 +94,28 @@ impl SlashCommand for DeltaSlashCommand {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(file_command_new_outputs)
|
.zip(file_command_new_outputs)
|
||||||
{
|
{
|
||||||
if let Ok(new_output) = new_output {
|
if let Ok(new_output) = new_output
|
||||||
if let Ok(new_output) = SlashCommandOutput::from_event_stream(new_output).await
|
&& let Ok(new_output) = SlashCommandOutput::from_event_stream(new_output).await
|
||||||
|
&& let Some(file_command_range) = new_output.sections.first()
|
||||||
{
|
{
|
||||||
if let Some(file_command_range) = new_output.sections.first() {
|
|
||||||
let new_text = &new_output.text[file_command_range.range.clone()];
|
let new_text = &new_output.text[file_command_range.range.clone()];
|
||||||
if old_text.chars().ne(new_text.chars()) {
|
if old_text.chars().ne(new_text.chars()) {
|
||||||
changes_detected = true;
|
changes_detected = true;
|
||||||
output.sections.extend(new_output.sections.into_iter().map(
|
output
|
||||||
|section| SlashCommandOutputSection {
|
.sections
|
||||||
|
.extend(new_output.sections.into_iter().map(|section| {
|
||||||
|
SlashCommandOutputSection {
|
||||||
range: output.text.len() + section.range.start
|
range: output.text.len() + section.range.start
|
||||||
..output.text.len() + section.range.end,
|
..output.text.len() + section.range.end,
|
||||||
icon: section.icon,
|
icon: section.icon,
|
||||||
label: section.label,
|
label: section.label,
|
||||||
metadata: section.metadata,
|
metadata: section.metadata,
|
||||||
},
|
}
|
||||||
));
|
}));
|
||||||
output.text.push_str(&new_output.text);
|
output.text.push_str(&new_output.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
anyhow::ensure!(changes_detected, "no new changes detected");
|
anyhow::ensure!(changes_detected, "no new changes detected");
|
||||||
Ok(output.to_event_stream())
|
Ok(output.to_event_stream())
|
||||||
|
|
|
@ -280,11 +280,11 @@ fn collect_diagnostics(
|
||||||
|
|
||||||
let mut project_summary = DiagnosticSummary::default();
|
let mut project_summary = DiagnosticSummary::default();
|
||||||
for (project_path, path, summary) in diagnostic_summaries {
|
for (project_path, path, summary) in diagnostic_summaries {
|
||||||
if let Some(path_matcher) = &options.path_matcher {
|
if let Some(path_matcher) = &options.path_matcher
|
||||||
if !path_matcher.is_match(&path) {
|
&& !path_matcher.is_match(&path)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
project_summary.error_count += summary.error_count;
|
project_summary.error_count += summary.error_count;
|
||||||
if options.include_warnings {
|
if options.include_warnings {
|
||||||
|
|
|
@ -195,18 +195,16 @@ fn tab_items_for_queries(
|
||||||
}
|
}
|
||||||
|
|
||||||
for editor in workspace.items_of_type::<Editor>(cx) {
|
for editor in workspace.items_of_type::<Editor>(cx) {
|
||||||
if let Some(buffer) = editor.read(cx).buffer().read(cx).as_singleton() {
|
if let Some(buffer) = editor.read(cx).buffer().read(cx).as_singleton()
|
||||||
if let Some(timestamp) =
|
&& let Some(timestamp) =
|
||||||
timestamps_by_entity_id.get(&editor.entity_id())
|
timestamps_by_entity_id.get(&editor.entity_id())
|
||||||
|
&& visited_buffers.insert(buffer.read(cx).remote_id())
|
||||||
{
|
{
|
||||||
if visited_buffers.insert(buffer.read(cx).remote_id()) {
|
|
||||||
let snapshot = buffer.read(cx).snapshot();
|
let snapshot = buffer.read(cx).snapshot();
|
||||||
let full_path = snapshot.resolve_file_path(cx, true);
|
let full_path = snapshot.resolve_file_path(cx, true);
|
||||||
open_buffers.push((full_path, snapshot, *timestamp));
|
open_buffers.push((full_path, snapshot, *timestamp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(open_buffers)
|
Ok(open_buffers)
|
||||||
})??;
|
})??;
|
||||||
|
|
|
@ -24,8 +24,9 @@ pub fn adapt_schema_to_format(
|
||||||
fn preprocess_json_schema(json: &mut Value) -> Result<()> {
|
fn preprocess_json_schema(json: &mut Value) -> Result<()> {
|
||||||
// `additionalProperties` defaults to `false` unless explicitly specified.
|
// `additionalProperties` defaults to `false` unless explicitly specified.
|
||||||
// This prevents models from hallucinating tool parameters.
|
// This prevents models from hallucinating tool parameters.
|
||||||
if let Value::Object(obj) = json {
|
if let Value::Object(obj) = json
|
||||||
if matches!(obj.get("type"), Some(Value::String(s)) if s == "object") {
|
&& matches!(obj.get("type"), Some(Value::String(s)) if s == "object")
|
||||||
|
{
|
||||||
if !obj.contains_key("additionalProperties") {
|
if !obj.contains_key("additionalProperties") {
|
||||||
obj.insert("additionalProperties".to_string(), Value::Bool(false));
|
obj.insert("additionalProperties".to_string(), Value::Bool(false));
|
||||||
}
|
}
|
||||||
|
@ -35,7 +36,6 @@ fn preprocess_json_schema(json: &mut Value) -> Result<()> {
|
||||||
obj.insert("properties".to_string(), Value::Object(Default::default()));
|
obj.insert("properties".to_string(), Value::Object(Default::default()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,12 +59,12 @@ fn adapt_to_json_schema_subset(json: &mut Value) -> Result<()> {
|
||||||
("optional", |value| value.is_boolean()),
|
("optional", |value| value.is_boolean()),
|
||||||
];
|
];
|
||||||
for (key, predicate) in KEYS_TO_REMOVE {
|
for (key, predicate) in KEYS_TO_REMOVE {
|
||||||
if let Some(value) = obj.get(key) {
|
if let Some(value) = obj.get(key)
|
||||||
if predicate(value) {
|
&& predicate(value)
|
||||||
|
{
|
||||||
obj.remove(key);
|
obj.remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If a type is not specified for an input parameter, add a default type
|
// If a type is not specified for an input parameter, add a default type
|
||||||
if matches!(obj.get("description"), Some(Value::String(_)))
|
if matches!(obj.get("description"), Some(Value::String(_)))
|
||||||
|
@ -77,13 +77,13 @@ fn adapt_to_json_schema_subset(json: &mut Value) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle oneOf -> anyOf conversion
|
// Handle oneOf -> anyOf conversion
|
||||||
if let Some(subschemas) = obj.get_mut("oneOf") {
|
if let Some(subschemas) = obj.get_mut("oneOf")
|
||||||
if subschemas.is_array() {
|
&& subschemas.is_array()
|
||||||
|
{
|
||||||
let subschemas_clone = subschemas.clone();
|
let subschemas_clone = subschemas.clone();
|
||||||
obj.remove("oneOf");
|
obj.remove("oneOf");
|
||||||
obj.insert("anyOf".to_string(), subschemas_clone);
|
obj.insert("anyOf".to_string(), subschemas_clone);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Recursively process all nested objects and arrays
|
// Recursively process all nested objects and arrays
|
||||||
for (_, value) in obj.iter_mut() {
|
for (_, value) in obj.iter_mut() {
|
||||||
|
|
|
@ -672,8 +672,9 @@ impl EditAgent {
|
||||||
cx: &mut AsyncApp,
|
cx: &mut AsyncApp,
|
||||||
) -> Result<BoxStream<'static, Result<String, LanguageModelCompletionError>>> {
|
) -> Result<BoxStream<'static, Result<String, LanguageModelCompletionError>>> {
|
||||||
let mut messages_iter = conversation.messages.iter_mut();
|
let mut messages_iter = conversation.messages.iter_mut();
|
||||||
if let Some(last_message) = messages_iter.next_back() {
|
if let Some(last_message) = messages_iter.next_back()
|
||||||
if last_message.role == Role::Assistant {
|
&& last_message.role == Role::Assistant
|
||||||
|
{
|
||||||
let old_content_len = last_message.content.len();
|
let old_content_len = last_message.content.len();
|
||||||
last_message
|
last_message
|
||||||
.content
|
.content
|
||||||
|
@ -685,18 +686,18 @@ impl EditAgent {
|
||||||
// (e.g., the message will look very different on the next
|
// (e.g., the message will look very different on the next
|
||||||
// request). Thus, we move the flag to the message prior to it,
|
// request). Thus, we move the flag to the message prior to it,
|
||||||
// as it will still be a valid prefix of the conversation.
|
// as it will still be a valid prefix of the conversation.
|
||||||
if old_content_len != new_content_len && last_message.cache {
|
if old_content_len != new_content_len
|
||||||
if let Some(prev_message) = messages_iter.next_back() {
|
&& last_message.cache
|
||||||
|
&& let Some(prev_message) = messages_iter.next_back()
|
||||||
|
{
|
||||||
last_message.cache = false;
|
last_message.cache = false;
|
||||||
prev_message.cache = true;
|
prev_message.cache = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if last_message.content.is_empty() {
|
if last_message.content.is_empty() {
|
||||||
conversation.messages.pop();
|
conversation.messages.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
conversation.messages.push(LanguageModelRequestMessage {
|
conversation.messages.push(LanguageModelRequestMessage {
|
||||||
role: Role::User,
|
role: Role::User,
|
||||||
|
|
|
@ -1283,15 +1283,15 @@ impl EvalAssertion {
|
||||||
|
|
||||||
// Parse the score from the response
|
// Parse the score from the response
|
||||||
let re = regex::Regex::new(r"<score>(\d+)</score>").unwrap();
|
let re = regex::Regex::new(r"<score>(\d+)</score>").unwrap();
|
||||||
if let Some(captures) = re.captures(&output) {
|
if let Some(captures) = re.captures(&output)
|
||||||
if let Some(score_match) = captures.get(1) {
|
&& let Some(score_match) = captures.get(1)
|
||||||
|
{
|
||||||
let score = score_match.as_str().parse().unwrap_or(0);
|
let score = score_match.as_str().parse().unwrap_or(0);
|
||||||
return Ok(EvalAssertionOutcome {
|
return Ok(EvalAssertionOutcome {
|
||||||
score,
|
score,
|
||||||
message: Some(output),
|
message: Some(output),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
anyhow::bail!("No score found in response. Raw output: {output}");
|
anyhow::bail!("No score found in response. Raw output: {output}");
|
||||||
})
|
})
|
||||||
|
|
|
@ -155,11 +155,11 @@ impl Tool for EditFileTool {
|
||||||
|
|
||||||
// It's also possible that the global config dir is configured to be inside the project,
|
// It's also possible that the global config dir is configured to be inside the project,
|
||||||
// so check for that edge case too.
|
// so check for that edge case too.
|
||||||
if let Ok(canonical_path) = std::fs::canonicalize(&input.path) {
|
if let Ok(canonical_path) = std::fs::canonicalize(&input.path)
|
||||||
if canonical_path.starts_with(paths::config_dir()) {
|
&& canonical_path.starts_with(paths::config_dir())
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Check if path is inside the global config directory
|
// Check if path is inside the global config directory
|
||||||
// First check if it's already inside project - if not, try to canonicalize
|
// First check if it's already inside project - if not, try to canonicalize
|
||||||
|
@ -199,11 +199,11 @@ impl Tool for EditFileTool {
|
||||||
.any(|c| c.as_os_str() == local_settings_folder.as_os_str())
|
.any(|c| c.as_os_str() == local_settings_folder.as_os_str())
|
||||||
{
|
{
|
||||||
description.push_str(" (local settings)");
|
description.push_str(" (local settings)");
|
||||||
} else if let Ok(canonical_path) = std::fs::canonicalize(&input.path) {
|
} else if let Ok(canonical_path) = std::fs::canonicalize(&input.path)
|
||||||
if canonical_path.starts_with(paths::config_dir()) {
|
&& canonical_path.starts_with(paths::config_dir())
|
||||||
|
{
|
||||||
description.push_str(" (global settings)");
|
description.push_str(" (global settings)");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
description
|
description
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,15 +188,14 @@ impl Tool for GrepTool {
|
||||||
// Check if this file should be excluded based on its worktree settings
|
// Check if this file should be excluded based on its worktree settings
|
||||||
if let Ok(Some(project_path)) = project.read_with(cx, |project, cx| {
|
if let Ok(Some(project_path)) = project.read_with(cx, |project, cx| {
|
||||||
project.find_project_path(&path, cx)
|
project.find_project_path(&path, cx)
|
||||||
}) {
|
})
|
||||||
if cx.update(|cx| {
|
&& cx.update(|cx| {
|
||||||
let worktree_settings = WorktreeSettings::get(Some((&project_path).into()), cx);
|
let worktree_settings = WorktreeSettings::get(Some((&project_path).into()), cx);
|
||||||
worktree_settings.is_path_excluded(&project_path.path)
|
worktree_settings.is_path_excluded(&project_path.path)
|
||||||
|| worktree_settings.is_path_private(&project_path.path)
|
|| worktree_settings.is_path_private(&project_path.path)
|
||||||
}).unwrap_or(false) {
|
}).unwrap_or(false) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
while *parse_status.borrow() != ParseStatus::Idle {
|
while *parse_status.borrow() != ParseStatus::Idle {
|
||||||
parse_status.changed().await?;
|
parse_status.changed().await?;
|
||||||
|
@ -284,12 +283,11 @@ impl Tool for GrepTool {
|
||||||
output.extend(snapshot.text_for_range(range));
|
output.extend(snapshot.text_for_range(range));
|
||||||
output.push_str("\n```\n");
|
output.push_str("\n```\n");
|
||||||
|
|
||||||
if let Some(ancestor_range) = ancestor_range {
|
if let Some(ancestor_range) = ancestor_range
|
||||||
if end_row < ancestor_range.end.row {
|
&& end_row < ancestor_range.end.row {
|
||||||
let remaining_lines = ancestor_range.end.row - end_row;
|
let remaining_lines = ancestor_range.end.row - end_row;
|
||||||
writeln!(output, "\n{} lines remaining in ancestor node. Read the file to see all.", remaining_lines)?;
|
writeln!(output, "\n{} lines remaining in ancestor node. Read the file to see all.", remaining_lines)?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
matches_found += 1;
|
matches_found += 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,13 +43,12 @@ impl Transform for ToJsonSchemaSubsetTransform {
|
||||||
fn transform(&mut self, schema: &mut Schema) {
|
fn transform(&mut self, schema: &mut Schema) {
|
||||||
// Ensure that the type field is not an array, this happens when we use
|
// Ensure that the type field is not an array, this happens when we use
|
||||||
// Option<T>, the type will be [T, "null"].
|
// Option<T>, the type will be [T, "null"].
|
||||||
if let Some(type_field) = schema.get_mut("type") {
|
if let Some(type_field) = schema.get_mut("type")
|
||||||
if let Some(types) = type_field.as_array() {
|
&& let Some(types) = type_field.as_array()
|
||||||
if let Some(first_type) = types.first() {
|
&& let Some(first_type) = types.first()
|
||||||
|
{
|
||||||
*type_field = first_type.clone();
|
*type_field = first_type.clone();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// oneOf is not supported, use anyOf instead
|
// oneOf is not supported, use anyOf instead
|
||||||
if let Some(one_of) = schema.remove("oneOf") {
|
if let Some(one_of) = schema.remove("oneOf") {
|
||||||
|
|
|
@ -186,12 +186,12 @@ unsafe extern "system" fn wnd_proc(
|
||||||
}),
|
}),
|
||||||
WM_TERMINATE => {
|
WM_TERMINATE => {
|
||||||
with_dialog_data(hwnd, |data| {
|
with_dialog_data(hwnd, |data| {
|
||||||
if let Ok(result) = data.borrow_mut().rx.recv() {
|
if let Ok(result) = data.borrow_mut().rx.recv()
|
||||||
if let Err(e) = result {
|
&& let Err(e) = result
|
||||||
|
{
|
||||||
log::error!("Failed to update Zed: {:?}", e);
|
log::error!("Failed to update Zed: {:?}", e);
|
||||||
show_error(format!("Error: {:?}", e));
|
show_error(format!("Error: {:?}", e));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
unsafe { PostQuitMessage(0) };
|
unsafe { PostQuitMessage(0) };
|
||||||
LRESULT(0)
|
LRESULT(0)
|
||||||
|
|
|
@ -82,12 +82,13 @@ impl Render for Breadcrumbs {
|
||||||
}
|
}
|
||||||
text_style.color = Color::Muted.color(cx);
|
text_style.color = Color::Muted.color(cx);
|
||||||
|
|
||||||
if index == 0 && !TabBarSettings::get_global(cx).show && active_item.is_dirty(cx) {
|
if index == 0
|
||||||
if let Some(styled_element) = apply_dirty_filename_style(&segment, &text_style, cx)
|
&& !TabBarSettings::get_global(cx).show
|
||||||
|
&& active_item.is_dirty(cx)
|
||||||
|
&& let Some(styled_element) = apply_dirty_filename_style(&segment, &text_style, cx)
|
||||||
{
|
{
|
||||||
return styled_element;
|
return styled_element;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
StyledText::new(segment.text.replace('\n', "⏎"))
|
StyledText::new(segment.text.replace('\n', "⏎"))
|
||||||
.with_default_highlights(&text_style, segment.highlights.unwrap_or_default())
|
.with_default_highlights(&text_style, segment.highlights.unwrap_or_default())
|
||||||
|
|
|
@ -572,16 +572,16 @@ impl BufferDiffInner {
|
||||||
pending_range.end.column = 0;
|
pending_range.end.column = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if pending_range == (start_point..end_point) {
|
if pending_range == (start_point..end_point)
|
||||||
if !buffer.has_edits_since_in_range(
|
&& !buffer.has_edits_since_in_range(
|
||||||
&pending_hunk.buffer_version,
|
&pending_hunk.buffer_version,
|
||||||
start_anchor..end_anchor,
|
start_anchor..end_anchor,
|
||||||
) {
|
)
|
||||||
|
{
|
||||||
has_pending = true;
|
has_pending = true;
|
||||||
secondary_status = pending_hunk.new_status;
|
secondary_status = pending_hunk.new_status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let (Some(secondary_cursor), false) = (secondary_cursor.as_mut(), has_pending) {
|
if let (Some(secondary_cursor), false) = (secondary_cursor.as_mut(), has_pending) {
|
||||||
if start_anchor
|
if start_anchor
|
||||||
|
@ -1036,8 +1036,8 @@ impl BufferDiff {
|
||||||
_ => (true, Some(text::Anchor::MIN..text::Anchor::MAX)),
|
_ => (true, Some(text::Anchor::MIN..text::Anchor::MAX)),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(secondary_changed_range) = secondary_diff_change {
|
if let Some(secondary_changed_range) = secondary_diff_change
|
||||||
if let Some(secondary_hunk_range) =
|
&& let Some(secondary_hunk_range) =
|
||||||
self.range_to_hunk_range(secondary_changed_range, buffer, cx)
|
self.range_to_hunk_range(secondary_changed_range, buffer, cx)
|
||||||
{
|
{
|
||||||
if let Some(range) = &mut changed_range {
|
if let Some(range) = &mut changed_range {
|
||||||
|
@ -1047,7 +1047,6 @@ impl BufferDiff {
|
||||||
changed_range = Some(secondary_hunk_range);
|
changed_range = Some(secondary_hunk_range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let state = &mut self.inner;
|
let state = &mut self.inner;
|
||||||
state.base_text_exists = new_state.base_text_exists;
|
state.base_text_exists = new_state.base_text_exists;
|
||||||
|
|
|
@ -827,8 +827,8 @@ impl Room {
|
||||||
);
|
);
|
||||||
|
|
||||||
Audio::play_sound(Sound::Joined, cx);
|
Audio::play_sound(Sound::Joined, cx);
|
||||||
if let Some(livekit_participants) = &livekit_participants {
|
if let Some(livekit_participants) = &livekit_participants
|
||||||
if let Some(livekit_participant) = livekit_participants
|
&& let Some(livekit_participant) = livekit_participants
|
||||||
.get(&ParticipantIdentity(user.id.to_string()))
|
.get(&ParticipantIdentity(user.id.to_string()))
|
||||||
{
|
{
|
||||||
for publication in
|
for publication in
|
||||||
|
@ -849,7 +849,6 @@ impl Room {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this.remote_participants.retain(|user_id, participant| {
|
this.remote_participants.retain(|user_id, participant| {
|
||||||
if this.participant_user_ids.contains(user_id) {
|
if this.participant_user_ids.contains(user_id) {
|
||||||
|
@ -940,11 +939,10 @@ impl Room {
|
||||||
self.client.user_id()
|
self.client.user_id()
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
if self.live_kit.as_ref().map_or(true, |kit| kit.deafened) {
|
if self.live_kit.as_ref().map_or(true, |kit| kit.deafened) && publication.is_audio()
|
||||||
if publication.is_audio() {
|
{
|
||||||
publication.set_enabled(false, cx);
|
publication.set_enabled(false, cx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
match track {
|
match track {
|
||||||
livekit_client::RemoteTrack::Audio(track) => {
|
livekit_client::RemoteTrack::Audio(track) => {
|
||||||
cx.emit(Event::RemoteAudioTracksChanged {
|
cx.emit(Event::RemoteAudioTracksChanged {
|
||||||
|
@ -1005,12 +1003,12 @@ impl Room {
|
||||||
for (sid, participant) in &mut self.remote_participants {
|
for (sid, participant) in &mut self.remote_participants {
|
||||||
participant.speaking = speaker_ids.binary_search(sid).is_ok();
|
participant.speaking = speaker_ids.binary_search(sid).is_ok();
|
||||||
}
|
}
|
||||||
if let Some(id) = self.client.user_id() {
|
if let Some(id) = self.client.user_id()
|
||||||
if let Some(room) = &mut self.live_kit {
|
&& let Some(room) = &mut self.live_kit
|
||||||
|
{
|
||||||
room.speaking = speaker_ids.binary_search(&id).is_ok();
|
room.speaking = speaker_ids.binary_search(&id).is_ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
RoomEvent::TrackMuted {
|
RoomEvent::TrackMuted {
|
||||||
participant,
|
participant,
|
||||||
|
@ -1042,21 +1040,19 @@ impl Room {
|
||||||
if let LocalTrack::Published {
|
if let LocalTrack::Published {
|
||||||
track_publication, ..
|
track_publication, ..
|
||||||
} = &room.microphone_track
|
} = &room.microphone_track
|
||||||
|
&& track_publication.sid() == publication.sid()
|
||||||
{
|
{
|
||||||
if track_publication.sid() == publication.sid() {
|
|
||||||
room.microphone_track = LocalTrack::None;
|
room.microphone_track = LocalTrack::None;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if let LocalTrack::Published {
|
if let LocalTrack::Published {
|
||||||
track_publication, ..
|
track_publication, ..
|
||||||
} = &room.screen_track
|
} = &room.screen_track
|
||||||
|
&& track_publication.sid() == publication.sid()
|
||||||
{
|
{
|
||||||
if track_publication.sid() == publication.sid() {
|
|
||||||
room.screen_track = LocalTrack::None;
|
room.screen_track = LocalTrack::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
RoomEvent::LocalTrackPublished { publication, .. } => {
|
RoomEvent::LocalTrackPublished { publication, .. } => {
|
||||||
log::info!("published track {:?}", publication.sid());
|
log::info!("published track {:?}", publication.sid());
|
||||||
|
@ -1484,13 +1480,11 @@ impl Room {
|
||||||
|
|
||||||
self.set_deafened(deafened, cx);
|
self.set_deafened(deafened, cx);
|
||||||
|
|
||||||
if should_change_mute {
|
if should_change_mute && let Some(task) = self.set_mute(deafened, cx) {
|
||||||
if let Some(task) = self.set_mute(deafened, cx) {
|
|
||||||
task.detach_and_log_err(cx);
|
task.detach_and_log_err(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unshare_screen(&mut self, play_sound: bool, cx: &mut Context<Self>) -> Result<()> {
|
pub fn unshare_screen(&mut self, play_sound: bool, cx: &mut Context<Self>) -> Result<()> {
|
||||||
anyhow::ensure!(!self.status.is_offline(), "room is offline");
|
anyhow::ensure!(!self.status.is_offline(), "room is offline");
|
||||||
|
|
|
@ -191,13 +191,12 @@ impl ChannelBuffer {
|
||||||
operation,
|
operation,
|
||||||
is_local: true,
|
is_local: true,
|
||||||
} => {
|
} => {
|
||||||
if *ZED_ALWAYS_ACTIVE {
|
if *ZED_ALWAYS_ACTIVE
|
||||||
if let language::Operation::UpdateSelections { selections, .. } = operation {
|
&& let language::Operation::UpdateSelections { selections, .. } = operation
|
||||||
if selections.is_empty() {
|
&& selections.is_empty()
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
let operation = language::proto::serialize_operation(operation);
|
let operation = language::proto::serialize_operation(operation);
|
||||||
self.client
|
self.client
|
||||||
.send(proto::UpdateChannelBuffer {
|
.send(proto::UpdateChannelBuffer {
|
||||||
|
|
|
@ -329,8 +329,9 @@ impl ChannelChat {
|
||||||
loop {
|
loop {
|
||||||
let step = chat
|
let step = chat
|
||||||
.update(&mut cx, |chat, cx| {
|
.update(&mut cx, |chat, cx| {
|
||||||
if let Some(first_id) = chat.first_loaded_message_id() {
|
if let Some(first_id) = chat.first_loaded_message_id()
|
||||||
if first_id <= message_id {
|
&& first_id <= message_id
|
||||||
|
{
|
||||||
let mut cursor = chat
|
let mut cursor = chat
|
||||||
.messages
|
.messages
|
||||||
.cursor::<Dimensions<ChannelMessageId, Count>>(&());
|
.cursor::<Dimensions<ChannelMessageId, Count>>(&());
|
||||||
|
@ -347,7 +348,6 @@ impl ChannelChat {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ControlFlow::Continue(chat.load_more_messages(cx))
|
ControlFlow::Continue(chat.load_more_messages(cx))
|
||||||
})
|
})
|
||||||
.log_err()?;
|
.log_err()?;
|
||||||
|
@ -359,8 +359,8 @@ impl ChannelChat {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn acknowledge_last_message(&mut self, cx: &mut Context<Self>) {
|
pub fn acknowledge_last_message(&mut self, cx: &mut Context<Self>) {
|
||||||
if let ChannelMessageId::Saved(latest_message_id) = self.messages.summary().max_id {
|
if let ChannelMessageId::Saved(latest_message_id) = self.messages.summary().max_id
|
||||||
if self
|
&& self
|
||||||
.last_acknowledged_id
|
.last_acknowledged_id
|
||||||
.map_or(true, |acknowledged_id| acknowledged_id < latest_message_id)
|
.map_or(true, |acknowledged_id| acknowledged_id < latest_message_id)
|
||||||
{
|
{
|
||||||
|
@ -376,7 +376,6 @@ impl ChannelChat {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_loaded_messages(
|
async fn handle_loaded_messages(
|
||||||
this: WeakEntity<Self>,
|
this: WeakEntity<Self>,
|
||||||
|
@ -407,11 +406,11 @@ impl ChannelChat {
|
||||||
let missing_ancestors = loaded_messages
|
let missing_ancestors = loaded_messages
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|message| {
|
.filter_map(|message| {
|
||||||
if let Some(ancestor_id) = message.reply_to_message_id {
|
if let Some(ancestor_id) = message.reply_to_message_id
|
||||||
if !loaded_message_ids.contains(&ancestor_id) {
|
&& !loaded_message_ids.contains(&ancestor_id)
|
||||||
|
{
|
||||||
return Some(ancestor_id);
|
return Some(ancestor_id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
None
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -646,8 +645,9 @@ impl ChannelChat {
|
||||||
fn message_removed(&mut self, id: u64, cx: &mut Context<Self>) {
|
fn message_removed(&mut self, id: u64, cx: &mut Context<Self>) {
|
||||||
let mut cursor = self.messages.cursor::<ChannelMessageId>(&());
|
let mut cursor = self.messages.cursor::<ChannelMessageId>(&());
|
||||||
let mut messages = cursor.slice(&ChannelMessageId::Saved(id), Bias::Left);
|
let mut messages = cursor.slice(&ChannelMessageId::Saved(id), Bias::Left);
|
||||||
if let Some(item) = cursor.item() {
|
if let Some(item) = cursor.item()
|
||||||
if item.id == ChannelMessageId::Saved(id) {
|
&& item.id == ChannelMessageId::Saved(id)
|
||||||
|
{
|
||||||
let deleted_message_ix = messages.summary().count;
|
let deleted_message_ix = messages.summary().count;
|
||||||
cursor.next();
|
cursor.next();
|
||||||
messages.append(cursor.suffix(), &());
|
messages.append(cursor.suffix(), &());
|
||||||
|
@ -660,11 +660,11 @@ impl ChannelChat {
|
||||||
let summary = self.messages.summary();
|
let summary = self.messages.summary();
|
||||||
if summary.count == 0 {
|
if summary.count == 0 {
|
||||||
store.set_acknowledged_message_id(self.channel_id, None);
|
store.set_acknowledged_message_id(self.channel_id, None);
|
||||||
} else if deleted_message_ix == summary.count {
|
} else if deleted_message_ix == summary.count
|
||||||
if let ChannelMessageId::Saved(id) = summary.max_id {
|
&& let ChannelMessageId::Saved(id) = summary.max_id
|
||||||
|
{
|
||||||
store.set_acknowledged_message_id(self.channel_id, Some(id));
|
store.set_acknowledged_message_id(self.channel_id, Some(id));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.emit(ChannelChatEvent::MessagesUpdated {
|
cx.emit(ChannelChatEvent::MessagesUpdated {
|
||||||
|
@ -673,7 +673,6 @@ impl ChannelChat {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn message_update(
|
fn message_update(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -262,13 +262,12 @@ impl ChannelStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status = status_receiver.next().fuse() => {
|
status = status_receiver.next().fuse() => {
|
||||||
if let Some(status) = status {
|
if let Some(status) = status
|
||||||
if status.is_connected() {
|
&& status.is_connected() {
|
||||||
this.update(cx, |this, _cx| {
|
this.update(cx, |this, _cx| {
|
||||||
this.initialize();
|
this.initialize();
|
||||||
}).ok();
|
}).ok();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_ = timer => {
|
_ = timer => {
|
||||||
|
@ -336,11 +335,11 @@ impl ChannelStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_open_channel_buffer(&self, channel_id: ChannelId, _cx: &App) -> bool {
|
pub fn has_open_channel_buffer(&self, channel_id: ChannelId, _cx: &App) -> bool {
|
||||||
if let Some(buffer) = self.opened_buffers.get(&channel_id) {
|
if let Some(buffer) = self.opened_buffers.get(&channel_id)
|
||||||
if let OpenEntityHandle::Open(buffer) = buffer {
|
&& let OpenEntityHandle::Open(buffer) = buffer
|
||||||
|
{
|
||||||
return buffer.upgrade().is_some();
|
return buffer.upgrade().is_some();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,14 +407,13 @@ impl ChannelStore {
|
||||||
|
|
||||||
pub fn last_acknowledge_message_id(&self, channel_id: ChannelId) -> Option<u64> {
|
pub fn last_acknowledge_message_id(&self, channel_id: ChannelId) -> Option<u64> {
|
||||||
self.channel_states.get(&channel_id).and_then(|state| {
|
self.channel_states.get(&channel_id).and_then(|state| {
|
||||||
if let Some(last_message_id) = state.latest_chat_message {
|
if let Some(last_message_id) = state.latest_chat_message
|
||||||
if state
|
&& state
|
||||||
.last_acknowledged_message_id()
|
.last_acknowledged_message_id()
|
||||||
.is_some_and(|id| id < last_message_id)
|
.is_some_and(|id| id < last_message_id)
|
||||||
{
|
{
|
||||||
return state.last_acknowledged_message_id();
|
return state.last_acknowledged_message_id();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
None
|
None
|
||||||
})
|
})
|
||||||
|
@ -962,19 +960,20 @@ impl ChannelStore {
|
||||||
self.disconnect_channel_buffers_task.take();
|
self.disconnect_channel_buffers_task.take();
|
||||||
|
|
||||||
for chat in self.opened_chats.values() {
|
for chat in self.opened_chats.values() {
|
||||||
if let OpenEntityHandle::Open(chat) = chat {
|
if let OpenEntityHandle::Open(chat) = chat
|
||||||
if let Some(chat) = chat.upgrade() {
|
&& let Some(chat) = chat.upgrade()
|
||||||
|
{
|
||||||
chat.update(cx, |chat, cx| {
|
chat.update(cx, |chat, cx| {
|
||||||
chat.rejoin(cx);
|
chat.rejoin(cx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut buffer_versions = Vec::new();
|
let mut buffer_versions = Vec::new();
|
||||||
for buffer in self.opened_buffers.values() {
|
for buffer in self.opened_buffers.values() {
|
||||||
if let OpenEntityHandle::Open(buffer) = buffer {
|
if let OpenEntityHandle::Open(buffer) = buffer
|
||||||
if let Some(buffer) = buffer.upgrade() {
|
&& let Some(buffer) = buffer.upgrade()
|
||||||
|
{
|
||||||
let channel_buffer = buffer.read(cx);
|
let channel_buffer = buffer.read(cx);
|
||||||
let buffer = channel_buffer.buffer().read(cx);
|
let buffer = channel_buffer.buffer().read(cx);
|
||||||
buffer_versions.push(proto::ChannelBufferVersion {
|
buffer_versions.push(proto::ChannelBufferVersion {
|
||||||
|
@ -984,7 +983,6 @@ impl ChannelStore {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if buffer_versions.is_empty() {
|
if buffer_versions.is_empty() {
|
||||||
return Task::ready(Ok(()));
|
return Task::ready(Ok(()));
|
||||||
|
@ -1078,12 +1076,12 @@ impl ChannelStore {
|
||||||
if let Some(this) = this.upgrade() {
|
if let Some(this) = this.upgrade() {
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
for (_, buffer) in &this.opened_buffers {
|
for (_, buffer) in &this.opened_buffers {
|
||||||
if let OpenEntityHandle::Open(buffer) = &buffer {
|
if let OpenEntityHandle::Open(buffer) = &buffer
|
||||||
if let Some(buffer) = buffer.upgrade() {
|
&& let Some(buffer) = buffer.upgrade()
|
||||||
|
{
|
||||||
buffer.update(cx, |buffer, cx| buffer.disconnect(cx));
|
buffer.update(cx, |buffer, cx| buffer.disconnect(cx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
@ -1157,27 +1155,25 @@ impl ChannelStore {
|
||||||
}
|
}
|
||||||
if let Some(OpenEntityHandle::Open(buffer)) =
|
if let Some(OpenEntityHandle::Open(buffer)) =
|
||||||
self.opened_buffers.remove(&channel_id)
|
self.opened_buffers.remove(&channel_id)
|
||||||
|
&& let Some(buffer) = buffer.upgrade()
|
||||||
{
|
{
|
||||||
if let Some(buffer) = buffer.upgrade() {
|
|
||||||
buffer.update(cx, ChannelBuffer::disconnect);
|
buffer.update(cx, ChannelBuffer::disconnect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut index = self.channel_index.bulk_insert();
|
let mut index = self.channel_index.bulk_insert();
|
||||||
for channel in payload.channels {
|
for channel in payload.channels {
|
||||||
let id = ChannelId(channel.id);
|
let id = ChannelId(channel.id);
|
||||||
let channel_changed = index.insert(channel);
|
let channel_changed = index.insert(channel);
|
||||||
|
|
||||||
if channel_changed {
|
if channel_changed
|
||||||
if let Some(OpenEntityHandle::Open(buffer)) = self.opened_buffers.get(&id) {
|
&& let Some(OpenEntityHandle::Open(buffer)) = self.opened_buffers.get(&id)
|
||||||
if let Some(buffer) = buffer.upgrade() {
|
&& let Some(buffer) = buffer.upgrade()
|
||||||
|
{
|
||||||
buffer.update(cx, ChannelBuffer::channel_changed);
|
buffer.update(cx, ChannelBuffer::channel_changed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for latest_buffer_version in payload.latest_channel_buffer_versions {
|
for latest_buffer_version in payload.latest_channel_buffer_versions {
|
||||||
let version = language::proto::deserialize_version(&latest_buffer_version.version);
|
let version = language::proto::deserialize_version(&latest_buffer_version.version);
|
||||||
|
|
|
@ -587,13 +587,10 @@ mod flatpak {
|
||||||
pub fn set_bin_if_no_escape(mut args: super::Args) -> super::Args {
|
pub fn set_bin_if_no_escape(mut args: super::Args) -> super::Args {
|
||||||
if env::var(NO_ESCAPE_ENV_NAME).is_ok()
|
if env::var(NO_ESCAPE_ENV_NAME).is_ok()
|
||||||
&& env::var("FLATPAK_ID").map_or(false, |id| id.starts_with("dev.zed.Zed"))
|
&& env::var("FLATPAK_ID").map_or(false, |id| id.starts_with("dev.zed.Zed"))
|
||||||
|
&& args.zed.is_none()
|
||||||
{
|
{
|
||||||
if args.zed.is_none() {
|
|
||||||
args.zed = Some("/app/libexec/zed-editor".into());
|
args.zed = Some("/app/libexec/zed-editor".into());
|
||||||
unsafe {
|
unsafe { env::set_var("ZED_UPDATE_EXPLANATION", "Please use flatpak to update zed") };
|
||||||
env::set_var("ZED_UPDATE_EXPLANATION", "Please use flatpak to update zed")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
args
|
args
|
||||||
}
|
}
|
||||||
|
|
|
@ -864,14 +864,16 @@ impl Client {
|
||||||
let mut credentials = None;
|
let mut credentials = None;
|
||||||
|
|
||||||
let old_credentials = self.state.read().credentials.clone();
|
let old_credentials = self.state.read().credentials.clone();
|
||||||
if let Some(old_credentials) = old_credentials {
|
if let Some(old_credentials) = old_credentials
|
||||||
if self.validate_credentials(&old_credentials, cx).await? {
|
&& self.validate_credentials(&old_credentials, cx).await?
|
||||||
|
{
|
||||||
credentials = Some(old_credentials);
|
credentials = Some(old_credentials);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if credentials.is_none() && try_provider {
|
if credentials.is_none()
|
||||||
if let Some(stored_credentials) = self.credentials_provider.read_credentials(cx).await {
|
&& try_provider
|
||||||
|
&& let Some(stored_credentials) = self.credentials_provider.read_credentials(cx).await
|
||||||
|
{
|
||||||
if self.validate_credentials(&stored_credentials, cx).await? {
|
if self.validate_credentials(&stored_credentials, cx).await? {
|
||||||
credentials = Some(stored_credentials);
|
credentials = Some(stored_credentials);
|
||||||
} else {
|
} else {
|
||||||
|
@ -881,7 +883,6 @@ impl Client {
|
||||||
.log_err();
|
.log_err();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if credentials.is_none() {
|
if credentials.is_none() {
|
||||||
let mut status_rx = self.status();
|
let mut status_rx = self.status();
|
||||||
|
|
|
@ -894,11 +894,11 @@ impl UserStore {
|
||||||
let mut ret = Vec::with_capacity(users.len());
|
let mut ret = Vec::with_capacity(users.len());
|
||||||
for user in users {
|
for user in users {
|
||||||
let user = User::new(user);
|
let user = User::new(user);
|
||||||
if let Some(old) = self.users.insert(user.id, user.clone()) {
|
if let Some(old) = self.users.insert(user.id, user.clone())
|
||||||
if old.github_login != user.github_login {
|
&& old.github_login != user.github_login
|
||||||
|
{
|
||||||
self.by_github_login.remove(&old.github_login);
|
self.by_github_login.remove(&old.github_login);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self.by_github_login
|
self.by_github_login
|
||||||
.insert(user.github_login.clone(), user.id);
|
.insert(user.github_login.clone(), user.id);
|
||||||
ret.push(user)
|
ret.push(user)
|
||||||
|
|
|
@ -149,8 +149,9 @@ pub async fn post_crash(
|
||||||
"crash report"
|
"crash report"
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(kinesis_client) = app.kinesis_client.clone() {
|
if let Some(kinesis_client) = app.kinesis_client.clone()
|
||||||
if let Some(stream) = app.config.kinesis_stream.clone() {
|
&& let Some(stream) = app.config.kinesis_stream.clone()
|
||||||
|
{
|
||||||
let properties = json!({
|
let properties = json!({
|
||||||
"app_version": report.header.app_version,
|
"app_version": report.header.app_version,
|
||||||
"os_version": report.header.os_version,
|
"os_version": report.header.os_version,
|
||||||
|
@ -178,7 +179,6 @@ pub async fn post_crash(
|
||||||
.await
|
.await
|
||||||
.log_err();
|
.log_err();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(slack_panics_webhook) = app.config.slack_panics_webhook.clone() {
|
if let Some(slack_panics_webhook) = app.config.slack_panics_webhook.clone() {
|
||||||
let payload = slack::WebhookBody::new(|w| {
|
let payload = slack::WebhookBody::new(|w| {
|
||||||
|
@ -359,8 +359,9 @@ pub async fn post_panic(
|
||||||
"panic report"
|
"panic report"
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(kinesis_client) = app.kinesis_client.clone() {
|
if let Some(kinesis_client) = app.kinesis_client.clone()
|
||||||
if let Some(stream) = app.config.kinesis_stream.clone() {
|
&& let Some(stream) = app.config.kinesis_stream.clone()
|
||||||
|
{
|
||||||
let properties = json!({
|
let properties = json!({
|
||||||
"app_version": panic.app_version,
|
"app_version": panic.app_version,
|
||||||
"os_name": panic.os_name,
|
"os_name": panic.os_name,
|
||||||
|
@ -387,7 +388,6 @@ pub async fn post_panic(
|
||||||
.await
|
.await
|
||||||
.log_err();
|
.log_err();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if !report_to_slack(&panic) {
|
if !report_to_slack(&panic) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -518,8 +518,9 @@ pub async fn post_events(
|
||||||
let first_event_at = chrono::Utc::now()
|
let first_event_at = chrono::Utc::now()
|
||||||
- chrono::Duration::milliseconds(last_event.milliseconds_since_first_event);
|
- chrono::Duration::milliseconds(last_event.milliseconds_since_first_event);
|
||||||
|
|
||||||
if let Some(kinesis_client) = app.kinesis_client.clone() {
|
if let Some(kinesis_client) = app.kinesis_client.clone()
|
||||||
if let Some(stream) = app.config.kinesis_stream.clone() {
|
&& let Some(stream) = app.config.kinesis_stream.clone()
|
||||||
|
{
|
||||||
let mut request = kinesis_client.put_records().stream_name(stream);
|
let mut request = kinesis_client.put_records().stream_name(stream);
|
||||||
let mut has_records = false;
|
let mut has_records = false;
|
||||||
for row in for_snowflake(
|
for row in for_snowflake(
|
||||||
|
@ -542,7 +543,6 @@ pub async fn post_events(
|
||||||
if has_records {
|
if has_records {
|
||||||
request.send().await.log_err();
|
request.send().await.log_err();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -337,8 +337,7 @@ async fn fetch_extensions_from_blob_store(
|
||||||
if known_versions
|
if known_versions
|
||||||
.binary_search_by_key(&published_version, |known_version| known_version)
|
.binary_search_by_key(&published_version, |known_version| known_version)
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
&& let Some(extension) = fetch_extension_manifest(
|
||||||
if let Some(extension) = fetch_extension_manifest(
|
|
||||||
blob_store_client,
|
blob_store_client,
|
||||||
blob_store_bucket,
|
blob_store_bucket,
|
||||||
extension_id,
|
extension_id,
|
||||||
|
@ -354,7 +353,6 @@ async fn fetch_extensions_from_blob_store(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
app_state
|
app_state
|
||||||
.db
|
.db
|
||||||
|
|
|
@ -79,8 +79,9 @@ pub async fn validate_header<B>(mut req: Request<B>, next: Next<B>) -> impl Into
|
||||||
verify_access_token(access_token, user_id, &state.db).await
|
verify_access_token(access_token, user_id, &state.db).await
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Ok(validate_result) = validate_result {
|
if let Ok(validate_result) = validate_result
|
||||||
if validate_result.is_valid {
|
&& validate_result.is_valid
|
||||||
|
{
|
||||||
let user = state
|
let user = state
|
||||||
.db
|
.db
|
||||||
.get_user_by_id(user_id)
|
.get_user_by_id(user_id)
|
||||||
|
@ -100,7 +101,6 @@ pub async fn validate_header<B>(mut req: Request<B>, next: Next<B>) -> impl Into
|
||||||
};
|
};
|
||||||
return Ok::<_, Error>(next.run(req).await);
|
return Ok::<_, Error>(next.run(req).await);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Err(Error::http(
|
Err(Error::http(
|
||||||
StatusCode::UNAUTHORIZED,
|
StatusCode::UNAUTHORIZED,
|
||||||
|
|
|
@ -87,11 +87,11 @@ impl Database {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((_, max_extension_version)) = &max_versions.get(&version.extension_id) {
|
if let Some((_, max_extension_version)) = &max_versions.get(&version.extension_id)
|
||||||
if max_extension_version > &extension_version {
|
&& max_extension_version > &extension_version
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(constraints) = constraints {
|
if let Some(constraints) = constraints {
|
||||||
if !constraints
|
if !constraints
|
||||||
|
@ -331,11 +331,11 @@ impl Database {
|
||||||
.exec_without_returning(&*tx)
|
.exec_without_returning(&*tx)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if let Ok(db_version) = semver::Version::parse(&extension.latest_version) {
|
if let Ok(db_version) = semver::Version::parse(&extension.latest_version)
|
||||||
if db_version >= latest_version.version {
|
&& db_version >= latest_version.version
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut extension = extension.into_active_model();
|
let mut extension = extension.into_active_model();
|
||||||
extension.latest_version = ActiveValue::Set(latest_version.version.to_string());
|
extension.latest_version = ActiveValue::Set(latest_version.version.to_string());
|
||||||
|
|
|
@ -1321,11 +1321,11 @@ impl Database {
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let mut connection_ids = HashSet::default();
|
let mut connection_ids = HashSet::default();
|
||||||
if let Some(host_connection) = project.host_connection().log_err() {
|
if let Some(host_connection) = project.host_connection().log_err()
|
||||||
if !exclude_dev_server {
|
&& !exclude_dev_server
|
||||||
|
{
|
||||||
connection_ids.insert(host_connection);
|
connection_ids.insert(host_connection);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
while let Some(collaborator) = collaborators.next().await {
|
while let Some(collaborator) = collaborators.next().await {
|
||||||
let collaborator = collaborator?;
|
let collaborator = collaborator?;
|
||||||
|
|
|
@ -616,13 +616,13 @@ impl Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(live_kit) = livekit_client.as_ref() {
|
if let Some(live_kit) = livekit_client.as_ref()
|
||||||
if delete_livekit_room {
|
&& delete_livekit_room
|
||||||
|
{
|
||||||
live_kit.delete_room(livekit_room).await.trace_err();
|
live_kit.delete_room(livekit_room).await.trace_err();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
app_state
|
app_state
|
||||||
.db
|
.db
|
||||||
|
@ -1015,8 +1015,9 @@ impl Server {
|
||||||
inviter_id: UserId,
|
inviter_id: UserId,
|
||||||
invitee_id: UserId,
|
invitee_id: UserId,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if let Some(user) = self.app_state.db.get_user_by_id(inviter_id).await? {
|
if let Some(user) = self.app_state.db.get_user_by_id(inviter_id).await?
|
||||||
if let Some(code) = &user.invite_code {
|
&& let Some(code) = &user.invite_code
|
||||||
|
{
|
||||||
let pool = self.connection_pool.lock();
|
let pool = self.connection_pool.lock();
|
||||||
let invitee_contact = contact_for_user(invitee_id, false, &pool);
|
let invitee_contact = contact_for_user(invitee_id, false, &pool);
|
||||||
for connection_id in pool.user_connection_ids(inviter_id) {
|
for connection_id in pool.user_connection_ids(inviter_id) {
|
||||||
|
@ -1036,13 +1037,13 @@ impl Server {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn invite_count_updated(self: &Arc<Self>, user_id: UserId) -> Result<()> {
|
pub async fn invite_count_updated(self: &Arc<Self>, user_id: UserId) -> Result<()> {
|
||||||
if let Some(user) = self.app_state.db.get_user_by_id(user_id).await? {
|
if let Some(user) = self.app_state.db.get_user_by_id(user_id).await?
|
||||||
if let Some(invite_code) = &user.invite_code {
|
&& let Some(invite_code) = &user.invite_code
|
||||||
|
{
|
||||||
let pool = self.connection_pool.lock();
|
let pool = self.connection_pool.lock();
|
||||||
for connection_id in pool.user_connection_ids(user_id) {
|
for connection_id in pool.user_connection_ids(user_id) {
|
||||||
self.peer.send(
|
self.peer.send(
|
||||||
|
@ -1057,7 +1058,6 @@ impl Server {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1101,12 +1101,12 @@ fn broadcast<F>(
|
||||||
F: FnMut(ConnectionId) -> anyhow::Result<()>,
|
F: FnMut(ConnectionId) -> anyhow::Result<()>,
|
||||||
{
|
{
|
||||||
for receiver_id in receiver_ids {
|
for receiver_id in receiver_ids {
|
||||||
if Some(receiver_id) != sender_id {
|
if Some(receiver_id) != sender_id
|
||||||
if let Err(error) = f(receiver_id) {
|
&& let Err(error) = f(receiver_id)
|
||||||
|
{
|
||||||
tracing::error!("failed to send to {:?} {}", receiver_id, error);
|
tracing::error!("failed to send to {:?} {}", receiver_id, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ProtocolVersion(u32);
|
pub struct ProtocolVersion(u32);
|
||||||
|
@ -2294,12 +2294,11 @@ async fn update_language_server(
|
||||||
let db = session.db().await;
|
let db = session.db().await;
|
||||||
|
|
||||||
if let Some(proto::update_language_server::Variant::MetadataUpdated(update)) = &request.variant
|
if let Some(proto::update_language_server::Variant::MetadataUpdated(update)) = &request.variant
|
||||||
|
&& let Some(capabilities) = update.capabilities.clone()
|
||||||
{
|
{
|
||||||
if let Some(capabilities) = update.capabilities.clone() {
|
|
||||||
db.update_server_capabilities(project_id, request.language_server_id, capabilities)
|
db.update_server_capabilities(project_id, request.language_server_id, capabilities)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let project_connection_ids = db
|
let project_connection_ids = db
|
||||||
.project_connection_ids(project_id, session.connection_id, true)
|
.project_connection_ids(project_id, session.connection_id, true)
|
||||||
|
|
|
@ -1162,8 +1162,8 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||||
Some((project, cx))
|
Some((project, cx))
|
||||||
});
|
});
|
||||||
|
|
||||||
if !guest_project.is_disconnected(cx) {
|
if !guest_project.is_disconnected(cx)
|
||||||
if let Some((host_project, host_cx)) = host_project {
|
&& let Some((host_project, host_cx)) = host_project {
|
||||||
let host_worktree_snapshots =
|
let host_worktree_snapshots =
|
||||||
host_project.read_with(host_cx, |host_project, cx| {
|
host_project.read_with(host_cx, |host_project, cx| {
|
||||||
host_project
|
host_project
|
||||||
|
@ -1235,7 +1235,6 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for buffer in guest_project.opened_buffers(cx) {
|
for buffer in guest_project.opened_buffers(cx) {
|
||||||
let buffer = buffer.read(cx);
|
let buffer = buffer.read(cx);
|
||||||
|
|
|
@ -198,12 +198,12 @@ pub async fn run_randomized_test<T: RandomizedTest>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_randomized_test_plan() {
|
pub fn save_randomized_test_plan() {
|
||||||
if let Some(serialize_plan) = LAST_PLAN.lock().take() {
|
if let Some(serialize_plan) = LAST_PLAN.lock().take()
|
||||||
if let Some(path) = plan_save_path() {
|
&& let Some(path) = plan_save_path()
|
||||||
|
{
|
||||||
eprintln!("saved test plan to path {:?}", path);
|
eprintln!("saved test plan to path {:?}", path);
|
||||||
std::fs::write(path, serialize_plan()).unwrap();
|
std::fs::write(path, serialize_plan()).unwrap();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RandomizedTest> TestPlan<T> {
|
impl<T: RandomizedTest> TestPlan<T> {
|
||||||
|
@ -290,11 +290,10 @@ impl<T: RandomizedTest> TestPlan<T> {
|
||||||
if let StoredOperation::Client {
|
if let StoredOperation::Client {
|
||||||
user_id, batch_id, ..
|
user_id, batch_id, ..
|
||||||
} = operation
|
} = operation
|
||||||
|
&& batch_id == current_batch_id
|
||||||
{
|
{
|
||||||
if batch_id == current_batch_id {
|
|
||||||
return Some(user_id);
|
return Some(user_id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}));
|
}));
|
||||||
user_ids.sort_unstable();
|
user_ids.sort_unstable();
|
||||||
|
@ -366,12 +365,11 @@ impl<T: RandomizedTest> TestPlan<T> {
|
||||||
},
|
},
|
||||||
applied,
|
applied,
|
||||||
) = stored_operation
|
) = stored_operation
|
||||||
|
&& user_id == ¤t_user_id
|
||||||
{
|
{
|
||||||
if user_id == ¤t_user_id {
|
|
||||||
return Some((operation.clone(), applied.clone()));
|
return Some((operation.clone(), applied.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
if self.operation_ix == self.max_operations {
|
if self.operation_ix == self.max_operations {
|
||||||
|
@ -550,14 +548,14 @@ impl<T: RandomizedTest> TestPlan<T> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let pool = server.connection_pool.lock();
|
let pool = server.connection_pool.lock();
|
||||||
for contact in contacts {
|
for contact in contacts {
|
||||||
if let db::Contact::Accepted { user_id, busy, .. } = contact {
|
if let db::Contact::Accepted { user_id, busy, .. } = contact
|
||||||
if user_id == removed_user_id {
|
&& user_id == removed_user_id
|
||||||
|
{
|
||||||
assert!(!pool.is_user_online(user_id));
|
assert!(!pool.is_user_online(user_id));
|
||||||
assert!(!busy);
|
assert!(!busy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
log::info!("{} removed", client.username);
|
log::info!("{} removed", client.username);
|
||||||
plan.lock().user(removed_user_id).online = false;
|
plan.lock().user(removed_user_id).online = false;
|
||||||
|
|
|
@ -130,8 +130,9 @@ impl UserBackfiller {
|
||||||
.and_then(|value| value.parse::<i64>().ok())
|
.and_then(|value| value.parse::<i64>().ok())
|
||||||
.and_then(|value| DateTime::from_timestamp(value, 0));
|
.and_then(|value| DateTime::from_timestamp(value, 0));
|
||||||
|
|
||||||
if rate_limit_remaining == Some(0) {
|
if rate_limit_remaining == Some(0)
|
||||||
if let Some(reset_at) = rate_limit_reset {
|
&& let Some(reset_at) = rate_limit_reset
|
||||||
|
{
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
if reset_at > now {
|
if reset_at > now {
|
||||||
let sleep_duration = reset_at - now;
|
let sleep_duration = reset_at - now;
|
||||||
|
@ -142,7 +143,6 @@ impl UserBackfiller {
|
||||||
self.executor.sleep(sleep_duration.to_std().unwrap()).await;
|
self.executor.sleep(sleep_duration.to_std().unwrap()).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
response
|
response
|
||||||
.error_for_status()
|
.error_for_status()
|
||||||
|
|
|
@ -107,33 +107,23 @@ impl ChannelView {
|
||||||
.find(|view| view.read(cx).channel_buffer.read(cx).remote_id(cx) == buffer_id);
|
.find(|view| view.read(cx).channel_buffer.read(cx).remote_id(cx) == buffer_id);
|
||||||
|
|
||||||
// If this channel buffer is already open in this pane, just return it.
|
// If this channel buffer is already open in this pane, just return it.
|
||||||
if let Some(existing_view) = existing_view.clone() {
|
if let Some(existing_view) = existing_view.clone()
|
||||||
if existing_view.read(cx).channel_buffer == channel_view.read(cx).channel_buffer
|
&& existing_view.read(cx).channel_buffer == channel_view.read(cx).channel_buffer
|
||||||
{
|
{
|
||||||
if let Some(link_position) = link_position {
|
if let Some(link_position) = link_position {
|
||||||
existing_view.update(cx, |channel_view, cx| {
|
existing_view.update(cx, |channel_view, cx| {
|
||||||
channel_view.focus_position_from_link(
|
channel_view.focus_position_from_link(link_position, true, window, cx)
|
||||||
link_position,
|
|
||||||
true,
|
|
||||||
window,
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return existing_view;
|
return existing_view;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If the pane contained a disconnected view for this channel buffer,
|
// If the pane contained a disconnected view for this channel buffer,
|
||||||
// replace that.
|
// replace that.
|
||||||
if let Some(existing_item) = existing_view {
|
if let Some(existing_item) = existing_view
|
||||||
if let Some(ix) = pane.index_for_item(&existing_item) {
|
&& let Some(ix) = pane.index_for_item(&existing_item)
|
||||||
pane.close_item_by_id(
|
{
|
||||||
existing_item.entity_id(),
|
pane.close_item_by_id(existing_item.entity_id(), SaveIntent::Skip, window, cx)
|
||||||
SaveIntent::Skip,
|
|
||||||
window,
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
.detach();
|
.detach();
|
||||||
pane.add_item(
|
pane.add_item(
|
||||||
Box::new(channel_view.clone()),
|
Box::new(channel_view.clone()),
|
||||||
|
@ -144,7 +134,6 @@ impl ChannelView {
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(link_position) = link_position {
|
if let Some(link_position) = link_position {
|
||||||
channel_view.update(cx, |channel_view, cx| {
|
channel_view.update(cx, |channel_view, cx| {
|
||||||
|
@ -259,8 +248,8 @@ impl ChannelView {
|
||||||
.editor
|
.editor
|
||||||
.update(cx, |editor, cx| editor.snapshot(window, cx));
|
.update(cx, |editor, cx| editor.snapshot(window, cx));
|
||||||
|
|
||||||
if let Some(outline) = snapshot.buffer_snapshot.outline(None) {
|
if let Some(outline) = snapshot.buffer_snapshot.outline(None)
|
||||||
if let Some(item) = outline
|
&& let Some(item) = outline
|
||||||
.items
|
.items
|
||||||
.iter()
|
.iter()
|
||||||
.find(|item| &Channel::slug(&item.text).to_lowercase() == &position)
|
.find(|item| &Channel::slug(&item.text).to_lowercase() == &position)
|
||||||
|
@ -270,16 +259,11 @@ impl ChannelView {
|
||||||
SelectionEffects::scroll(Autoscroll::focused()),
|
SelectionEffects::scroll(Autoscroll::focused()),
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
|s| {
|
|s| s.replace_cursors_with(|map| vec![item.range.start.to_display_point(map)]),
|
||||||
s.replace_cursors_with(|map| {
|
|
||||||
vec![item.range.start.to_display_point(map)]
|
|
||||||
})
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if !first_attempt {
|
if !first_attempt {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -287,8 +287,10 @@ impl ChatPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn acknowledge_last_message(&mut self, cx: &mut Context<Self>) {
|
fn acknowledge_last_message(&mut self, cx: &mut Context<Self>) {
|
||||||
if self.active && self.is_scrolled_to_bottom {
|
if self.active
|
||||||
if let Some((chat, _)) = &self.active_chat {
|
&& self.is_scrolled_to_bottom
|
||||||
|
&& let Some((chat, _)) = &self.active_chat
|
||||||
|
{
|
||||||
if let Some(channel_id) = self.channel_id(cx) {
|
if let Some(channel_id) = self.channel_id(cx) {
|
||||||
self.last_acknowledged_message_id = self
|
self.last_acknowledged_message_id = self
|
||||||
.channel_store
|
.channel_store
|
||||||
|
@ -301,7 +303,6 @@ impl ChatPanel {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn render_replied_to_message(
|
fn render_replied_to_message(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -405,15 +406,14 @@ impl ChatPanel {
|
||||||
&& last_message.id != this_message.id
|
&& last_message.id != this_message.id
|
||||||
&& duration_since_last_message < Duration::from_secs(5 * 60);
|
&& duration_since_last_message < Duration::from_secs(5 * 60);
|
||||||
|
|
||||||
if let ChannelMessageId::Saved(id) = this_message.id {
|
if let ChannelMessageId::Saved(id) = this_message.id
|
||||||
if this_message
|
&& this_message
|
||||||
.mentions
|
.mentions
|
||||||
.iter()
|
.iter()
|
||||||
.any(|(_, user_id)| Some(*user_id) == self.client.user_id())
|
.any(|(_, user_id)| Some(*user_id) == self.client.user_id())
|
||||||
{
|
{
|
||||||
active_chat.acknowledge_message(id);
|
active_chat.acknowledge_message(id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
(this_message, is_continuation_from_previous, is_admin)
|
(this_message, is_continuation_from_previous, is_admin)
|
||||||
});
|
});
|
||||||
|
@ -871,8 +871,8 @@ impl ChatPanel {
|
||||||
scroll_to_message_id.or(this.last_acknowledged_message_id)
|
scroll_to_message_id.or(this.last_acknowledged_message_id)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(message_id) = scroll_to_message_id {
|
if let Some(message_id) = scroll_to_message_id
|
||||||
if let Some(item_ix) =
|
&& let Some(item_ix) =
|
||||||
ChannelChat::load_history_since_message(chat.clone(), message_id, cx.clone())
|
ChannelChat::load_history_since_message(chat.clone(), message_id, cx.clone())
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
@ -899,7 +899,6 @@ impl ChatPanel {
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|
|
@ -241,8 +241,8 @@ impl MessageEditor {
|
||||||
) -> Task<Result<Vec<CompletionResponse>>> {
|
) -> Task<Result<Vec<CompletionResponse>>> {
|
||||||
if let Some((start_anchor, query, candidates)) =
|
if let Some((start_anchor, query, candidates)) =
|
||||||
self.collect_mention_candidates(buffer, end_anchor, cx)
|
self.collect_mention_candidates(buffer, end_anchor, cx)
|
||||||
|
&& !candidates.is_empty()
|
||||||
{
|
{
|
||||||
if !candidates.is_empty() {
|
|
||||||
return cx.spawn(async move |_, cx| {
|
return cx.spawn(async move |_, cx| {
|
||||||
let completion_response = Self::completions_for_candidates(
|
let completion_response = Self::completions_for_candidates(
|
||||||
cx,
|
cx,
|
||||||
|
@ -255,12 +255,11 @@ impl MessageEditor {
|
||||||
Ok(vec![completion_response])
|
Ok(vec![completion_response])
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((start_anchor, query, candidates)) =
|
if let Some((start_anchor, query, candidates)) =
|
||||||
self.collect_emoji_candidates(buffer, end_anchor, cx)
|
self.collect_emoji_candidates(buffer, end_anchor, cx)
|
||||||
|
&& !candidates.is_empty()
|
||||||
{
|
{
|
||||||
if !candidates.is_empty() {
|
|
||||||
return cx.spawn(async move |_, cx| {
|
return cx.spawn(async move |_, cx| {
|
||||||
let completion_response = Self::completions_for_candidates(
|
let completion_response = Self::completions_for_candidates(
|
||||||
cx,
|
cx,
|
||||||
|
@ -273,7 +272,6 @@ impl MessageEditor {
|
||||||
Ok(vec![completion_response])
|
Ok(vec![completion_response])
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Task::ready(Ok(vec![CompletionResponse {
|
Task::ready(Ok(vec![CompletionResponse {
|
||||||
completions: Vec::new(),
|
completions: Vec::new(),
|
||||||
|
@ -474,8 +472,8 @@ impl MessageEditor {
|
||||||
for range in ranges {
|
for range in ranges {
|
||||||
text.clear();
|
text.clear();
|
||||||
text.extend(buffer.text_for_range(range.clone()));
|
text.extend(buffer.text_for_range(range.clone()));
|
||||||
if let Some(username) = text.strip_prefix('@') {
|
if let Some(username) = text.strip_prefix('@')
|
||||||
if let Some(user) = this
|
&& let Some(user) = this
|
||||||
.user_store
|
.user_store
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.cached_user_by_github_login(username)
|
.cached_user_by_github_login(username)
|
||||||
|
@ -487,7 +485,6 @@ impl MessageEditor {
|
||||||
anchor_ranges.push(start..end);
|
anchor_ranges.push(start..end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
editor.clear_highlights::<Self>(cx);
|
editor.clear_highlights::<Self>(cx);
|
||||||
editor.highlight_text::<Self>(
|
editor.highlight_text::<Self>(
|
||||||
|
|
|
@ -311,11 +311,11 @@ impl CollabPanel {
|
||||||
window,
|
window,
|
||||||
|this: &mut Self, _, event, window, cx| {
|
|this: &mut Self, _, event, window, cx| {
|
||||||
if let editor::EditorEvent::Blurred = event {
|
if let editor::EditorEvent::Blurred = event {
|
||||||
if let Some(state) = &this.channel_editing_state {
|
if let Some(state) = &this.channel_editing_state
|
||||||
if state.pending_name().is_some() {
|
&& state.pending_name().is_some()
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
this.take_editing_state(window, cx);
|
this.take_editing_state(window, cx);
|
||||||
this.update_entries(false, cx);
|
this.update_entries(false, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
@ -491,12 +491,12 @@ impl CollabPanel {
|
||||||
if !self.collapsed_sections.contains(&Section::ActiveCall) {
|
if !self.collapsed_sections.contains(&Section::ActiveCall) {
|
||||||
let room = room.read(cx);
|
let room = room.read(cx);
|
||||||
|
|
||||||
if query.is_empty() {
|
if query.is_empty()
|
||||||
if let Some(channel_id) = room.channel_id() {
|
&& let Some(channel_id) = room.channel_id()
|
||||||
|
{
|
||||||
self.entries.push(ListEntry::ChannelNotes { channel_id });
|
self.entries.push(ListEntry::ChannelNotes { channel_id });
|
||||||
self.entries.push(ListEntry::ChannelChat { channel_id });
|
self.entries.push(ListEntry::ChannelChat { channel_id });
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Populate the active user.
|
// Populate the active user.
|
||||||
if let Some(user) = user_store.current_user() {
|
if let Some(user) = user_store.current_user() {
|
||||||
|
@ -639,11 +639,11 @@ impl CollabPanel {
|
||||||
&Default::default(),
|
&Default::default(),
|
||||||
executor.clone(),
|
executor.clone(),
|
||||||
));
|
));
|
||||||
if let Some(state) = &self.channel_editing_state {
|
if let Some(state) = &self.channel_editing_state
|
||||||
if matches!(state, ChannelEditingState::Create { location: None, .. }) {
|
&& matches!(state, ChannelEditingState::Create { location: None, .. })
|
||||||
|
{
|
||||||
self.entries.push(ListEntry::ChannelEditor { depth: 0 });
|
self.entries.push(ListEntry::ChannelEditor { depth: 0 });
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let mut collapse_depth = None;
|
let mut collapse_depth = None;
|
||||||
for mat in matches {
|
for mat in matches {
|
||||||
let channel = channel_store.channel_at_index(mat.candidate_id).unwrap();
|
let channel = channel_store.channel_at_index(mat.candidate_id).unwrap();
|
||||||
|
@ -1552,8 +1552,9 @@ impl CollabPanel {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(selection) = self.selection {
|
if let Some(selection) = self.selection
|
||||||
if let Some(entry) = self.entries.get(selection) {
|
&& let Some(entry) = self.entries.get(selection)
|
||||||
|
{
|
||||||
match entry {
|
match entry {
|
||||||
ListEntry::Header(section) => match section {
|
ListEntry::Header(section) => match section {
|
||||||
Section::ActiveCall => Self::leave_call(window, cx),
|
Section::ActiveCall => Self::leave_call(window, cx),
|
||||||
|
@ -1578,12 +1579,7 @@ impl CollabPanel {
|
||||||
} => {
|
} => {
|
||||||
if let Some(workspace) = self.workspace.upgrade() {
|
if let Some(workspace) = self.workspace.upgrade() {
|
||||||
let app_state = workspace.read(cx).app_state().clone();
|
let app_state = workspace.read(cx).app_state().clone();
|
||||||
workspace::join_in_room_project(
|
workspace::join_in_room_project(*project_id, *host_user_id, app_state, cx)
|
||||||
*project_id,
|
|
||||||
*host_user_id,
|
|
||||||
app_state,
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
.detach_and_prompt_err(
|
.detach_and_prompt_err(
|
||||||
"Failed to join project",
|
"Failed to join project",
|
||||||
window,
|
window,
|
||||||
|
@ -1646,7 +1642,6 @@ impl CollabPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn insert_space(&mut self, _: &InsertSpace, window: &mut Window, cx: &mut Context<Self>) {
|
fn insert_space(&mut self, _: &InsertSpace, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
if self.channel_editing_state.is_some() {
|
if self.channel_editing_state.is_some() {
|
||||||
|
|
|
@ -121,14 +121,13 @@ impl NotificationPanel {
|
||||||
let notification_list = ListState::new(0, ListAlignment::Top, px(1000.));
|
let notification_list = ListState::new(0, ListAlignment::Top, px(1000.));
|
||||||
notification_list.set_scroll_handler(cx.listener(
|
notification_list.set_scroll_handler(cx.listener(
|
||||||
|this, event: &ListScrollEvent, _, cx| {
|
|this, event: &ListScrollEvent, _, cx| {
|
||||||
if event.count.saturating_sub(event.visible_range.end) < LOADING_THRESHOLD {
|
if event.count.saturating_sub(event.visible_range.end) < LOADING_THRESHOLD
|
||||||
if let Some(task) = this
|
&& let Some(task) = this
|
||||||
.notification_store
|
.notification_store
|
||||||
.update(cx, |store, cx| store.load_more_notifications(false, cx))
|
.update(cx, |store, cx| store.load_more_notifications(false, cx))
|
||||||
{
|
{
|
||||||
task.detach();
|
task.detach();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -469,8 +468,8 @@ impl NotificationPanel {
|
||||||
channel_id,
|
channel_id,
|
||||||
..
|
..
|
||||||
} = notification.clone()
|
} = notification.clone()
|
||||||
|
&& let Some(workspace) = self.workspace.upgrade()
|
||||||
{
|
{
|
||||||
if let Some(workspace) = self.workspace.upgrade() {
|
|
||||||
window.defer(cx, move |window, cx| {
|
window.defer(cx, move |window, cx| {
|
||||||
workspace.update(cx, |workspace, cx| {
|
workspace.update(cx, |workspace, cx| {
|
||||||
if let Some(panel) = workspace.focus_panel::<ChatPanel>(window, cx) {
|
if let Some(panel) = workspace.focus_panel::<ChatPanel>(window, cx) {
|
||||||
|
@ -484,15 +483,15 @@ impl NotificationPanel {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn is_showing_notification(&self, notification: &Notification, cx: &mut Context<Self>) -> bool {
|
fn is_showing_notification(&self, notification: &Notification, cx: &mut Context<Self>) -> bool {
|
||||||
if !self.active {
|
if !self.active {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Notification::ChannelMessageMention { channel_id, .. } = ¬ification {
|
if let Notification::ChannelMessageMention { channel_id, .. } = ¬ification
|
||||||
if let Some(workspace) = self.workspace.upgrade() {
|
&& let Some(workspace) = self.workspace.upgrade()
|
||||||
|
{
|
||||||
return if let Some(panel) = workspace.read(cx).panel::<ChatPanel>(cx) {
|
return if let Some(panel) = workspace.read(cx).panel::<ChatPanel>(cx) {
|
||||||
let panel = panel.read(cx);
|
let panel = panel.read(cx);
|
||||||
panel.is_scrolled_to_bottom()
|
panel.is_scrolled_to_bottom()
|
||||||
|
@ -503,7 +502,6 @@ impl NotificationPanel {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -582,8 +580,9 @@ impl NotificationPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_toast(&mut self, notification_id: u64, cx: &mut Context<Self>) {
|
fn remove_toast(&mut self, notification_id: u64, cx: &mut Context<Self>) {
|
||||||
if let Some((current_id, _)) = &self.current_notification_toast {
|
if let Some((current_id, _)) = &self.current_notification_toast
|
||||||
if *current_id == notification_id {
|
&& *current_id == notification_id
|
||||||
|
{
|
||||||
self.current_notification_toast.take();
|
self.current_notification_toast.take();
|
||||||
self.workspace
|
self.workspace
|
||||||
.update(cx, |workspace, cx| {
|
.update(cx, |workspace, cx| {
|
||||||
|
@ -593,7 +592,6 @@ impl NotificationPanel {
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn respond_to_notification(
|
fn respond_to_notification(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -271,11 +271,11 @@ impl Client {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if let Ok(response) = serde_json::from_str::<AnyResponse>(&message) {
|
} else if let Ok(response) = serde_json::from_str::<AnyResponse>(&message) {
|
||||||
if let Some(handlers) = response_handlers.lock().as_mut() {
|
if let Some(handlers) = response_handlers.lock().as_mut()
|
||||||
if let Some(handler) = handlers.remove(&response.id) {
|
&& let Some(handler) = handlers.remove(&response.id)
|
||||||
|
{
|
||||||
handler(Ok(message.to_string()));
|
handler(Ok(message.to_string()));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else if let Ok(notification) = serde_json::from_str::<AnyNotification>(&message) {
|
} else if let Ok(notification) = serde_json::from_str::<AnyNotification>(&message) {
|
||||||
let mut notification_handlers = notification_handlers.lock();
|
let mut notification_handlers = notification_handlers.lock();
|
||||||
if let Some(handler) = notification_handlers.get_mut(notification.method.as_str()) {
|
if let Some(handler) = notification_handlers.get_mut(notification.method.as_str()) {
|
||||||
|
|
|
@ -608,8 +608,7 @@ impl Copilot {
|
||||||
sign_in_status: status,
|
sign_in_status: status,
|
||||||
..
|
..
|
||||||
}) = &mut this.server
|
}) = &mut this.server
|
||||||
{
|
&& let SignInStatus::SigningIn {
|
||||||
if let SignInStatus::SigningIn {
|
|
||||||
prompt: prompt_flow,
|
prompt: prompt_flow,
|
||||||
..
|
..
|
||||||
} = status
|
} = status
|
||||||
|
@ -617,7 +616,6 @@ impl Copilot {
|
||||||
*prompt_flow = Some(flow.clone());
|
*prompt_flow = Some(flow.clone());
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})?;
|
})?;
|
||||||
let response = lsp
|
let response = lsp
|
||||||
.request::<request::SignInConfirm>(
|
.request::<request::SignInConfirm>(
|
||||||
|
@ -782,8 +780,8 @@ impl Copilot {
|
||||||
event: &language::BufferEvent,
|
event: &language::BufferEvent,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if let Ok(server) = self.server.as_running() {
|
if let Ok(server) = self.server.as_running()
|
||||||
if let Some(registered_buffer) = server.registered_buffers.get_mut(&buffer.entity_id())
|
&& let Some(registered_buffer) = server.registered_buffers.get_mut(&buffer.entity_id())
|
||||||
{
|
{
|
||||||
match event {
|
match event {
|
||||||
language::BufferEvent::Edited => {
|
language::BufferEvent::Edited => {
|
||||||
|
@ -836,14 +834,14 @@ impl Copilot {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unregister_buffer(&mut self, buffer: &WeakEntity<Buffer>) {
|
fn unregister_buffer(&mut self, buffer: &WeakEntity<Buffer>) {
|
||||||
if let Ok(server) = self.server.as_running() {
|
if let Ok(server) = self.server.as_running()
|
||||||
if let Some(buffer) = server.registered_buffers.remove(&buffer.entity_id()) {
|
&& let Some(buffer) = server.registered_buffers.remove(&buffer.entity_id())
|
||||||
|
{
|
||||||
server
|
server
|
||||||
.lsp
|
.lsp
|
||||||
.notify::<lsp::notification::DidCloseTextDocument>(
|
.notify::<lsp::notification::DidCloseTextDocument>(
|
||||||
|
@ -854,7 +852,6 @@ impl Copilot {
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn completions<T>(
|
pub fn completions<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -99,11 +99,11 @@ impl JsDebugAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(env) = configuration.get("env").cloned() {
|
if let Some(env) = configuration.get("env").cloned()
|
||||||
if let Ok(env) = serde_json::from_value(env) {
|
&& let Ok(env) = serde_json::from_value(env)
|
||||||
|
{
|
||||||
envs = env;
|
envs = env;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
configuration
|
configuration
|
||||||
.entry("cwd")
|
.entry("cwd")
|
||||||
|
|
|
@ -661,12 +661,12 @@ impl ToolbarItemView for DapLogToolbarItemView {
|
||||||
_window: &mut Window,
|
_window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> workspace::ToolbarItemLocation {
|
) -> workspace::ToolbarItemLocation {
|
||||||
if let Some(item) = active_pane_item {
|
if let Some(item) = active_pane_item
|
||||||
if let Some(log_view) = item.downcast::<DapLogView>() {
|
&& let Some(log_view) = item.downcast::<DapLogView>()
|
||||||
|
{
|
||||||
self.log_view = Some(log_view.clone());
|
self.log_view = Some(log_view.clone());
|
||||||
return workspace::ToolbarItemLocation::PrimaryLeft;
|
return workspace::ToolbarItemLocation::PrimaryLeft;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self.log_view = None;
|
self.log_view = None;
|
||||||
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
|
|
@ -530,11 +530,10 @@ impl DebugPanel {
|
||||||
.active_session
|
.active_session
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|session| session.entity_id())
|
.map(|session| session.entity_id())
|
||||||
|
&& active_session_id == entity_id
|
||||||
{
|
{
|
||||||
if active_session_id == entity_id {
|
|
||||||
this.active_session = this.sessions_with_children.keys().next().cloned();
|
this.active_session = this.sessions_with_children.keys().next().cloned();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
cx.notify()
|
cx.notify()
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
@ -1302,11 +1301,11 @@ impl DebugPanel {
|
||||||
cx: &mut Context<'_, Self>,
|
cx: &mut Context<'_, Self>,
|
||||||
) -> Option<SharedString> {
|
) -> Option<SharedString> {
|
||||||
let adapter = parent_session.read(cx).adapter();
|
let adapter = parent_session.read(cx).adapter();
|
||||||
if let Some(adapter) = DapRegistry::global(cx).adapter(&adapter) {
|
if let Some(adapter) = DapRegistry::global(cx).adapter(&adapter)
|
||||||
if let Some(label) = adapter.label_for_child_session(request) {
|
&& let Some(label) = adapter.label_for_child_session(request)
|
||||||
|
{
|
||||||
return Some(label.into());
|
return Some(label.into());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -343,11 +343,11 @@ impl NewProcessModal {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let NewProcessMode::Launch = &self.mode {
|
if let NewProcessMode::Launch = &self.mode
|
||||||
if self.configure_mode.read(cx).save_to_debug_json.selected() {
|
&& self.configure_mode.read(cx).save_to_debug_json.selected()
|
||||||
|
{
|
||||||
self.save_debug_scenario(window, cx);
|
self.save_debug_scenario(window, cx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let Some(debugger) = self.debugger.clone() else {
|
let Some(debugger) = self.debugger.clone() else {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -239,12 +239,10 @@ impl BreakpointList {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_next(&mut self, _: &menu::SelectNext, window: &mut Window, cx: &mut Context<Self>) {
|
fn select_next(&mut self, _: &menu::SelectNext, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
if self.strip_mode.is_some() {
|
if self.strip_mode.is_some() && self.input.focus_handle(cx).contains_focused(window, cx) {
|
||||||
if self.input.focus_handle(cx).contains_focused(window, cx) {
|
|
||||||
cx.propagate();
|
cx.propagate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let ix = match self.selected_ix {
|
let ix = match self.selected_ix {
|
||||||
_ if self.breakpoints.len() == 0 => None,
|
_ if self.breakpoints.len() == 0 => None,
|
||||||
None => Some(0),
|
None => Some(0),
|
||||||
|
@ -265,12 +263,10 @@ impl BreakpointList {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
if self.strip_mode.is_some() {
|
if self.strip_mode.is_some() && self.input.focus_handle(cx).contains_focused(window, cx) {
|
||||||
if self.input.focus_handle(cx).contains_focused(window, cx) {
|
|
||||||
cx.propagate();
|
cx.propagate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let ix = match self.selected_ix {
|
let ix = match self.selected_ix {
|
||||||
_ if self.breakpoints.len() == 0 => None,
|
_ if self.breakpoints.len() == 0 => None,
|
||||||
None => Some(self.breakpoints.len() - 1),
|
None => Some(self.breakpoints.len() - 1),
|
||||||
|
@ -286,12 +282,10 @@ impl BreakpointList {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_first(&mut self, _: &menu::SelectFirst, window: &mut Window, cx: &mut Context<Self>) {
|
fn select_first(&mut self, _: &menu::SelectFirst, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
if self.strip_mode.is_some() {
|
if self.strip_mode.is_some() && self.input.focus_handle(cx).contains_focused(window, cx) {
|
||||||
if self.input.focus_handle(cx).contains_focused(window, cx) {
|
|
||||||
cx.propagate();
|
cx.propagate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let ix = if self.breakpoints.len() > 0 {
|
let ix = if self.breakpoints.len() > 0 {
|
||||||
Some(0)
|
Some(0)
|
||||||
} else {
|
} else {
|
||||||
|
@ -301,12 +295,10 @@ impl BreakpointList {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_last(&mut self, _: &menu::SelectLast, window: &mut Window, cx: &mut Context<Self>) {
|
fn select_last(&mut self, _: &menu::SelectLast, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
if self.strip_mode.is_some() {
|
if self.strip_mode.is_some() && self.input.focus_handle(cx).contains_focused(window, cx) {
|
||||||
if self.input.focus_handle(cx).contains_focused(window, cx) {
|
|
||||||
cx.propagate();
|
cx.propagate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let ix = if self.breakpoints.len() > 0 {
|
let ix = if self.breakpoints.len() > 0 {
|
||||||
Some(self.breakpoints.len() - 1)
|
Some(self.breakpoints.len() - 1)
|
||||||
} else {
|
} else {
|
||||||
|
@ -401,12 +393,10 @@ impl BreakpointList {
|
||||||
let Some(entry) = self.selected_ix.and_then(|ix| self.breakpoints.get_mut(ix)) else {
|
let Some(entry) = self.selected_ix.and_then(|ix| self.breakpoints.get_mut(ix)) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if self.strip_mode.is_some() {
|
if self.strip_mode.is_some() && self.input.focus_handle(cx).contains_focused(window, cx) {
|
||||||
if self.input.focus_handle(cx).contains_focused(window, cx) {
|
|
||||||
cx.propagate();
|
cx.propagate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
match &mut entry.kind {
|
match &mut entry.kind {
|
||||||
BreakpointEntryKind::LineBreakpoint(line_breakpoint) => {
|
BreakpointEntryKind::LineBreakpoint(line_breakpoint) => {
|
||||||
|
|
|
@ -611,8 +611,8 @@ impl ConsoleQueryBarCompletionProvider {
|
||||||
for variable in console.variable_list.update(cx, |variable_list, cx| {
|
for variable in console.variable_list.update(cx, |variable_list, cx| {
|
||||||
variable_list.completion_variables(cx)
|
variable_list.completion_variables(cx)
|
||||||
}) {
|
}) {
|
||||||
if let Some(evaluate_name) = &variable.evaluate_name {
|
if let Some(evaluate_name) = &variable.evaluate_name
|
||||||
if variables
|
&& variables
|
||||||
.insert(evaluate_name.clone(), variable.value.clone())
|
.insert(evaluate_name.clone(), variable.value.clone())
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
|
@ -622,7 +622,6 @@ impl ConsoleQueryBarCompletionProvider {
|
||||||
char_bag: evaluate_name.chars().collect(),
|
char_bag: evaluate_name.chars().collect(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if variables
|
if variables
|
||||||
.insert(variable.name.clone(), variable.value.clone())
|
.insert(variable.name.clone(), variable.value.clone())
|
||||||
|
|
|
@ -639,8 +639,7 @@ impl ProjectDiagnosticsEditor {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
let cloned_blocks = blocks.clone();
|
let cloned_blocks = blocks.clone();
|
||||||
|
|
||||||
if was_empty {
|
if was_empty && let Some(anchor_range) = anchor_ranges.first() {
|
||||||
if let Some(anchor_range) = anchor_ranges.first() {
|
|
||||||
let range_to_select = anchor_range.start..anchor_range.start;
|
let range_to_select = anchor_range.start..anchor_range.start;
|
||||||
this.editor.update(cx, |editor, cx| {
|
this.editor.update(cx, |editor, cx| {
|
||||||
editor.change_selections(Default::default(), window, cx, |s| {
|
editor.change_selections(Default::default(), window, cx, |s| {
|
||||||
|
@ -651,7 +650,6 @@ impl ProjectDiagnosticsEditor {
|
||||||
this.editor.read(cx).focus_handle(cx).focus(window);
|
this.editor.read(cx).focus_handle(cx).focus(window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let editor_blocks =
|
let editor_blocks =
|
||||||
anchor_ranges
|
anchor_ranges
|
||||||
|
@ -980,8 +978,7 @@ async fn heuristic_syntactic_expand(
|
||||||
// Remove blank lines from start and end
|
// Remove blank lines from start and end
|
||||||
if let Some(start_row) = (outline_range.start.row..outline_range.end.row)
|
if let Some(start_row) = (outline_range.start.row..outline_range.end.row)
|
||||||
.find(|row| !snapshot.line_indent_for_row(*row).is_line_blank())
|
.find(|row| !snapshot.line_indent_for_row(*row).is_line_blank())
|
||||||
{
|
&& let Some(end_row) = (outline_range.start.row..outline_range.end.row + 1)
|
||||||
if let Some(end_row) = (outline_range.start.row..outline_range.end.row + 1)
|
|
||||||
.rev()
|
.rev()
|
||||||
.find(|row| !snapshot.line_indent_for_row(*row).is_line_blank())
|
.find(|row| !snapshot.line_indent_for_row(*row).is_line_blank())
|
||||||
{
|
{
|
||||||
|
@ -994,7 +991,6 @@ async fn heuristic_syntactic_expand(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut node = snapshot.syntax_ancestor(input_range.clone())?;
|
let mut node = snapshot.syntax_ancestor(input_range.clone())?;
|
||||||
|
|
||||||
|
|
|
@ -969,15 +969,15 @@ impl DisplaySnapshot {
|
||||||
if let Some(chunk_highlight) = chunk.highlight_style {
|
if let Some(chunk_highlight) = chunk.highlight_style {
|
||||||
// For color inlays, blend the color with the editor background
|
// For color inlays, blend the color with the editor background
|
||||||
let mut processed_highlight = chunk_highlight;
|
let mut processed_highlight = chunk_highlight;
|
||||||
if chunk.is_inlay {
|
if chunk.is_inlay
|
||||||
if let Some(inlay_color) = chunk_highlight.color {
|
&& let Some(inlay_color) = chunk_highlight.color
|
||||||
|
{
|
||||||
// Only blend if the color has transparency (alpha < 1.0)
|
// Only blend if the color has transparency (alpha < 1.0)
|
||||||
if inlay_color.a < 1.0 {
|
if inlay_color.a < 1.0 {
|
||||||
let blended_color = editor_style.background.blend(inlay_color);
|
let blended_color = editor_style.background.blend(inlay_color);
|
||||||
processed_highlight.color = Some(blended_color);
|
processed_highlight.color = Some(blended_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(highlight_style) = highlight_style.as_mut() {
|
if let Some(highlight_style) = highlight_style.as_mut() {
|
||||||
highlight_style.highlight(processed_highlight);
|
highlight_style.highlight(processed_highlight);
|
||||||
|
@ -2351,12 +2351,13 @@ pub mod tests {
|
||||||
.highlight_style
|
.highlight_style
|
||||||
.and_then(|style| style.color)
|
.and_then(|style| style.color)
|
||||||
.map_or(black, |color| color.to_rgb());
|
.map_or(black, |color| color.to_rgb());
|
||||||
if let Some((last_chunk, last_severity, last_color)) = chunks.last_mut() {
|
if let Some((last_chunk, last_severity, last_color)) = chunks.last_mut()
|
||||||
if *last_severity == chunk.diagnostic_severity && *last_color == color {
|
&& *last_severity == chunk.diagnostic_severity
|
||||||
|
&& *last_color == color
|
||||||
|
{
|
||||||
last_chunk.push_str(chunk.text);
|
last_chunk.push_str(chunk.text);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
chunks.push((chunk.text.to_string(), chunk.diagnostic_severity, color));
|
chunks.push((chunk.text.to_string(), chunk.diagnostic_severity, color));
|
||||||
}
|
}
|
||||||
|
@ -2901,12 +2902,13 @@ pub mod tests {
|
||||||
.syntax_highlight_id
|
.syntax_highlight_id
|
||||||
.and_then(|id| id.style(theme)?.color);
|
.and_then(|id| id.style(theme)?.color);
|
||||||
let highlight_color = chunk.highlight_style.and_then(|style| style.color);
|
let highlight_color = chunk.highlight_style.and_then(|style| style.color);
|
||||||
if let Some((last_chunk, last_syntax_color, last_highlight_color)) = chunks.last_mut() {
|
if let Some((last_chunk, last_syntax_color, last_highlight_color)) = chunks.last_mut()
|
||||||
if syntax_color == *last_syntax_color && highlight_color == *last_highlight_color {
|
&& syntax_color == *last_syntax_color
|
||||||
|
&& highlight_color == *last_highlight_color
|
||||||
|
{
|
||||||
last_chunk.push_str(chunk.text);
|
last_chunk.push_str(chunk.text);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
chunks.push((chunk.text.to_string(), syntax_color, highlight_color));
|
chunks.push((chunk.text.to_string(), syntax_color, highlight_color));
|
||||||
}
|
}
|
||||||
chunks
|
chunks
|
||||||
|
|
|
@ -525,8 +525,8 @@ impl BlockMap {
|
||||||
// * Below blocks that end at the start of the edit
|
// * Below blocks that end at the start of the edit
|
||||||
// However, if we hit a replace block that ends at the start of the edit we want to reconstruct it.
|
// However, if we hit a replace block that ends at the start of the edit we want to reconstruct it.
|
||||||
new_transforms.append(cursor.slice(&old_start, Bias::Left), &());
|
new_transforms.append(cursor.slice(&old_start, Bias::Left), &());
|
||||||
if let Some(transform) = cursor.item() {
|
if let Some(transform) = cursor.item()
|
||||||
if transform.summary.input_rows > 0
|
&& transform.summary.input_rows > 0
|
||||||
&& cursor.end() == old_start
|
&& cursor.end() == old_start
|
||||||
&& transform
|
&& transform
|
||||||
.block
|
.block
|
||||||
|
@ -547,7 +547,6 @@ impl BlockMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the edit starts at a transform boundary.
|
// Ensure the edit starts at a transform boundary.
|
||||||
// If the edit starts within an isomorphic transform, preserve its prefix
|
// If the edit starts within an isomorphic transform, preserve its prefix
|
||||||
|
@ -657,11 +656,11 @@ impl BlockMap {
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|block| {
|
.filter_map(|block| {
|
||||||
let placement = block.placement.to_wrap_row(wrap_snapshot)?;
|
let placement = block.placement.to_wrap_row(wrap_snapshot)?;
|
||||||
if let BlockPlacement::Above(row) = placement {
|
if let BlockPlacement::Above(row) = placement
|
||||||
if row < new_start {
|
&& row < new_start
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Some((placement, Block::Custom(block.clone())))
|
Some((placement, Block::Custom(block.clone())))
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -977,11 +976,11 @@ impl BlockMapReader<'_> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(BlockId::Custom(id)) = transform.block.as_ref().map(|block| block.id()) {
|
if let Some(BlockId::Custom(id)) = transform.block.as_ref().map(|block| block.id())
|
||||||
if id == block_id {
|
&& id == block_id
|
||||||
|
{
|
||||||
return Some(cursor.start().1);
|
return Some(cursor.start().1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
cursor.next();
|
cursor.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1299,15 +1298,15 @@ impl BlockSnapshot {
|
||||||
|
|
||||||
let mut input_start = transform_input_start;
|
let mut input_start = transform_input_start;
|
||||||
let mut input_end = transform_input_start;
|
let mut input_end = transform_input_start;
|
||||||
if let Some(transform) = cursor.item() {
|
if let Some(transform) = cursor.item()
|
||||||
if transform.block.is_none() {
|
&& transform.block.is_none()
|
||||||
|
{
|
||||||
input_start += rows.start - transform_output_start;
|
input_start += rows.start - transform_output_start;
|
||||||
input_end += cmp::min(
|
input_end += cmp::min(
|
||||||
rows.end - transform_output_start,
|
rows.end - transform_output_start,
|
||||||
transform.summary.input_rows,
|
transform.summary.input_rows,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
BlockChunks {
|
BlockChunks {
|
||||||
input_chunks: self.wrap_snapshot.chunks(
|
input_chunks: self.wrap_snapshot.chunks(
|
||||||
|
@ -1472,8 +1471,9 @@ impl BlockSnapshot {
|
||||||
longest_row_chars = summary.longest_row_chars;
|
longest_row_chars = summary.longest_row_chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(transform) = cursor.item() {
|
if let Some(transform) = cursor.item()
|
||||||
if transform.block.is_none() {
|
&& transform.block.is_none()
|
||||||
|
{
|
||||||
let Dimensions(output_start, input_start, _) = cursor.start();
|
let Dimensions(output_start, input_start, _) = cursor.start();
|
||||||
let overshoot = range.end.0 - output_start.0;
|
let overshoot = range.end.0 - output_start.0;
|
||||||
let wrap_start_row = input_start.0;
|
let wrap_start_row = input_start.0;
|
||||||
|
@ -1486,7 +1486,6 @@ impl BlockSnapshot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
longest_row
|
longest_row
|
||||||
}
|
}
|
||||||
|
@ -1557,14 +1556,13 @@ impl BlockSnapshot {
|
||||||
|
|
||||||
match transform.block.as_ref() {
|
match transform.block.as_ref() {
|
||||||
Some(block) => {
|
Some(block) => {
|
||||||
if block.is_replacement() {
|
if block.is_replacement()
|
||||||
if ((bias == Bias::Left || search_left) && output_start <= point.0)
|
&& (((bias == Bias::Left || search_left) && output_start <= point.0)
|
||||||
|| (!search_left && output_start >= point.0)
|
|| (!search_left && output_start >= point.0))
|
||||||
{
|
{
|
||||||
return BlockPoint(output_start);
|
return BlockPoint(output_start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
let input_point = if point.row >= output_end_row.0 {
|
let input_point = if point.row >= output_end_row.0 {
|
||||||
let line_len = self.wrap_snapshot.line_len(input_end_row.0 - 1);
|
let line_len = self.wrap_snapshot.line_len(input_end_row.0 - 1);
|
||||||
|
@ -3228,16 +3226,15 @@ mod tests {
|
||||||
let mut is_in_replace_block = false;
|
let mut is_in_replace_block = false;
|
||||||
if let Some((BlockPlacement::Replace(replace_range), block)) =
|
if let Some((BlockPlacement::Replace(replace_range), block)) =
|
||||||
sorted_blocks_iter.peek()
|
sorted_blocks_iter.peek()
|
||||||
|
&& wrap_row >= replace_range.start().0
|
||||||
{
|
{
|
||||||
if wrap_row >= replace_range.start().0 {
|
|
||||||
is_in_replace_block = true;
|
is_in_replace_block = true;
|
||||||
|
|
||||||
if wrap_row == replace_range.start().0 {
|
if wrap_row == replace_range.start().0 {
|
||||||
if matches!(block, Block::FoldedBuffer { .. }) {
|
if matches!(block, Block::FoldedBuffer { .. }) {
|
||||||
expected_buffer_rows.push(None);
|
expected_buffer_rows.push(None);
|
||||||
} else {
|
} else {
|
||||||
expected_buffer_rows
|
expected_buffer_rows.push(input_buffer_rows[multibuffer_row as usize]);
|
||||||
.push(input_buffer_rows[multibuffer_row as usize]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3257,7 +3254,6 @@ mod tests {
|
||||||
sorted_blocks_iter.next();
|
sorted_blocks_iter.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if is_in_replace_block {
|
if is_in_replace_block {
|
||||||
expected_replaced_buffer_rows.insert(MultiBufferRow(multibuffer_row));
|
expected_replaced_buffer_rows.insert(MultiBufferRow(multibuffer_row));
|
||||||
|
|
|
@ -289,8 +289,9 @@ impl FoldMapWriter<'_> {
|
||||||
let ChunkRendererId::Fold(id) = id else {
|
let ChunkRendererId::Fold(id) = id else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if let Some(metadata) = self.0.snapshot.fold_metadata_by_id.get(&id).cloned() {
|
if let Some(metadata) = self.0.snapshot.fold_metadata_by_id.get(&id).cloned()
|
||||||
if Some(new_width) != metadata.width {
|
&& Some(new_width) != metadata.width
|
||||||
|
{
|
||||||
let buffer_start = metadata.range.start.to_offset(buffer);
|
let buffer_start = metadata.range.start.to_offset(buffer);
|
||||||
let buffer_end = metadata.range.end.to_offset(buffer);
|
let buffer_end = metadata.range.end.to_offset(buffer);
|
||||||
let inlay_range = inlay_snapshot.to_inlay_offset(buffer_start)
|
let inlay_range = inlay_snapshot.to_inlay_offset(buffer_start)
|
||||||
|
@ -309,7 +310,6 @@ impl FoldMapWriter<'_> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let edits = consolidate_inlay_edits(edits);
|
let edits = consolidate_inlay_edits(edits);
|
||||||
let edits = self.0.sync(inlay_snapshot, edits);
|
let edits = self.0.sync(inlay_snapshot, edits);
|
||||||
|
@ -417,8 +417,9 @@ impl FoldMap {
|
||||||
cursor.seek(&InlayOffset(0), Bias::Right);
|
cursor.seek(&InlayOffset(0), Bias::Right);
|
||||||
|
|
||||||
while let Some(mut edit) = inlay_edits_iter.next() {
|
while let Some(mut edit) = inlay_edits_iter.next() {
|
||||||
if let Some(item) = cursor.item() {
|
if let Some(item) = cursor.item()
|
||||||
if !item.is_fold() {
|
&& !item.is_fold()
|
||||||
|
{
|
||||||
new_transforms.update_last(
|
new_transforms.update_last(
|
||||||
|transform| {
|
|transform| {
|
||||||
if !transform.is_fold() {
|
if !transform.is_fold() {
|
||||||
|
@ -429,7 +430,6 @@ impl FoldMap {
|
||||||
&(),
|
&(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
new_transforms.append(cursor.slice(&edit.old.start, Bias::Left), &());
|
new_transforms.append(cursor.slice(&edit.old.start, Bias::Left), &());
|
||||||
edit.new.start -= edit.old.start - *cursor.start();
|
edit.new.start -= edit.old.start - *cursor.start();
|
||||||
edit.old.start = *cursor.start();
|
edit.old.start = *cursor.start();
|
||||||
|
|
|
@ -557,12 +557,12 @@ impl InlayMap {
|
||||||
let mut buffer_edits_iter = buffer_edits.iter().peekable();
|
let mut buffer_edits_iter = buffer_edits.iter().peekable();
|
||||||
while let Some(buffer_edit) = buffer_edits_iter.next() {
|
while let Some(buffer_edit) = buffer_edits_iter.next() {
|
||||||
new_transforms.append(cursor.slice(&buffer_edit.old.start, Bias::Left), &());
|
new_transforms.append(cursor.slice(&buffer_edit.old.start, Bias::Left), &());
|
||||||
if let Some(Transform::Isomorphic(transform)) = cursor.item() {
|
if let Some(Transform::Isomorphic(transform)) = cursor.item()
|
||||||
if cursor.end().0 == buffer_edit.old.start {
|
&& cursor.end().0 == buffer_edit.old.start
|
||||||
|
{
|
||||||
push_isomorphic(&mut new_transforms, *transform);
|
push_isomorphic(&mut new_transforms, *transform);
|
||||||
cursor.next();
|
cursor.next();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Remove all the inlays and transforms contained by the edit.
|
// Remove all the inlays and transforms contained by the edit.
|
||||||
let old_start =
|
let old_start =
|
||||||
|
|
|
@ -249,8 +249,9 @@ impl WrapMap {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(wrap_width) = self.wrap_width {
|
if let Some(wrap_width) = self.wrap_width
|
||||||
if self.background_task.is_none() {
|
&& self.background_task.is_none()
|
||||||
|
{
|
||||||
let pending_edits = self.pending_edits.clone();
|
let pending_edits = self.pending_edits.clone();
|
||||||
let mut snapshot = self.snapshot.clone();
|
let mut snapshot = self.snapshot.clone();
|
||||||
let text_system = cx.text_system().clone();
|
let text_system = cx.text_system().clone();
|
||||||
|
@ -293,7 +294,6 @@ impl WrapMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let was_interpolated = self.snapshot.interpolated;
|
let was_interpolated = self.snapshot.interpolated;
|
||||||
let mut to_remove_len = 0;
|
let mut to_remove_len = 0;
|
||||||
|
@ -1065,13 +1065,13 @@ impl sum_tree::Item for Transform {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_isomorphic(transforms: &mut Vec<Transform>, summary: TextSummary) {
|
fn push_isomorphic(transforms: &mut Vec<Transform>, summary: TextSummary) {
|
||||||
if let Some(last_transform) = transforms.last_mut() {
|
if let Some(last_transform) = transforms.last_mut()
|
||||||
if last_transform.is_isomorphic() {
|
&& last_transform.is_isomorphic()
|
||||||
|
{
|
||||||
last_transform.summary.input += &summary;
|
last_transform.summary.input += &summary;
|
||||||
last_transform.summary.output += &summary;
|
last_transform.summary.output += &summary;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
transforms.push(Transform::isomorphic(summary));
|
transforms.push(Transform::isomorphic(summary));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -942,12 +942,12 @@ impl ChangeList {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invert_last_group(&mut self) {
|
pub fn invert_last_group(&mut self) {
|
||||||
if let Some(last) = self.changes.last_mut() {
|
if let Some(last) = self.changes.last_mut()
|
||||||
if let Some(current) = last.current.as_mut() {
|
&& let Some(current) = last.current.as_mut()
|
||||||
|
{
|
||||||
mem::swap(&mut last.original, current);
|
mem::swap(&mut last.original, current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -1861,8 +1861,7 @@ impl Editor {
|
||||||
.then(|| language_settings::SoftWrap::None);
|
.then(|| language_settings::SoftWrap::None);
|
||||||
|
|
||||||
let mut project_subscriptions = Vec::new();
|
let mut project_subscriptions = Vec::new();
|
||||||
if full_mode {
|
if full_mode && let Some(project) = project.as_ref() {
|
||||||
if let Some(project) = project.as_ref() {
|
|
||||||
project_subscriptions.push(cx.subscribe_in(
|
project_subscriptions.push(cx.subscribe_in(
|
||||||
project,
|
project,
|
||||||
window,
|
window,
|
||||||
|
@ -1871,14 +1870,12 @@ impl Editor {
|
||||||
// we always query lens with actions, without storing them, always refreshing them
|
// we always query lens with actions, without storing them, always refreshing them
|
||||||
}
|
}
|
||||||
project::Event::RefreshInlayHints => {
|
project::Event::RefreshInlayHints => {
|
||||||
editor
|
editor.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
|
||||||
.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
|
|
||||||
}
|
}
|
||||||
project::Event::LanguageServerAdded(..)
|
project::Event::LanguageServerAdded(..)
|
||||||
| project::Event::LanguageServerRemoved(..) => {
|
| project::Event::LanguageServerRemoved(..) => {
|
||||||
if editor.tasks_update_task.is_none() {
|
if editor.tasks_update_task.is_none() {
|
||||||
editor.tasks_update_task =
|
editor.tasks_update_task = Some(editor.refresh_runnables(window, cx));
|
||||||
Some(editor.refresh_runnables(window, cx));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
project::Event::SnippetEdit(id, snippet_edits) => {
|
project::Event::SnippetEdit(id, snippet_edits) => {
|
||||||
|
@ -1969,7 +1966,6 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let buffer_snapshot = buffer.read(cx).snapshot(cx);
|
let buffer_snapshot = buffer.read(cx).snapshot(cx);
|
||||||
|
|
||||||
|
@ -2323,8 +2319,9 @@ impl Editor {
|
||||||
|
|
||||||
editor.go_to_active_debug_line(window, cx);
|
editor.go_to_active_debug_line(window, cx);
|
||||||
|
|
||||||
if let Some(buffer) = buffer.read(cx).as_singleton() {
|
if let Some(buffer) = buffer.read(cx).as_singleton()
|
||||||
if let Some(project) = editor.project() {
|
&& let Some(project) = editor.project()
|
||||||
|
{
|
||||||
let handle = project.update(cx, |project, cx| {
|
let handle = project.update(cx, |project, cx| {
|
||||||
project.register_buffer_with_language_servers(&buffer, cx)
|
project.register_buffer_with_language_servers(&buffer, cx)
|
||||||
});
|
});
|
||||||
|
@ -2332,7 +2329,6 @@ impl Editor {
|
||||||
.registered_buffers
|
.registered_buffers
|
||||||
.insert(buffer.read(cx).remote_id(), handle);
|
.insert(buffer.read(cx).remote_id(), handle);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
editor.minimap =
|
editor.minimap =
|
||||||
editor.create_minimap(EditorSettings::get_global(cx).minimap, window, cx);
|
editor.create_minimap(EditorSettings::get_global(cx).minimap, window, cx);
|
||||||
|
@ -3035,9 +3031,10 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
if local {
|
if local {
|
||||||
if let Some(buffer_id) = new_cursor_position.buffer_id {
|
if let Some(buffer_id) = new_cursor_position.buffer_id
|
||||||
if !self.registered_buffers.contains_key(&buffer_id) {
|
&& !self.registered_buffers.contains_key(&buffer_id)
|
||||||
if let Some(project) = self.project.as_ref() {
|
&& let Some(project) = self.project.as_ref()
|
||||||
|
{
|
||||||
project.update(cx, |project, cx| {
|
project.update(cx, |project, cx| {
|
||||||
let Some(buffer) = self.buffer.read(cx).buffer(buffer_id) else {
|
let Some(buffer) = self.buffer.read(cx).buffer(buffer_id) else {
|
||||||
return;
|
return;
|
||||||
|
@ -3048,8 +3045,6 @@ impl Editor {
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut context_menu = self.context_menu.borrow_mut();
|
let mut context_menu = self.context_menu.borrow_mut();
|
||||||
let completion_menu = match context_menu.as_ref() {
|
let completion_menu = match context_menu.as_ref() {
|
||||||
|
@ -3063,8 +3058,9 @@ impl Editor {
|
||||||
let completion_position = completion_menu.map(|menu| menu.initial_position);
|
let completion_position = completion_menu.map(|menu| menu.initial_position);
|
||||||
drop(context_menu);
|
drop(context_menu);
|
||||||
|
|
||||||
if effects.completions {
|
if effects.completions
|
||||||
if let Some(completion_position) = completion_position {
|
&& let Some(completion_position) = completion_position
|
||||||
|
{
|
||||||
let start_offset = selection_start.to_offset(buffer);
|
let start_offset = selection_start.to_offset(buffer);
|
||||||
let position_matches = start_offset == completion_position.to_offset(buffer);
|
let position_matches = start_offset == completion_position.to_offset(buffer);
|
||||||
let continue_showing = if position_matches {
|
let continue_showing = if position_matches {
|
||||||
|
@ -3086,7 +3082,6 @@ impl Editor {
|
||||||
self.hide_context_menu(window, cx);
|
self.hide_context_menu(window, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
hide_hover(self, cx);
|
hide_hover(self, cx);
|
||||||
|
|
||||||
|
@ -3115,8 +3110,7 @@ impl Editor {
|
||||||
if selections.len() == 1 {
|
if selections.len() == 1 {
|
||||||
cx.emit(SearchEvent::ActiveMatchChanged)
|
cx.emit(SearchEvent::ActiveMatchChanged)
|
||||||
}
|
}
|
||||||
if local {
|
if local && let Some((_, _, buffer_snapshot)) = buffer.as_singleton() {
|
||||||
if let Some((_, _, buffer_snapshot)) = buffer.as_singleton() {
|
|
||||||
let inmemory_selections = selections
|
let inmemory_selections = selections
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| {
|
.map(|s| {
|
||||||
|
@ -3128,10 +3122,8 @@ impl Editor {
|
||||||
data.selections = inmemory_selections;
|
data.selections = inmemory_selections;
|
||||||
});
|
});
|
||||||
|
|
||||||
if WorkspaceSettings::get(None, cx).restore_on_startup
|
if WorkspaceSettings::get(None, cx).restore_on_startup != RestoreOnStartupBehavior::None
|
||||||
!= RestoreOnStartupBehavior::None
|
&& let Some(workspace_id) =
|
||||||
{
|
|
||||||
if let Some(workspace_id) =
|
|
||||||
self.workspace.as_ref().and_then(|workspace| workspace.1)
|
self.workspace.as_ref().and_then(|workspace| workspace.1)
|
||||||
{
|
{
|
||||||
let snapshot = self.buffer().read(cx).snapshot(cx);
|
let snapshot = self.buffer().read(cx).snapshot(cx);
|
||||||
|
@ -3157,8 +3149,6 @@ impl Editor {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
@ -4154,12 +4144,11 @@ impl Editor {
|
||||||
if self.auto_replace_emoji_shortcode
|
if self.auto_replace_emoji_shortcode
|
||||||
&& selection.is_empty()
|
&& selection.is_empty()
|
||||||
&& text.as_ref().ends_with(':')
|
&& text.as_ref().ends_with(':')
|
||||||
{
|
&& let Some(possible_emoji_short_code) =
|
||||||
if let Some(possible_emoji_short_code) =
|
|
||||||
Self::find_possible_emoji_shortcode_at_position(&snapshot, selection.start)
|
Self::find_possible_emoji_shortcode_at_position(&snapshot, selection.start)
|
||||||
|
&& !possible_emoji_short_code.is_empty()
|
||||||
|
&& let Some(emoji) = emojis::get_by_shortcode(&possible_emoji_short_code)
|
||||||
{
|
{
|
||||||
if !possible_emoji_short_code.is_empty() {
|
|
||||||
if let Some(emoji) = emojis::get_by_shortcode(&possible_emoji_short_code) {
|
|
||||||
let emoji_shortcode_start = Point::new(
|
let emoji_shortcode_start = Point::new(
|
||||||
selection.start.row,
|
selection.start.row,
|
||||||
selection.start.column - possible_emoji_short_code.len() as u32 - 1,
|
selection.start.column - possible_emoji_short_code.len() as u32 - 1,
|
||||||
|
@ -4188,9 +4177,6 @@ impl Editor {
|
||||||
|
|
||||||
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
|
||||||
|
@ -4303,13 +4289,12 @@ impl Editor {
|
||||||
|s| s.select(new_selections),
|
|s| s.select(new_selections),
|
||||||
);
|
);
|
||||||
|
|
||||||
if !bracket_inserted {
|
if !bracket_inserted
|
||||||
if let Some(on_type_format_task) =
|
&& let Some(on_type_format_task) =
|
||||||
this.trigger_on_type_formatting(text.to_string(), window, cx)
|
this.trigger_on_type_formatting(text.to_string(), window, cx)
|
||||||
{
|
{
|
||||||
on_type_format_task.detach_and_log_err(cx);
|
on_type_format_task.detach_and_log_err(cx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let editor_settings = EditorSettings::get_global(cx);
|
let editor_settings = EditorSettings::get_global(cx);
|
||||||
if bracket_inserted
|
if bracket_inserted
|
||||||
|
@ -5274,11 +5259,11 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
let language = buffer.language()?;
|
let language = buffer.language()?;
|
||||||
if let Some(restrict_to_languages) = restrict_to_languages {
|
if let Some(restrict_to_languages) = restrict_to_languages
|
||||||
if !restrict_to_languages.contains(language) {
|
&& !restrict_to_languages.contains(language)
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Some((
|
Some((
|
||||||
excerpt_id,
|
excerpt_id,
|
||||||
(
|
(
|
||||||
|
@ -5605,8 +5590,9 @@ impl Editor {
|
||||||
// that having one source with `is_incomplete: true` doesn't cause all to be re-queried.
|
// that having one source with `is_incomplete: true` doesn't cause all to be re-queried.
|
||||||
let mut completions = Vec::new();
|
let mut completions = Vec::new();
|
||||||
let mut is_incomplete = false;
|
let mut is_incomplete = false;
|
||||||
if let Some(provider_responses) = provider_responses.await.log_err() {
|
if let Some(provider_responses) = provider_responses.await.log_err()
|
||||||
if !provider_responses.is_empty() {
|
&& !provider_responses.is_empty()
|
||||||
|
{
|
||||||
for response in provider_responses {
|
for response in provider_responses {
|
||||||
completions.extend(response.completions);
|
completions.extend(response.completions);
|
||||||
is_incomplete = is_incomplete || response.is_incomplete;
|
is_incomplete = is_incomplete || response.is_incomplete;
|
||||||
|
@ -5615,7 +5601,6 @@ impl Editor {
|
||||||
words = Task::ready(BTreeMap::default());
|
words = Task::ready(BTreeMap::default());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut words = words.await;
|
let mut words = words.await;
|
||||||
if let Some(word_to_exclude) = &word_to_exclude {
|
if let Some(word_to_exclude) = &word_to_exclude {
|
||||||
|
@ -5718,8 +5703,9 @@ impl Editor {
|
||||||
|
|
||||||
editor
|
editor
|
||||||
.update_in(cx, |editor, window, cx| {
|
.update_in(cx, |editor, window, cx| {
|
||||||
if editor.focus_handle.is_focused(window) {
|
if editor.focus_handle.is_focused(window)
|
||||||
if let Some(menu) = menu {
|
&& let Some(menu) = menu
|
||||||
|
{
|
||||||
*editor.context_menu.borrow_mut() =
|
*editor.context_menu.borrow_mut() =
|
||||||
Some(CodeContextMenu::Completions(menu));
|
Some(CodeContextMenu::Completions(menu));
|
||||||
|
|
||||||
|
@ -5733,7 +5719,6 @@ impl Editor {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if editor.completion_tasks.len() <= 1 {
|
if editor.completion_tasks.len() <= 1 {
|
||||||
// If there are no more completion tasks and the last menu was empty, we should hide it.
|
// If there are no more completion tasks and the last menu was empty, we should hide it.
|
||||||
|
@ -6079,12 +6064,12 @@ impl Editor {
|
||||||
Some(CodeActionSource::Indicator(_)) => Task::ready(Ok(Default::default())),
|
Some(CodeActionSource::Indicator(_)) => Task::ready(Ok(Default::default())),
|
||||||
_ => {
|
_ => {
|
||||||
let mut task_context_task = Task::ready(None);
|
let mut task_context_task = Task::ready(None);
|
||||||
if let Some(tasks) = &tasks {
|
if let Some(tasks) = &tasks
|
||||||
if let Some(project) = project {
|
&& let Some(project) = project
|
||||||
|
{
|
||||||
task_context_task =
|
task_context_task =
|
||||||
Self::build_tasks_context(&project, &buffer, buffer_row, tasks, cx);
|
Self::build_tasks_context(&project, &buffer, buffer_row, tasks, cx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
cx.spawn_in(window, {
|
cx.spawn_in(window, {
|
||||||
let buffer = buffer.clone();
|
let buffer = buffer.clone();
|
||||||
|
@ -6148,15 +6133,15 @@ impl Editor {
|
||||||
deployed_from,
|
deployed_from,
|
||||||
}));
|
}));
|
||||||
cx.notify();
|
cx.notify();
|
||||||
if spawn_straight_away {
|
if spawn_straight_away
|
||||||
if let Some(task) = editor.confirm_code_action(
|
&& let Some(task) = editor.confirm_code_action(
|
||||||
&ConfirmCodeAction { item_ix: Some(0) },
|
&ConfirmCodeAction { item_ix: Some(0) },
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
) {
|
)
|
||||||
|
{
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Task::ready(Ok(()))
|
Task::ready(Ok(()))
|
||||||
})
|
})
|
||||||
|
@ -6342,15 +6327,15 @@ impl Editor {
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.excerpt_containing(editor.selections.newest_anchor().head(), cx)
|
.excerpt_containing(editor.selections.newest_anchor().head(), cx)
|
||||||
})?;
|
})?;
|
||||||
if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
|
if let Some((_, excerpted_buffer, excerpt_range)) = excerpt
|
||||||
if excerpted_buffer == *buffer {
|
&& excerpted_buffer == *buffer
|
||||||
|
{
|
||||||
let all_edits_within_excerpt = buffer.read_with(cx, |buffer, _| {
|
let all_edits_within_excerpt = buffer.read_with(cx, |buffer, _| {
|
||||||
let excerpt_range = excerpt_range.to_offset(buffer);
|
let excerpt_range = excerpt_range.to_offset(buffer);
|
||||||
buffer
|
buffer
|
||||||
.edited_ranges_for_transaction::<usize>(transaction)
|
.edited_ranges_for_transaction::<usize>(transaction)
|
||||||
.all(|range| {
|
.all(|range| {
|
||||||
excerpt_range.start <= range.start
|
excerpt_range.start <= range.start && excerpt_range.end >= range.end
|
||||||
&& excerpt_range.end >= range.end
|
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
@ -6359,7 +6344,6 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -7779,12 +7763,12 @@ impl Editor {
|
||||||
|
|
||||||
let indents = multibuffer.suggested_indents(cursor_point.row..cursor_point.row + 1, cx);
|
let indents = multibuffer.suggested_indents(cursor_point.row..cursor_point.row + 1, cx);
|
||||||
|
|
||||||
if let Some((_, indent)) = indents.iter().next() {
|
if let Some((_, indent)) = indents.iter().next()
|
||||||
if indent.len == cursor_point.column {
|
&& indent.len == cursor_point.column
|
||||||
|
{
|
||||||
self.edit_prediction_indent_conflict = false;
|
self.edit_prediction_indent_conflict = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let edit_prediction = provider.suggest(&buffer, cursor_buffer_position, cx)?;
|
let edit_prediction = provider.suggest(&buffer, cursor_buffer_position, cx)?;
|
||||||
let edits = edit_prediction
|
let edits = edit_prediction
|
||||||
|
@ -9531,11 +9515,11 @@ impl Editor {
|
||||||
let context_menu = self.context_menu.borrow_mut().take();
|
let context_menu = self.context_menu.borrow_mut().take();
|
||||||
self.stale_edit_prediction_in_menu.take();
|
self.stale_edit_prediction_in_menu.take();
|
||||||
self.update_visible_edit_prediction(window, cx);
|
self.update_visible_edit_prediction(window, cx);
|
||||||
if let Some(CodeContextMenu::Completions(_)) = &context_menu {
|
if let Some(CodeContextMenu::Completions(_)) = &context_menu
|
||||||
if let Some(completion_provider) = &self.completion_provider {
|
&& let Some(completion_provider) = &self.completion_provider
|
||||||
|
{
|
||||||
completion_provider.selection_changed(None, window, cx);
|
completion_provider.selection_changed(None, window, cx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
context_menu
|
context_menu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9639,11 +9623,11 @@ impl Editor {
|
||||||
s.select_ranges(tabstop.ranges.iter().rev().cloned());
|
s.select_ranges(tabstop.ranges.iter().rev().cloned());
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(choices) = &tabstop.choices {
|
if let Some(choices) = &tabstop.choices
|
||||||
if let Some(selection) = tabstop.ranges.first() {
|
&& let Some(selection) = tabstop.ranges.first()
|
||||||
|
{
|
||||||
self.show_snippet_choices(choices, selection.clone(), cx)
|
self.show_snippet_choices(choices, selection.clone(), cx)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If we're already at the last tabstop and it's at the end of the snippet,
|
// If we're already at the last tabstop and it's at the end of the snippet,
|
||||||
// we're done, we don't need to keep the state around.
|
// we're done, we don't need to keep the state around.
|
||||||
|
@ -9776,11 +9760,11 @@ impl Editor {
|
||||||
s.select_ranges(current_ranges.iter().rev().cloned())
|
s.select_ranges(current_ranges.iter().rev().cloned())
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(choices) = &snippet.choices[snippet.active_index] {
|
if let Some(choices) = &snippet.choices[snippet.active_index]
|
||||||
if let Some(selection) = current_ranges.first() {
|
&& let Some(selection) = current_ranges.first()
|
||||||
|
{
|
||||||
self.show_snippet_choices(choices, selection.clone(), cx);
|
self.show_snippet_choices(choices, selection.clone(), cx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If snippet state is not at the last tabstop, push it back on the stack
|
// If snippet state is not at the last tabstop, push it back on the stack
|
||||||
if snippet.active_index + 1 < snippet.ranges.len() {
|
if snippet.active_index + 1 < snippet.ranges.len() {
|
||||||
|
@ -10176,11 +10160,11 @@ impl Editor {
|
||||||
|
|
||||||
// Avoid re-outdenting a row that has already been outdented by a
|
// Avoid re-outdenting a row that has already been outdented by a
|
||||||
// previous selection.
|
// previous selection.
|
||||||
if let Some(last_row) = last_outdent {
|
if let Some(last_row) = last_outdent
|
||||||
if last_row == rows.start {
|
&& last_row == rows.start
|
||||||
|
{
|
||||||
rows.start = rows.start.next_row();
|
rows.start = rows.start.next_row();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let has_multiple_rows = rows.len() > 1;
|
let has_multiple_rows = rows.len() > 1;
|
||||||
for row in rows.iter_rows() {
|
for row in rows.iter_rows() {
|
||||||
let indent_size = snapshot.indent_size_for_line(row);
|
let indent_size = snapshot.indent_size_for_line(row);
|
||||||
|
@ -10357,12 +10341,12 @@ impl Editor {
|
||||||
MultiBufferRow(selection.end.row)
|
MultiBufferRow(selection.end.row)
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(last_row_range) = row_ranges.last_mut() {
|
if let Some(last_row_range) = row_ranges.last_mut()
|
||||||
if start <= last_row_range.end {
|
&& start <= last_row_range.end
|
||||||
|
{
|
||||||
last_row_range.end = end;
|
last_row_range.end = end;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
row_ranges.push(start..end);
|
row_ranges.push(start..end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15331,19 +15315,17 @@ impl Editor {
|
||||||
if direction == ExpandExcerptDirection::Down {
|
if direction == ExpandExcerptDirection::Down {
|
||||||
let multi_buffer = self.buffer.read(cx);
|
let multi_buffer = self.buffer.read(cx);
|
||||||
let snapshot = multi_buffer.snapshot(cx);
|
let snapshot = multi_buffer.snapshot(cx);
|
||||||
if let Some(buffer_id) = snapshot.buffer_id_for_excerpt(excerpt) {
|
if let Some(buffer_id) = snapshot.buffer_id_for_excerpt(excerpt)
|
||||||
if let Some(buffer) = multi_buffer.buffer(buffer_id) {
|
&& let Some(buffer) = multi_buffer.buffer(buffer_id)
|
||||||
if let Some(excerpt_range) = snapshot.buffer_range_for_excerpt(excerpt) {
|
&& let Some(excerpt_range) = snapshot.buffer_range_for_excerpt(excerpt)
|
||||||
|
{
|
||||||
let buffer_snapshot = buffer.read(cx).snapshot();
|
let buffer_snapshot = buffer.read(cx).snapshot();
|
||||||
let excerpt_end_row =
|
let excerpt_end_row = Point::from_anchor(&excerpt_range.end, &buffer_snapshot).row;
|
||||||
Point::from_anchor(&excerpt_range.end, &buffer_snapshot).row;
|
|
||||||
let last_row = buffer_snapshot.max_point().row;
|
let last_row = buffer_snapshot.max_point().row;
|
||||||
let lines_below = last_row.saturating_sub(excerpt_end_row);
|
let lines_below = last_row.saturating_sub(excerpt_end_row);
|
||||||
should_scroll_up = lines_below >= lines_to_expand;
|
should_scroll_up = lines_below >= lines_to_expand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
self.buffer.update(cx, |buffer, cx| {
|
||||||
buffer.expand_excerpts([excerpt], lines_to_expand, direction, cx)
|
buffer.expand_excerpts([excerpt], lines_to_expand, direction, cx)
|
||||||
|
@ -15426,11 +15408,11 @@ impl Editor {
|
||||||
let selection = self.selections.newest::<usize>(cx);
|
let selection = self.selections.newest::<usize>(cx);
|
||||||
|
|
||||||
let mut active_group_id = None;
|
let mut active_group_id = None;
|
||||||
if let ActiveDiagnostic::Group(active_group) = &self.active_diagnostics {
|
if let ActiveDiagnostic::Group(active_group) = &self.active_diagnostics
|
||||||
if active_group.active_range.start.to_offset(&buffer) == selection.start {
|
&& active_group.active_range.start.to_offset(&buffer) == selection.start
|
||||||
|
{
|
||||||
active_group_id = Some(active_group.group_id);
|
active_group_id = Some(active_group.group_id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn filtered(
|
fn filtered(
|
||||||
snapshot: EditorSnapshot,
|
snapshot: EditorSnapshot,
|
||||||
|
@ -16674,11 +16656,11 @@ impl Editor {
|
||||||
|
|
||||||
buffer
|
buffer
|
||||||
.update(cx, |buffer, cx| {
|
.update(cx, |buffer, cx| {
|
||||||
if let Some(transaction) = transaction {
|
if let Some(transaction) = transaction
|
||||||
if !buffer.is_singleton() {
|
&& !buffer.is_singleton()
|
||||||
|
{
|
||||||
buffer.push_transaction(&transaction.0, cx);
|
buffer.push_transaction(&transaction.0, cx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
@ -16743,11 +16725,11 @@ impl Editor {
|
||||||
buffer
|
buffer
|
||||||
.update(cx, |buffer, cx| {
|
.update(cx, |buffer, cx| {
|
||||||
// check if we need this
|
// check if we need this
|
||||||
if let Some(transaction) = transaction {
|
if let Some(transaction) = transaction
|
||||||
if !buffer.is_singleton() {
|
&& !buffer.is_singleton()
|
||||||
|
{
|
||||||
buffer.push_transaction(&transaction.0, cx);
|
buffer.push_transaction(&transaction.0, cx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
@ -17378,8 +17360,9 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
for row in (0..=range.start.row).rev() {
|
for row in (0..=range.start.row).rev() {
|
||||||
if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
|
if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row))
|
||||||
if crease.range().end.row >= buffer_start_row {
|
&& crease.range().end.row >= buffer_start_row
|
||||||
|
{
|
||||||
to_fold.push(crease);
|
to_fold.push(crease);
|
||||||
if row <= range.start.row {
|
if row <= range.start.row {
|
||||||
break;
|
break;
|
||||||
|
@ -17387,7 +17370,6 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.fold_creases(to_fold, true, window, cx);
|
self.fold_creases(to_fold, true, window, cx);
|
||||||
} else {
|
} else {
|
||||||
|
@ -18693,11 +18675,11 @@ impl Editor {
|
||||||
|
|
||||||
pub fn working_directory(&self, cx: &App) -> Option<PathBuf> {
|
pub fn working_directory(&self, cx: &App) -> Option<PathBuf> {
|
||||||
if let Some(buffer) = self.buffer().read(cx).as_singleton() {
|
if let Some(buffer) = self.buffer().read(cx).as_singleton() {
|
||||||
if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
|
if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local())
|
||||||
if let Some(dir) = file.abs_path(cx).parent() {
|
&& let Some(dir) = file.abs_path(cx).parent()
|
||||||
|
{
|
||||||
return Some(dir.to_owned());
|
return Some(dir.to_owned());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(project_path) = buffer.read(cx).project_path(cx) {
|
if let Some(project_path) = buffer.read(cx).project_path(cx) {
|
||||||
return Some(project_path.path.to_path_buf());
|
return Some(project_path.path.to_path_buf());
|
||||||
|
@ -18756,12 +18738,12 @@ impl Editor {
|
||||||
_window: &mut Window,
|
_window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
if let Some(path) = self.target_file_abs_path(cx) {
|
if let Some(path) = self.target_file_abs_path(cx)
|
||||||
if let Some(path) = path.to_str() {
|
&& let Some(path) = path.to_str()
|
||||||
|
{
|
||||||
cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
|
cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn copy_relative_path(
|
pub fn copy_relative_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -18769,12 +18751,12 @@ impl Editor {
|
||||||
_window: &mut Window,
|
_window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
if let Some(path) = self.target_file_path(cx) {
|
if let Some(path) = self.target_file_path(cx)
|
||||||
if let Some(path) = path.to_str() {
|
&& let Some(path) = path.to_str()
|
||||||
|
{
|
||||||
cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
|
cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn project_path(&self, cx: &App) -> Option<ProjectPath> {
|
pub fn project_path(&self, cx: &App) -> Option<ProjectPath> {
|
||||||
if let Some(buffer) = self.buffer.read(cx).as_singleton() {
|
if let Some(buffer) = self.buffer.read(cx).as_singleton() {
|
||||||
|
@ -18841,24 +18823,22 @@ impl Editor {
|
||||||
_: &mut Window,
|
_: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
if let Some(file) = self.target_file(cx) {
|
if let Some(file) = self.target_file(cx)
|
||||||
if let Some(file_stem) = file.path().file_stem() {
|
&& let Some(file_stem) = file.path().file_stem()
|
||||||
if let Some(name) = file_stem.to_str() {
|
&& let Some(name) = file_stem.to_str()
|
||||||
|
{
|
||||||
cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
|
cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn copy_file_name(&mut self, _: &CopyFileName, _: &mut Window, cx: &mut Context<Self>) {
|
pub fn copy_file_name(&mut self, _: &CopyFileName, _: &mut Window, cx: &mut Context<Self>) {
|
||||||
if let Some(file) = self.target_file(cx) {
|
if let Some(file) = self.target_file(cx)
|
||||||
if let Some(file_name) = file.path().file_name() {
|
&& let Some(file_name) = file.path().file_name()
|
||||||
if let Some(name) = file_name.to_str() {
|
&& let Some(name) = file_name.to_str()
|
||||||
|
{
|
||||||
cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
|
cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn toggle_git_blame(
|
pub fn toggle_git_blame(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -19126,12 +19106,12 @@ impl Editor {
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
let selection = self.selections.newest::<Point>(cx).start.row + 1;
|
let selection = self.selections.newest::<Point>(cx).start.row + 1;
|
||||||
if let Some(file) = self.target_file(cx) {
|
if let Some(file) = self.target_file(cx)
|
||||||
if let Some(path) = file.path().to_str() {
|
&& let Some(path) = file.path().to_str()
|
||||||
|
{
|
||||||
cx.write_to_clipboard(ClipboardItem::new_string(format!("{path}:{selection}")));
|
cx.write_to_clipboard(ClipboardItem::new_string(format!("{path}:{selection}")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn open_permalink_to_line(
|
pub fn open_permalink_to_line(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -19769,11 +19749,11 @@ impl Editor {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let end = range.end.to_point(&display_snapshot.buffer_snapshot);
|
let end = range.end.to_point(&display_snapshot.buffer_snapshot);
|
||||||
if let Some(current_row) = &end_row {
|
if let Some(current_row) = &end_row
|
||||||
if end.row == current_row.row {
|
&& end.row == current_row.row
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let start = range.start.to_point(&display_snapshot.buffer_snapshot);
|
let start = range.start.to_point(&display_snapshot.buffer_snapshot);
|
||||||
if start_row.is_none() {
|
if start_row.is_none() {
|
||||||
assert_eq!(end_row, None);
|
assert_eq!(end_row, None);
|
||||||
|
@ -20064,8 +20044,9 @@ impl Editor {
|
||||||
if self.has_active_edit_prediction() {
|
if self.has_active_edit_prediction() {
|
||||||
self.update_visible_edit_prediction(window, cx);
|
self.update_visible_edit_prediction(window, cx);
|
||||||
}
|
}
|
||||||
if let Some(project) = self.project.as_ref() {
|
if let Some(project) = self.project.as_ref()
|
||||||
if let Some(edited_buffer) = edited_buffer {
|
&& let Some(edited_buffer) = edited_buffer
|
||||||
|
{
|
||||||
project.update(cx, |project, cx| {
|
project.update(cx, |project, cx| {
|
||||||
self.registered_buffers
|
self.registered_buffers
|
||||||
.entry(edited_buffer.read(cx).remote_id())
|
.entry(edited_buffer.read(cx).remote_id())
|
||||||
|
@ -20074,7 +20055,6 @@ impl Editor {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
cx.emit(EditorEvent::BufferEdited);
|
cx.emit(EditorEvent::BufferEdited);
|
||||||
cx.emit(SearchEvent::MatchesInvalidated);
|
cx.emit(SearchEvent::MatchesInvalidated);
|
||||||
|
|
||||||
|
@ -20083,11 +20063,11 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
if *singleton_buffer_edited {
|
if *singleton_buffer_edited {
|
||||||
if let Some(buffer) = edited_buffer {
|
if let Some(buffer) = edited_buffer
|
||||||
if buffer.read(cx).file().is_none() {
|
&& buffer.read(cx).file().is_none()
|
||||||
|
{
|
||||||
cx.emit(EditorEvent::TitleChanged);
|
cx.emit(EditorEvent::TitleChanged);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if let Some(project) = &self.project {
|
if let Some(project) = &self.project {
|
||||||
#[allow(clippy::mutable_key_type)]
|
#[allow(clippy::mutable_key_type)]
|
||||||
let languages_affected = multibuffer.update(cx, |multibuffer, cx| {
|
let languages_affected = multibuffer.update(cx, |multibuffer, cx| {
|
||||||
|
@ -20132,8 +20112,9 @@ impl Editor {
|
||||||
} => {
|
} => {
|
||||||
self.tasks_update_task = Some(self.refresh_runnables(window, cx));
|
self.tasks_update_task = Some(self.refresh_runnables(window, cx));
|
||||||
let buffer_id = buffer.read(cx).remote_id();
|
let buffer_id = buffer.read(cx).remote_id();
|
||||||
if self.buffer.read(cx).diff_for(buffer_id).is_none() {
|
if self.buffer.read(cx).diff_for(buffer_id).is_none()
|
||||||
if let Some(project) = &self.project {
|
&& let Some(project) = &self.project
|
||||||
|
{
|
||||||
update_uncommitted_diff_for_buffer(
|
update_uncommitted_diff_for_buffer(
|
||||||
cx.entity(),
|
cx.entity(),
|
||||||
project,
|
project,
|
||||||
|
@ -20143,7 +20124,6 @@ impl Editor {
|
||||||
)
|
)
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self.update_lsp_data(false, Some(buffer_id), window, cx);
|
self.update_lsp_data(false, Some(buffer_id), window, cx);
|
||||||
cx.emit(EditorEvent::ExcerptsAdded {
|
cx.emit(EditorEvent::ExcerptsAdded {
|
||||||
buffer: buffer.clone(),
|
buffer: buffer.clone(),
|
||||||
|
@ -20746,12 +20726,12 @@ impl Editor {
|
||||||
let mut chunk_lines = chunk.text.split('\n').peekable();
|
let mut chunk_lines = chunk.text.split('\n').peekable();
|
||||||
while let Some(text) = chunk_lines.next() {
|
while let Some(text) = chunk_lines.next() {
|
||||||
let mut merged_with_last_token = false;
|
let mut merged_with_last_token = false;
|
||||||
if let Some(last_token) = line.back_mut() {
|
if let Some(last_token) = line.back_mut()
|
||||||
if last_token.highlight == highlight {
|
&& last_token.highlight == highlight
|
||||||
|
{
|
||||||
last_token.text.push_str(text);
|
last_token.text.push_str(text);
|
||||||
merged_with_last_token = true;
|
merged_with_last_token = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if !merged_with_last_token {
|
if !merged_with_last_token {
|
||||||
line.push_back(Chunk {
|
line.push_back(Chunk {
|
||||||
|
@ -21209,10 +21189,10 @@ impl Editor {
|
||||||
{
|
{
|
||||||
let buffer_snapshot = OnceCell::new();
|
let buffer_snapshot = OnceCell::new();
|
||||||
|
|
||||||
if let Some(folds) = DB.get_editor_folds(item_id, workspace_id).log_err() {
|
if let Some(folds) = DB.get_editor_folds(item_id, workspace_id).log_err()
|
||||||
if !folds.is_empty() {
|
&& !folds.is_empty()
|
||||||
let snapshot =
|
{
|
||||||
buffer_snapshot.get_or_init(|| self.buffer.read(cx).snapshot(cx));
|
let snapshot = buffer_snapshot.get_or_init(|| self.buffer.read(cx).snapshot(cx));
|
||||||
self.fold_ranges(
|
self.fold_ranges(
|
||||||
folds
|
folds
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -21226,12 +21206,11 @@ impl Editor {
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(selections) = DB.get_editor_selections(item_id, workspace_id).log_err() {
|
if let Some(selections) = DB.get_editor_selections(item_id, workspace_id).log_err()
|
||||||
if !selections.is_empty() {
|
&& !selections.is_empty()
|
||||||
let snapshot =
|
{
|
||||||
buffer_snapshot.get_or_init(|| self.buffer.read(cx).snapshot(cx));
|
let snapshot = buffer_snapshot.get_or_init(|| self.buffer.read(cx).snapshot(cx));
|
||||||
// skip adding the initial selection to selection history
|
// skip adding the initial selection to selection history
|
||||||
self.selection_history.mode = SelectionHistoryMode::Skipping;
|
self.selection_history.mode = SelectionHistoryMode::Skipping;
|
||||||
self.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
self.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||||
|
@ -21241,7 +21220,6 @@ impl Editor {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
self.selection_history.mode = SelectionHistoryMode::Normal;
|
self.selection_history.mode = SelectionHistoryMode::Normal;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21283,18 +21261,16 @@ fn process_completion_for_edit(
|
||||||
let mut snippet_source = completion.new_text.clone();
|
let mut snippet_source = completion.new_text.clone();
|
||||||
let mut previous_point = text::ToPoint::to_point(cursor_position, buffer);
|
let mut previous_point = text::ToPoint::to_point(cursor_position, buffer);
|
||||||
previous_point.column = previous_point.column.saturating_sub(1);
|
previous_point.column = previous_point.column.saturating_sub(1);
|
||||||
if let Some(scope) = buffer_snapshot.language_scope_at(previous_point) {
|
if let Some(scope) = buffer_snapshot.language_scope_at(previous_point)
|
||||||
if scope.prefers_label_for_snippet_in_completion() {
|
&& scope.prefers_label_for_snippet_in_completion()
|
||||||
if let Some(label) = completion.label() {
|
&& let Some(label) = completion.label()
|
||||||
if matches!(
|
&& matches!(
|
||||||
completion.kind(),
|
completion.kind(),
|
||||||
Some(CompletionItemKind::FUNCTION) | Some(CompletionItemKind::METHOD)
|
Some(CompletionItemKind::FUNCTION) | Some(CompletionItemKind::METHOD)
|
||||||
) {
|
)
|
||||||
|
{
|
||||||
snippet_source = label;
|
snippet_source = label;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match Snippet::parse(&snippet_source).log_err() {
|
match Snippet::parse(&snippet_source).log_err() {
|
||||||
Some(parsed_snippet) => (Some(parsed_snippet.clone()), parsed_snippet.text),
|
Some(parsed_snippet) => (Some(parsed_snippet.clone()), parsed_snippet.text),
|
||||||
None => (None, completion.new_text.clone()),
|
None => (None, completion.new_text.clone()),
|
||||||
|
@ -21347,12 +21323,12 @@ fn process_completion_for_edit(
|
||||||
);
|
);
|
||||||
let mut current_needle = text_to_replace.next();
|
let mut current_needle = text_to_replace.next();
|
||||||
for haystack_ch in completion.label.text.chars() {
|
for haystack_ch in completion.label.text.chars() {
|
||||||
if let Some(needle_ch) = current_needle {
|
if let Some(needle_ch) = current_needle
|
||||||
if haystack_ch.eq_ignore_ascii_case(&needle_ch) {
|
&& haystack_ch.eq_ignore_ascii_case(&needle_ch)
|
||||||
|
{
|
||||||
current_needle = text_to_replace.next();
|
current_needle = text_to_replace.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
current_needle.is_none()
|
current_needle.is_none()
|
||||||
}
|
}
|
||||||
LspInsertMode::ReplaceSuffix => {
|
LspInsertMode::ReplaceSuffix => {
|
||||||
|
@ -21604,12 +21580,12 @@ impl<'a> Iterator for WordBreakingTokenizer<'a> {
|
||||||
offset += first_grapheme.len();
|
offset += first_grapheme.len();
|
||||||
grapheme_len += 1;
|
grapheme_len += 1;
|
||||||
if is_grapheme_ideographic(first_grapheme) && !is_whitespace {
|
if is_grapheme_ideographic(first_grapheme) && !is_whitespace {
|
||||||
if let Some(grapheme) = iter.peek().copied() {
|
if let Some(grapheme) = iter.peek().copied()
|
||||||
if should_stay_with_preceding_ideograph(grapheme) {
|
&& should_stay_with_preceding_ideograph(grapheme)
|
||||||
|
{
|
||||||
offset += grapheme.len();
|
offset += grapheme.len();
|
||||||
grapheme_len += 1;
|
grapheme_len += 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let mut words = self.input[offset..].split_word_bound_indices().peekable();
|
let mut words = self.input[offset..].split_word_bound_indices().peekable();
|
||||||
let mut next_word_bound = words.peek().copied();
|
let mut next_word_bound = words.peek().copied();
|
||||||
|
|
|
@ -917,6 +917,10 @@ impl EditorElement {
|
||||||
} else if cfg!(any(target_os = "linux", target_os = "freebsd"))
|
} else if cfg!(any(target_os = "linux", target_os = "freebsd"))
|
||||||
&& event.button == MouseButton::Middle
|
&& event.button == MouseButton::Middle
|
||||||
{
|
{
|
||||||
|
#[allow(
|
||||||
|
clippy::collapsible_if,
|
||||||
|
reason = "The cfg-block below makes this a false positive"
|
||||||
|
)]
|
||||||
if !text_hitbox.is_hovered(window) || editor.read_only(cx) {
|
if !text_hitbox.is_hovered(window) || editor.read_only(cx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1387,8 +1391,7 @@ impl EditorElement {
|
||||||
ref drop_cursor,
|
ref drop_cursor,
|
||||||
ref hide_drop_cursor,
|
ref hide_drop_cursor,
|
||||||
} = editor.selection_drag_state
|
} = editor.selection_drag_state
|
||||||
{
|
&& !hide_drop_cursor
|
||||||
if !hide_drop_cursor
|
|
||||||
&& (drop_cursor
|
&& (drop_cursor
|
||||||
.start
|
.start
|
||||||
.cmp(&selection.start, &snapshot.buffer_snapshot)
|
.cmp(&selection.start, &snapshot.buffer_snapshot)
|
||||||
|
@ -1411,7 +1414,6 @@ impl EditorElement {
|
||||||
selections.push((absent_color, vec![drag_cursor_layout]));
|
selections.push((absent_color, vec![drag_cursor_layout]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(collaboration_hub) = &editor.collaboration_hub {
|
if let Some(collaboration_hub) = &editor.collaboration_hub {
|
||||||
// When following someone, render the local selections in their color.
|
// When following someone, render the local selections in their color.
|
||||||
|
@ -1420,12 +1422,10 @@ impl EditorElement {
|
||||||
CollaboratorId::PeerId(peer_id) => {
|
CollaboratorId::PeerId(peer_id) => {
|
||||||
if let Some(collaborator) =
|
if let Some(collaborator) =
|
||||||
collaboration_hub.collaborators(cx).get(&peer_id)
|
collaboration_hub.collaborators(cx).get(&peer_id)
|
||||||
{
|
&& let Some(participant_index) = collaboration_hub
|
||||||
if let Some(participant_index) = collaboration_hub
|
|
||||||
.user_participant_indices(cx)
|
.user_participant_indices(cx)
|
||||||
.get(&collaborator.user_id)
|
.get(&collaborator.user_id)
|
||||||
{
|
&& let Some((local_selection_style, _)) = selections.first_mut()
|
||||||
if let Some((local_selection_style, _)) = selections.first_mut()
|
|
||||||
{
|
{
|
||||||
*local_selection_style = cx
|
*local_selection_style = cx
|
||||||
.theme()
|
.theme()
|
||||||
|
@ -1433,8 +1433,6 @@ impl EditorElement {
|
||||||
.color_for_participant(participant_index.0);
|
.color_for_participant(participant_index.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
CollaboratorId::Agent => {
|
CollaboratorId::Agent => {
|
||||||
if let Some((local_selection_style, _)) = selections.first_mut() {
|
if let Some((local_selection_style, _)) = selections.first_mut() {
|
||||||
*local_selection_style = cx.theme().players().agent();
|
*local_selection_style = cx.theme().players().agent();
|
||||||
|
@ -3518,10 +3516,12 @@ impl EditorElement {
|
||||||
let mut x_offset = px(0.);
|
let mut x_offset = px(0.);
|
||||||
let mut is_block = true;
|
let mut is_block = true;
|
||||||
|
|
||||||
if let BlockId::Custom(custom_block_id) = block_id {
|
if let BlockId::Custom(custom_block_id) = block_id
|
||||||
if block.has_height() {
|
&& block.has_height()
|
||||||
if block.place_near() {
|
{
|
||||||
if let Some((x_target, line_width)) = x_position {
|
if block.place_near()
|
||||||
|
&& let Some((x_target, line_width)) = x_position
|
||||||
|
{
|
||||||
let margin = em_width * 2;
|
let margin = em_width * 2;
|
||||||
if line_width + final_size.width + margin
|
if line_width + final_size.width + margin
|
||||||
< editor_width + editor_margins.gutter.full_width()
|
< editor_width + editor_margins.gutter.full_width()
|
||||||
|
@ -3534,19 +3534,17 @@ impl EditorElement {
|
||||||
element_height_in_lines = 0;
|
element_height_in_lines = 0;
|
||||||
row_block_types.insert(row, is_block);
|
row_block_types.insert(row, is_block);
|
||||||
} else {
|
} else {
|
||||||
let max_offset = editor_width + editor_margins.gutter.full_width()
|
let max_offset =
|
||||||
- final_size.width;
|
editor_width + editor_margins.gutter.full_width() - final_size.width;
|
||||||
let min_offset = (x_target + em_width - final_size.width)
|
let min_offset = (x_target + em_width - final_size.width)
|
||||||
.max(editor_margins.gutter.full_width());
|
.max(editor_margins.gutter.full_width());
|
||||||
x_offset = x_target.min(max_offset).max(min_offset);
|
x_offset = x_target.min(max_offset).max(min_offset);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if element_height_in_lines != block.height() {
|
if element_height_in_lines != block.height() {
|
||||||
resized_blocks.insert(custom_block_id, element_height_in_lines);
|
resized_blocks.insert(custom_block_id, element_height_in_lines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for i in 0..element_height_in_lines {
|
for i in 0..element_height_in_lines {
|
||||||
row_block_types.insert(row + i, is_block);
|
row_block_types.insert(row + i, is_block);
|
||||||
}
|
}
|
||||||
|
@ -3987,10 +3985,11 @@ impl EditorElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(focused_block) = focused_block {
|
if let Some(focused_block) = focused_block
|
||||||
if let Some(focus_handle) = focused_block.focus_handle.upgrade() {
|
&& let Some(focus_handle) = focused_block.focus_handle.upgrade()
|
||||||
if focus_handle.is_focused(window) {
|
&& focus_handle.is_focused(window)
|
||||||
if let Some(block) = snapshot.block_for_id(focused_block.id) {
|
&& let Some(block) = snapshot.block_for_id(focused_block.id)
|
||||||
|
{
|
||||||
let style = block.style();
|
let style = block.style();
|
||||||
let width = match style {
|
let width = match style {
|
||||||
BlockStyle::Fixed => AvailableSpace::MinContent,
|
BlockStyle::Fixed => AvailableSpace::MinContent,
|
||||||
|
@ -4040,9 +4039,6 @@ impl EditorElement {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if resized_blocks.is_empty() {
|
if resized_blocks.is_empty() {
|
||||||
*scroll_width =
|
*scroll_width =
|
||||||
|
@ -4203,8 +4199,9 @@ impl EditorElement {
|
||||||
edit_prediction_popover_visible = true;
|
edit_prediction_popover_visible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if editor.context_menu_visible() {
|
if editor.context_menu_visible()
|
||||||
if let Some(crate::ContextMenuOrigin::Cursor) = editor.context_menu_origin() {
|
&& let Some(crate::ContextMenuOrigin::Cursor) = editor.context_menu_origin()
|
||||||
|
{
|
||||||
let (min_height_in_lines, max_height_in_lines) = editor
|
let (min_height_in_lines, max_height_in_lines) = editor
|
||||||
.context_menu_options
|
.context_menu_options
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -4216,7 +4213,6 @@ impl EditorElement {
|
||||||
max_menu_height += line_height * max_height_in_lines as f32 + POPOVER_Y_PADDING;
|
max_menu_height += line_height * max_height_in_lines as f32 + POPOVER_Y_PADDING;
|
||||||
context_menu_visible = true;
|
context_menu_visible = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
context_menu_placement = editor
|
context_menu_placement = editor
|
||||||
.context_menu_options
|
.context_menu_options
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -5761,8 +5757,8 @@ impl EditorElement {
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) {
|
) {
|
||||||
for (_, hunk_hitbox) in &layout.display_hunks {
|
for (_, hunk_hitbox) in &layout.display_hunks {
|
||||||
if let Some(hunk_hitbox) = hunk_hitbox {
|
if let Some(hunk_hitbox) = hunk_hitbox
|
||||||
if !self
|
&& !self
|
||||||
.editor
|
.editor
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.buffer()
|
.buffer()
|
||||||
|
@ -5772,7 +5768,6 @@ impl EditorElement {
|
||||||
window.set_cursor_style(CursorStyle::PointingHand, hunk_hitbox);
|
window.set_cursor_style(CursorStyle::PointingHand, hunk_hitbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let show_git_gutter = layout
|
let show_git_gutter = layout
|
||||||
.position_map
|
.position_map
|
||||||
|
@ -10152,11 +10147,11 @@ fn compute_auto_height_layout(
|
||||||
let overscroll = size(em_width, px(0.));
|
let overscroll = size(em_width, px(0.));
|
||||||
|
|
||||||
let editor_width = text_width - gutter_dimensions.margin - overscroll.width - em_width;
|
let editor_width = text_width - gutter_dimensions.margin - overscroll.width - em_width;
|
||||||
if !matches!(editor.soft_wrap_mode(cx), SoftWrap::None) {
|
if !matches!(editor.soft_wrap_mode(cx), SoftWrap::None)
|
||||||
if editor.set_wrap_width(Some(editor_width), cx) {
|
&& editor.set_wrap_width(Some(editor_width), cx)
|
||||||
|
{
|
||||||
snapshot = editor.snapshot(window, cx);
|
snapshot = editor.snapshot(window, cx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let scroll_height = (snapshot.max_point().row().next_row().0 as f32) * line_height;
|
let scroll_height = (snapshot.max_point().row().next_row().0 as f32) * line_height;
|
||||||
|
|
||||||
|
|
|
@ -312,12 +312,12 @@ impl GitBlame {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|entry| entry.author.as_ref())
|
.and_then(|entry| entry.author.as_ref())
|
||||||
.map(|author| author.len());
|
.map(|author| author.len());
|
||||||
if let Some(author_len) = author_len {
|
if let Some(author_len) = author_len
|
||||||
if author_len > max_author_length {
|
&& author_len > max_author_length
|
||||||
|
{
|
||||||
max_author_length = author_len;
|
max_author_length = author_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
max_author_length
|
max_author_length
|
||||||
}
|
}
|
||||||
|
@ -416,8 +416,8 @@ impl GitBlame {
|
||||||
if row_edits
|
if row_edits
|
||||||
.peek()
|
.peek()
|
||||||
.map_or(true, |next_edit| next_edit.old.start >= old_end)
|
.map_or(true, |next_edit| next_edit.old.start >= old_end)
|
||||||
|
&& let Some(entry) = cursor.item()
|
||||||
{
|
{
|
||||||
if let Some(entry) = cursor.item() {
|
|
||||||
if old_end > edit.old.end {
|
if old_end > edit.old.end {
|
||||||
new_entries.push(
|
new_entries.push(
|
||||||
GitBlameEntry {
|
GitBlameEntry {
|
||||||
|
@ -431,7 +431,6 @@ impl GitBlame {
|
||||||
cursor.next();
|
cursor.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
new_entries.append(cursor.suffix(), &());
|
new_entries.append(cursor.suffix(), &());
|
||||||
drop(cursor);
|
drop(cursor);
|
||||||
|
|
||||||
|
|
|
@ -418,8 +418,7 @@ pub fn update_inlay_link_and_hover_points(
|
||||||
}
|
}
|
||||||
if let Some((language_server_id, location)) =
|
if let Some((language_server_id, location)) =
|
||||||
hovered_hint_part.location
|
hovered_hint_part.location
|
||||||
{
|
&& secondary_held
|
||||||
if secondary_held
|
|
||||||
&& !editor.has_pending_nonempty_selection()
|
&& !editor.has_pending_nonempty_selection()
|
||||||
{
|
{
|
||||||
go_to_definition_updated = true;
|
go_to_definition_updated = true;
|
||||||
|
@ -438,7 +437,6 @@ pub fn update_inlay_link_and_hover_points(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
ResolveState::Resolving => {}
|
ResolveState::Resolving => {}
|
||||||
|
@ -766,11 +764,12 @@ pub(crate) fn find_url_from_range(
|
||||||
let mut finder = LinkFinder::new();
|
let mut finder = LinkFinder::new();
|
||||||
finder.kinds(&[LinkKind::Url]);
|
finder.kinds(&[LinkKind::Url]);
|
||||||
|
|
||||||
if let Some(link) = finder.links(&text).next() {
|
if let Some(link) = finder.links(&text).next()
|
||||||
if link.start() == 0 && link.end() == text.len() {
|
&& link.start() == 0
|
||||||
|
&& link.end() == text.len()
|
||||||
|
{
|
||||||
return Some(link.as_str().to_string());
|
return Some(link.as_str().to_string());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,12 +142,12 @@ pub fn hover_at_inlay(
|
||||||
.info_popovers
|
.info_popovers
|
||||||
.iter()
|
.iter()
|
||||||
.any(|InfoPopover { symbol_range, .. }| {
|
.any(|InfoPopover { symbol_range, .. }| {
|
||||||
if let RangeInEditor::Inlay(range) = symbol_range {
|
if let RangeInEditor::Inlay(range) = symbol_range
|
||||||
if range == &inlay_hover.range {
|
&& range == &inlay_hover.range
|
||||||
|
{
|
||||||
// Hover triggered from same location as last time. Don't show again.
|
// Hover triggered from same location as last time. Don't show again.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
false
|
false
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
@ -270,14 +270,13 @@ fn show_hover(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't request again if the location is the same as the previous request
|
// Don't request again if the location is the same as the previous request
|
||||||
if let Some(triggered_from) = &editor.hover_state.triggered_from {
|
if let Some(triggered_from) = &editor.hover_state.triggered_from
|
||||||
if triggered_from
|
&& triggered_from
|
||||||
.cmp(&anchor, &snapshot.buffer_snapshot)
|
.cmp(&anchor, &snapshot.buffer_snapshot)
|
||||||
.is_eq()
|
.is_eq()
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let hover_popover_delay = EditorSettings::get_global(cx).hover_popover_delay;
|
let hover_popover_delay = EditorSettings::get_global(cx).hover_popover_delay;
|
||||||
let all_diagnostics_active = editor.active_diagnostics == ActiveDiagnostic::All;
|
let all_diagnostics_active = editor.active_diagnostics == ActiveDiagnostic::All;
|
||||||
|
@ -717,9 +716,10 @@ pub fn diagnostics_markdown_style(window: &Window, cx: &App) -> MarkdownStyle {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_markdown_url(link: SharedString, window: &mut Window, cx: &mut App) {
|
pub fn open_markdown_url(link: SharedString, window: &mut Window, cx: &mut App) {
|
||||||
if let Ok(uri) = Url::parse(&link) {
|
if let Ok(uri) = Url::parse(&link)
|
||||||
if uri.scheme() == "file" {
|
&& uri.scheme() == "file"
|
||||||
if let Some(workspace) = window.root::<Workspace>().flatten() {
|
&& let Some(workspace) = window.root::<Workspace>().flatten()
|
||||||
|
{
|
||||||
workspace.update(cx, |workspace, cx| {
|
workspace.update(cx, |workspace, cx| {
|
||||||
let task = workspace.open_abs_path(
|
let task = workspace.open_abs_path(
|
||||||
PathBuf::from(uri.path()),
|
PathBuf::from(uri.path()),
|
||||||
|
@ -754,23 +754,17 @@ pub fn open_markdown_url(link: SharedString, window: &mut Window, cx: &mut App)
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
editor.update_in(cx, |editor, window, cx| {
|
editor.update_in(cx, |editor, window, cx| {
|
||||||
editor.change_selections(
|
editor.change_selections(Default::default(), window, cx, |selections| {
|
||||||
Default::default(),
|
selections.select_ranges([
|
||||||
window,
|
text::Point::new(accum - 1, 0)..text::Point::new(accum - 1, 0)
|
||||||
cx,
|
]);
|
||||||
|selections| {
|
});
|
||||||
selections.select_ranges([text::Point::new(accum - 1, 0)
|
|
||||||
..text::Point::new(accum - 1, 0)]);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.detach_and_log_err(cx);
|
.detach_and_log_err(cx);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
cx.open_url(&link);
|
cx.open_url(&link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -839,21 +833,20 @@ impl HoverState {
|
||||||
pub fn focused(&self, window: &mut Window, cx: &mut Context<Editor>) -> bool {
|
pub fn focused(&self, window: &mut Window, cx: &mut Context<Editor>) -> bool {
|
||||||
let mut hover_popover_is_focused = false;
|
let mut hover_popover_is_focused = false;
|
||||||
for info_popover in &self.info_popovers {
|
for info_popover in &self.info_popovers {
|
||||||
if let Some(markdown_view) = &info_popover.parsed_content {
|
if let Some(markdown_view) = &info_popover.parsed_content
|
||||||
if markdown_view.focus_handle(cx).is_focused(window) {
|
&& markdown_view.focus_handle(cx).is_focused(window)
|
||||||
|
{
|
||||||
hover_popover_is_focused = true;
|
hover_popover_is_focused = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if let Some(diagnostic_popover) = &self.diagnostic_popover
|
||||||
if let Some(diagnostic_popover) = &self.diagnostic_popover {
|
&& diagnostic_popover
|
||||||
if diagnostic_popover
|
|
||||||
.markdown
|
.markdown
|
||||||
.focus_handle(cx)
|
.focus_handle(cx)
|
||||||
.is_focused(window)
|
.is_focused(window)
|
||||||
{
|
{
|
||||||
hover_popover_is_focused = true;
|
hover_popover_is_focused = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
hover_popover_is_focused
|
hover_popover_is_focused
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,12 +168,12 @@ pub fn indent_guides_in_range(
|
||||||
while let Some(fold) = folds.next() {
|
while let Some(fold) = folds.next() {
|
||||||
let start = fold.range.start.to_point(&snapshot.buffer_snapshot);
|
let start = fold.range.start.to_point(&snapshot.buffer_snapshot);
|
||||||
let end = fold.range.end.to_point(&snapshot.buffer_snapshot);
|
let end = fold.range.end.to_point(&snapshot.buffer_snapshot);
|
||||||
if let Some(last_range) = fold_ranges.last_mut() {
|
if let Some(last_range) = fold_ranges.last_mut()
|
||||||
if last_range.end >= start {
|
&& last_range.end >= start
|
||||||
|
{
|
||||||
last_range.end = last_range.end.max(end);
|
last_range.end = last_range.end.max(end);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
fold_ranges.push(start..end);
|
fold_ranges.push(start..end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -498,8 +498,7 @@ impl InlayHintCache {
|
||||||
cmp::Ordering::Less | cmp::Ordering::Equal => {
|
cmp::Ordering::Less | cmp::Ordering::Equal => {
|
||||||
if !old_kinds.contains(&cached_hint.kind)
|
if !old_kinds.contains(&cached_hint.kind)
|
||||||
&& new_kinds.contains(&cached_hint.kind)
|
&& new_kinds.contains(&cached_hint.kind)
|
||||||
{
|
&& let Some(anchor) = multi_buffer_snapshot
|
||||||
if let Some(anchor) = multi_buffer_snapshot
|
|
||||||
.anchor_in_excerpt(*excerpt_id, cached_hint.position)
|
.anchor_in_excerpt(*excerpt_id, cached_hint.position)
|
||||||
{
|
{
|
||||||
to_insert.push(Inlay::hint(
|
to_insert.push(Inlay::hint(
|
||||||
|
@ -508,7 +507,6 @@ impl InlayHintCache {
|
||||||
cached_hint,
|
cached_hint,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
excerpt_cache.next();
|
excerpt_cache.next();
|
||||||
}
|
}
|
||||||
cmp::Ordering::Greater => return true,
|
cmp::Ordering::Greater => return true,
|
||||||
|
@ -522,8 +520,9 @@ impl InlayHintCache {
|
||||||
for cached_hint_id in excerpt_cache {
|
for cached_hint_id in excerpt_cache {
|
||||||
let maybe_missed_cached_hint = &excerpt_cached_hints.hints_by_id[cached_hint_id];
|
let maybe_missed_cached_hint = &excerpt_cached_hints.hints_by_id[cached_hint_id];
|
||||||
let cached_hint_kind = maybe_missed_cached_hint.kind;
|
let cached_hint_kind = maybe_missed_cached_hint.kind;
|
||||||
if !old_kinds.contains(&cached_hint_kind) && new_kinds.contains(&cached_hint_kind) {
|
if !old_kinds.contains(&cached_hint_kind)
|
||||||
if let Some(anchor) = multi_buffer_snapshot
|
&& new_kinds.contains(&cached_hint_kind)
|
||||||
|
&& let Some(anchor) = multi_buffer_snapshot
|
||||||
.anchor_in_excerpt(*excerpt_id, maybe_missed_cached_hint.position)
|
.anchor_in_excerpt(*excerpt_id, maybe_missed_cached_hint.position)
|
||||||
{
|
{
|
||||||
to_insert.push(Inlay::hint(
|
to_insert.push(Inlay::hint(
|
||||||
|
@ -534,7 +533,6 @@ impl InlayHintCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
to_remove.extend(
|
to_remove.extend(
|
||||||
shown_hints_to_remove
|
shown_hints_to_remove
|
||||||
|
@ -620,8 +618,9 @@ impl InlayHintCache {
|
||||||
) {
|
) {
|
||||||
if let Some(excerpt_hints) = self.hints.get(&excerpt_id) {
|
if let Some(excerpt_hints) = self.hints.get(&excerpt_id) {
|
||||||
let mut guard = excerpt_hints.write();
|
let mut guard = excerpt_hints.write();
|
||||||
if let Some(cached_hint) = guard.hints_by_id.get_mut(&id) {
|
if let Some(cached_hint) = guard.hints_by_id.get_mut(&id)
|
||||||
if let ResolveState::CanResolve(server_id, _) = &cached_hint.resolve_state {
|
&& let ResolveState::CanResolve(server_id, _) = &cached_hint.resolve_state
|
||||||
|
{
|
||||||
let hint_to_resolve = cached_hint.clone();
|
let hint_to_resolve = cached_hint.clone();
|
||||||
let server_id = *server_id;
|
let server_id = *server_id;
|
||||||
cached_hint.resolve_state = ResolveState::Resolving;
|
cached_hint.resolve_state = ResolveState::Resolving;
|
||||||
|
@ -644,13 +643,13 @@ impl InlayHintCache {
|
||||||
editor.inlay_hint_cache.hints.get(&excerpt_id)
|
editor.inlay_hint_cache.hints.get(&excerpt_id)
|
||||||
{
|
{
|
||||||
let mut guard = excerpt_hints.write();
|
let mut guard = excerpt_hints.write();
|
||||||
if let Some(cached_hint) = guard.hints_by_id.get_mut(&id) {
|
if let Some(cached_hint) = guard.hints_by_id.get_mut(&id)
|
||||||
if cached_hint.resolve_state == ResolveState::Resolving {
|
&& cached_hint.resolve_state == ResolveState::Resolving
|
||||||
|
{
|
||||||
resolved_hint.resolve_state = ResolveState::Resolved;
|
resolved_hint.resolve_state = ResolveState::Resolved;
|
||||||
*cached_hint = resolved_hint;
|
*cached_hint = resolved_hint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,7 +659,6 @@ impl InlayHintCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debounce_value(debounce_ms: u64) -> Option<Duration> {
|
fn debounce_value(debounce_ms: u64) -> Option<Duration> {
|
||||||
|
@ -990,8 +988,8 @@ fn fetch_and_update_hints(
|
||||||
|
|
||||||
let buffer = editor.buffer().read(cx).buffer(query.buffer_id)?;
|
let buffer = editor.buffer().read(cx).buffer(query.buffer_id)?;
|
||||||
|
|
||||||
if !editor.registered_buffers.contains_key(&query.buffer_id) {
|
if !editor.registered_buffers.contains_key(&query.buffer_id)
|
||||||
if let Some(project) = editor.project.as_ref() {
|
&& let Some(project) = editor.project.as_ref() {
|
||||||
project.update(cx, |project, cx| {
|
project.update(cx, |project, cx| {
|
||||||
editor.registered_buffers.insert(
|
editor.registered_buffers.insert(
|
||||||
query.buffer_id,
|
query.buffer_id,
|
||||||
|
@ -999,7 +997,6 @@ fn fetch_and_update_hints(
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
editor
|
editor
|
||||||
.semantics_provider
|
.semantics_provider
|
||||||
|
@ -1240,15 +1237,13 @@ fn apply_hint_update(
|
||||||
.inlay_hint_cache
|
.inlay_hint_cache
|
||||||
.allowed_hint_kinds
|
.allowed_hint_kinds
|
||||||
.contains(&new_hint.kind)
|
.contains(&new_hint.kind)
|
||||||
{
|
&& let Some(new_hint_position) =
|
||||||
if let Some(new_hint_position) =
|
|
||||||
multi_buffer_snapshot.anchor_in_excerpt(query.excerpt_id, new_hint.position)
|
multi_buffer_snapshot.anchor_in_excerpt(query.excerpt_id, new_hint.position)
|
||||||
{
|
{
|
||||||
splice
|
splice
|
||||||
.to_insert
|
.to_insert
|
||||||
.push(Inlay::hint(new_inlay_id, new_hint_position, &new_hint));
|
.push(Inlay::hint(new_inlay_id, new_hint_position, &new_hint));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let new_id = InlayId::Hint(new_inlay_id);
|
let new_id = InlayId::Hint(new_inlay_id);
|
||||||
cached_excerpt_hints.hints_by_id.insert(new_id, new_hint);
|
cached_excerpt_hints.hints_by_id.insert(new_id, new_hint);
|
||||||
if cached_excerpt_hints.ordered_hints.len() <= insert_position {
|
if cached_excerpt_hints.ordered_hints.len() <= insert_position {
|
||||||
|
|
|
@ -930,11 +930,11 @@ impl Item for Editor {
|
||||||
})?;
|
})?;
|
||||||
buffer
|
buffer
|
||||||
.update(cx, |buffer, cx| {
|
.update(cx, |buffer, cx| {
|
||||||
if let Some(transaction) = transaction {
|
if let Some(transaction) = transaction
|
||||||
if !buffer.is_singleton() {
|
&& !buffer.is_singleton()
|
||||||
|
{
|
||||||
buffer.push_transaction(&transaction.0, cx);
|
buffer.push_transaction(&transaction.0, cx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1374,9 +1374,8 @@ impl ProjectItem for Editor {
|
||||||
let mut editor = Self::for_buffer(buffer.clone(), Some(project), window, cx);
|
let mut editor = Self::for_buffer(buffer.clone(), Some(project), window, cx);
|
||||||
if let Some((excerpt_id, buffer_id, snapshot)) =
|
if let Some((excerpt_id, buffer_id, snapshot)) =
|
||||||
editor.buffer().read(cx).snapshot(cx).as_singleton()
|
editor.buffer().read(cx).snapshot(cx).as_singleton()
|
||||||
{
|
&& WorkspaceSettings::get(None, cx).restore_on_file_reopen
|
||||||
if WorkspaceSettings::get(None, cx).restore_on_file_reopen {
|
&& let Some(restoration_data) = Self::project_item_kind()
|
||||||
if let Some(restoration_data) = Self::project_item_kind()
|
|
||||||
.and_then(|kind| pane.as_ref()?.project_item_restoration_data.get(&kind))
|
.and_then(|kind| pane.as_ref()?.project_item_restoration_data.get(&kind))
|
||||||
.and_then(|data| data.downcast_ref::<EditorRestorationData>())
|
.and_then(|data| data.downcast_ref::<EditorRestorationData>())
|
||||||
.and_then(|data| {
|
.and_then(|data| {
|
||||||
|
@ -1403,8 +1402,6 @@ impl ProjectItem for Editor {
|
||||||
);
|
);
|
||||||
editor.set_scroll_anchor(ScrollAnchor { anchor, offset }, window, cx);
|
editor.set_scroll_anchor(ScrollAnchor { anchor, offset }, window, cx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
editor
|
editor
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,13 +51,12 @@ pub(crate) fn should_auto_close(
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let mut jsx_open_tag_node = node;
|
let mut jsx_open_tag_node = node;
|
||||||
if node.grammar_name() != config.open_tag_node_name {
|
if node.grammar_name() != config.open_tag_node_name
|
||||||
if let Some(parent) = node.parent() {
|
&& let Some(parent) = node.parent()
|
||||||
if parent.grammar_name() == config.open_tag_node_name {
|
&& parent.grammar_name() == config.open_tag_node_name
|
||||||
|
{
|
||||||
jsx_open_tag_node = parent;
|
jsx_open_tag_node = parent;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
if jsx_open_tag_node.grammar_name() != config.open_tag_node_name {
|
if jsx_open_tag_node.grammar_name() != config.open_tag_node_name {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -284,11 +283,9 @@ pub(crate) fn generate_auto_close_edits(
|
||||||
unclosed_open_tag_count -= 1;
|
unclosed_open_tag_count -= 1;
|
||||||
}
|
}
|
||||||
} else if has_erroneous_close_tag && kind == erroneous_close_tag_node_name {
|
} else if has_erroneous_close_tag && kind == erroneous_close_tag_node_name {
|
||||||
if tag_node_name_equals(&node, &tag_name) {
|
if tag_node_name_equals(&node, &tag_name) && !is_after_open_tag(&node) {
|
||||||
if !is_after_open_tag(&node) {
|
|
||||||
unclosed_open_tag_count -= 1;
|
unclosed_open_tag_count -= 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else if kind == config.jsx_element_node_name {
|
} else if kind == config.jsx_element_node_name {
|
||||||
// perf: filter only open,close,element,erroneous nodes
|
// perf: filter only open,close,element,erroneous nodes
|
||||||
stack.extend(node.children(&mut cursor));
|
stack.extend(node.children(&mut cursor));
|
||||||
|
|
|
@ -147,8 +147,8 @@ pub fn lsp_tasks(
|
||||||
},
|
},
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
}) {
|
}) && let Some(new_runnables) = runnables_task.await.log_err()
|
||||||
if let Some(new_runnables) = runnables_task.await.log_err() {
|
{
|
||||||
new_lsp_tasks.extend(new_runnables.runnables.into_iter().filter_map(
|
new_lsp_tasks.extend(new_runnables.runnables.into_iter().filter_map(
|
||||||
|(location, runnable)| {
|
|(location, runnable)| {
|
||||||
let resolved_task =
|
let resolved_task =
|
||||||
|
@ -157,7 +157,6 @@ pub fn lsp_tasks(
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
lsp_tasks
|
lsp_tasks
|
||||||
.entry(source_kind)
|
.entry(source_kind)
|
||||||
.or_insert_with(Vec::new)
|
.or_insert_with(Vec::new)
|
||||||
|
|
|
@ -510,11 +510,11 @@ pub fn find_preceding_boundary_point(
|
||||||
if find_range == FindRange::SingleLine && ch == '\n' {
|
if find_range == FindRange::SingleLine && ch == '\n' {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if let Some(prev_ch) = prev_ch {
|
if let Some(prev_ch) = prev_ch
|
||||||
if is_boundary(ch, prev_ch) {
|
&& is_boundary(ch, prev_ch)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
offset -= ch.len_utf8();
|
offset -= ch.len_utf8();
|
||||||
prev_ch = Some(ch);
|
prev_ch = Some(ch);
|
||||||
|
@ -562,15 +562,15 @@ pub fn find_boundary_point(
|
||||||
if find_range == FindRange::SingleLine && ch == '\n' {
|
if find_range == FindRange::SingleLine && ch == '\n' {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if let Some(prev_ch) = prev_ch {
|
if let Some(prev_ch) = prev_ch
|
||||||
if is_boundary(prev_ch, ch) {
|
&& is_boundary(prev_ch, ch)
|
||||||
|
{
|
||||||
if return_point_before_boundary {
|
if return_point_before_boundary {
|
||||||
return map.clip_point(prev_offset.to_display_point(map), Bias::Right);
|
return map.clip_point(prev_offset.to_display_point(map), Bias::Right);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
prev_offset = offset;
|
prev_offset = offset;
|
||||||
offset += ch.len_utf8();
|
offset += ch.len_utf8();
|
||||||
prev_ch = Some(ch);
|
prev_ch = Some(ch);
|
||||||
|
@ -603,15 +603,15 @@ pub fn find_preceding_boundary_trail(
|
||||||
// Find the boundary
|
// Find the boundary
|
||||||
let start_offset = offset;
|
let start_offset = offset;
|
||||||
for ch in forward {
|
for ch in forward {
|
||||||
if let Some(prev_ch) = prev_ch {
|
if let Some(prev_ch) = prev_ch
|
||||||
if is_boundary(prev_ch, ch) {
|
&& is_boundary(prev_ch, ch)
|
||||||
|
{
|
||||||
if start_offset == offset {
|
if start_offset == offset {
|
||||||
trail_offset = Some(offset);
|
trail_offset = Some(offset);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
offset -= ch.len_utf8();
|
offset -= ch.len_utf8();
|
||||||
prev_ch = Some(ch);
|
prev_ch = Some(ch);
|
||||||
}
|
}
|
||||||
|
@ -651,15 +651,15 @@ pub fn find_boundary_trail(
|
||||||
// Find the boundary
|
// Find the boundary
|
||||||
let start_offset = offset;
|
let start_offset = offset;
|
||||||
for ch in forward {
|
for ch in forward {
|
||||||
if let Some(prev_ch) = prev_ch {
|
if let Some(prev_ch) = prev_ch
|
||||||
if is_boundary(prev_ch, ch) {
|
&& is_boundary(prev_ch, ch)
|
||||||
|
{
|
||||||
if start_offset == offset {
|
if start_offset == offset {
|
||||||
trail_offset = Some(offset);
|
trail_offset = Some(offset);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
offset += ch.len_utf8();
|
offset += ch.len_utf8();
|
||||||
prev_ch = Some(ch);
|
prev_ch = Some(ch);
|
||||||
}
|
}
|
||||||
|
|
|
@ -285,12 +285,12 @@ pub fn open_docs(editor: &mut Editor, _: &OpenDocs, window: &mut Window, cx: &mu
|
||||||
workspace.update(cx, |_workspace, cx| {
|
workspace.update(cx, |_workspace, cx| {
|
||||||
// Check if the local document exists, otherwise fallback to the online document.
|
// Check if the local document exists, otherwise fallback to the online document.
|
||||||
// Open with the default browser.
|
// Open with the default browser.
|
||||||
if let Some(local_url) = docs_urls.local {
|
if let Some(local_url) = docs_urls.local
|
||||||
if fs::metadata(Path::new(&local_url[8..])).is_ok() {
|
&& fs::metadata(Path::new(&local_url[8..])).is_ok()
|
||||||
|
{
|
||||||
cx.open_url(&local_url);
|
cx.open_url(&local_url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(web_url) = docs_urls.web {
|
if let Some(web_url) = docs_urls.web {
|
||||||
cx.open_url(&web_url);
|
cx.open_url(&web_url);
|
||||||
|
|
|
@ -703,21 +703,21 @@ impl Editor {
|
||||||
if matches!(
|
if matches!(
|
||||||
settings.defaults.soft_wrap,
|
settings.defaults.soft_wrap,
|
||||||
SoftWrap::PreferredLineLength | SoftWrap::Bounded
|
SoftWrap::PreferredLineLength | SoftWrap::Bounded
|
||||||
) {
|
) && (settings.defaults.preferred_line_length as f32) < visible_column_count
|
||||||
if (settings.defaults.preferred_line_length as f32) < visible_column_count {
|
{
|
||||||
visible_column_count = settings.defaults.preferred_line_length as f32;
|
visible_column_count = settings.defaults.preferred_line_length as f32;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If the scroll position is currently at the left edge of the document
|
// If the scroll position is currently at the left edge of the document
|
||||||
// (x == 0.0) and the intent is to scroll right, the gutter's margin
|
// (x == 0.0) and the intent is to scroll right, the gutter's margin
|
||||||
// should first be added to the current position, otherwise the cursor
|
// should first be added to the current position, otherwise the cursor
|
||||||
// will end at the column position minus the margin, which looks off.
|
// will end at the column position minus the margin, which looks off.
|
||||||
if current_position.x == 0.0 && amount.columns(visible_column_count) > 0. {
|
if current_position.x == 0.0
|
||||||
if let Some(last_position_map) = &self.last_position_map {
|
&& amount.columns(visible_column_count) > 0.
|
||||||
|
&& let Some(last_position_map) = &self.last_position_map
|
||||||
|
{
|
||||||
current_position.x += self.gutter_dimensions.margin / last_position_map.em_advance;
|
current_position.x += self.gutter_dimensions.margin / last_position_map.em_advance;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let new_position = current_position
|
let new_position = current_position
|
||||||
+ point(
|
+ point(
|
||||||
amount.columns(visible_column_count),
|
amount.columns(visible_column_count),
|
||||||
|
@ -749,13 +749,11 @@ impl Editor {
|
||||||
|
|
||||||
if let (Some(visible_lines), Some(visible_columns)) =
|
if let (Some(visible_lines), Some(visible_columns)) =
|
||||||
(self.visible_line_count(), self.visible_column_count())
|
(self.visible_line_count(), self.visible_column_count())
|
||||||
{
|
&& newest_head.row() <= DisplayRow(screen_top.row().0 + visible_lines as u32)
|
||||||
if newest_head.row() <= DisplayRow(screen_top.row().0 + visible_lines as u32)
|
|
||||||
&& newest_head.column() <= screen_top.column() + visible_columns as u32
|
&& newest_head.column() <= screen_top.column() + visible_columns as u32
|
||||||
{
|
{
|
||||||
return Ordering::Equal;
|
return Ordering::Equal;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ordering::Greater
|
Ordering::Greater
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,14 +116,14 @@ impl Editor {
|
||||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
let mut scroll_position = self.scroll_manager.scroll_position(&display_map);
|
let mut scroll_position = self.scroll_manager.scroll_position(&display_map);
|
||||||
let original_y = scroll_position.y;
|
let original_y = scroll_position.y;
|
||||||
if let Some(last_bounds) = self.expect_bounds_change.take() {
|
if let Some(last_bounds) = self.expect_bounds_change.take()
|
||||||
if scroll_position.y != 0. {
|
&& scroll_position.y != 0.
|
||||||
|
{
|
||||||
scroll_position.y += (bounds.top() - last_bounds.top()) / line_height;
|
scroll_position.y += (bounds.top() - last_bounds.top()) / line_height;
|
||||||
if scroll_position.y < 0. {
|
if scroll_position.y < 0. {
|
||||||
scroll_position.y = 0.;
|
scroll_position.y = 0.;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if scroll_position.y > max_scroll_top {
|
if scroll_position.y > max_scroll_top {
|
||||||
scroll_position.y = max_scroll_top;
|
scroll_position.y = max_scroll_top;
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,10 +184,10 @@ pub fn editor_content_with_blocks(editor: &Entity<Editor>, cx: &mut VisualTestCo
|
||||||
for (row, block) in blocks {
|
for (row, block) in blocks {
|
||||||
match block {
|
match block {
|
||||||
Block::Custom(custom_block) => {
|
Block::Custom(custom_block) => {
|
||||||
if let BlockPlacement::Near(x) = &custom_block.placement {
|
if let BlockPlacement::Near(x) = &custom_block.placement
|
||||||
if snapshot.intersects_fold(x.to_point(&snapshot.buffer_snapshot)) {
|
&& snapshot.intersects_fold(x.to_point(&snapshot.buffer_snapshot))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let content = block_content_for_tests(editor, custom_block.id, cx)
|
let content = block_content_for_tests(editor, custom_block.id, cx)
|
||||||
.expect("block content not found");
|
.expect("block content not found");
|
||||||
|
|
|
@ -167,15 +167,14 @@ fn main() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(language) = meta.language_server {
|
if let Some(language) = meta.language_server
|
||||||
if !languages.contains(&language.file_extension) {
|
&& !languages.contains(&language.file_extension) {
|
||||||
panic!(
|
panic!(
|
||||||
"Eval for {:?} could not be run because no language server was found for extension {:?}",
|
"Eval for {:?} could not be run because no language server was found for extension {:?}",
|
||||||
meta.name,
|
meta.name,
|
||||||
language.file_extension
|
language.file_extension
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This creates a worktree per repetition. Ideally these examples should
|
// TODO: This creates a worktree per repetition. Ideally these examples should
|
||||||
// either be run sequentially on the same worktree, or reuse worktrees when there
|
// either be run sequentially on the same worktree, or reuse worktrees when there
|
||||||
|
|
|
@ -46,28 +46,26 @@ fn find_target_files_recursive(
|
||||||
max_depth,
|
max_depth,
|
||||||
found_files,
|
found_files,
|
||||||
)?;
|
)?;
|
||||||
} else if path.is_file() {
|
} else if path.is_file()
|
||||||
if let Some(filename_osstr) = path.file_name() {
|
&& let Some(filename_osstr) = path.file_name()
|
||||||
if let Some(filename_str) = filename_osstr.to_str() {
|
&& let Some(filename_str) = filename_osstr.to_str()
|
||||||
if filename_str == target_filename {
|
&& filename_str == target_filename
|
||||||
|
{
|
||||||
found_files.push(path);
|
found_files.push(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_explorer_html(input_paths: &[PathBuf], output_path: &PathBuf) -> Result<String> {
|
pub fn generate_explorer_html(input_paths: &[PathBuf], output_path: &PathBuf) -> Result<String> {
|
||||||
if let Some(parent) = output_path.parent() {
|
if let Some(parent) = output_path.parent()
|
||||||
if !parent.exists() {
|
&& !parent.exists()
|
||||||
|
{
|
||||||
fs::create_dir_all(parent).context(format!(
|
fs::create_dir_all(parent).context(format!(
|
||||||
"Failed to create output directory: {}",
|
"Failed to create output directory: {}",
|
||||||
parent.display()
|
parent.display()
|
||||||
))?;
|
))?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let template_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/explorer.html");
|
let template_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/explorer.html");
|
||||||
let template_content = fs::read_to_string(&template_path).context(format!(
|
let template_content = fs::read_to_string(&template_path).context(format!(
|
||||||
|
|
|
@ -376,11 +376,10 @@ impl ExampleInstance {
|
||||||
);
|
);
|
||||||
let result = this.thread.conversation(&mut example_cx).await;
|
let result = this.thread.conversation(&mut example_cx).await;
|
||||||
|
|
||||||
if let Err(err) = result {
|
if let Err(err) = result
|
||||||
if !err.is::<FailedAssertion>() {
|
&& !err.is::<FailedAssertion>() {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
println!("{}Stopped", this.log_prefix);
|
println!("{}Stopped", this.log_prefix);
|
||||||
|
|
||||||
|
|
|
@ -178,8 +178,8 @@ pub fn parse_wasm_extension_version(
|
||||||
for part in wasmparser::Parser::new(0).parse_all(wasm_bytes) {
|
for part in wasmparser::Parser::new(0).parse_all(wasm_bytes) {
|
||||||
if let wasmparser::Payload::CustomSection(s) =
|
if let wasmparser::Payload::CustomSection(s) =
|
||||||
part.context("error parsing wasm extension")?
|
part.context("error parsing wasm extension")?
|
||||||
|
&& s.name() == "zed:api-version"
|
||||||
{
|
{
|
||||||
if s.name() == "zed:api-version" {
|
|
||||||
version = parse_wasm_extension_version_custom_section(s.data());
|
version = parse_wasm_extension_version_custom_section(s.data());
|
||||||
if version.is_none() {
|
if version.is_none() {
|
||||||
bail!(
|
bail!(
|
||||||
|
@ -190,7 +190,6 @@ pub fn parse_wasm_extension_version(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// The reason we wait until we're done parsing all of the Wasm bytes to return the version
|
// The reason we wait until we're done parsing all of the Wasm bytes to return the version
|
||||||
// is to work around a panic that can happen inside of Wasmtime when the bytes are invalid.
|
// is to work around a panic that can happen inside of Wasmtime when the bytes are invalid.
|
||||||
|
|
|
@ -93,11 +93,10 @@ pub fn is_version_compatible(
|
||||||
.wasm_api_version
|
.wasm_api_version
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|wasm_api_version| SemanticVersion::from_str(wasm_api_version).ok())
|
.and_then(|wasm_api_version| SemanticVersion::from_str(wasm_api_version).ok())
|
||||||
|
&& !is_supported_wasm_api_version(release_channel, wasm_api_version)
|
||||||
{
|
{
|
||||||
if !is_supported_wasm_api_version(release_channel, wasm_api_version) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -292,21 +291,19 @@ impl ExtensionStore {
|
||||||
// it must be asynchronously rebuilt.
|
// it must be asynchronously rebuilt.
|
||||||
let mut extension_index = ExtensionIndex::default();
|
let mut extension_index = ExtensionIndex::default();
|
||||||
let mut extension_index_needs_rebuild = true;
|
let mut extension_index_needs_rebuild = true;
|
||||||
if let Ok(index_content) = index_content {
|
if let Ok(index_content) = index_content
|
||||||
if let Some(index) = serde_json::from_str(&index_content).log_err() {
|
&& let Some(index) = serde_json::from_str(&index_content).log_err()
|
||||||
|
{
|
||||||
extension_index = index;
|
extension_index = index;
|
||||||
if let (Ok(Some(index_metadata)), Ok(Some(extensions_metadata))) =
|
if let (Ok(Some(index_metadata)), Ok(Some(extensions_metadata))) =
|
||||||
(index_metadata, extensions_metadata)
|
(index_metadata, extensions_metadata)
|
||||||
{
|
&& index_metadata
|
||||||
if index_metadata
|
|
||||||
.mtime
|
.mtime
|
||||||
.bad_is_greater_than(extensions_metadata.mtime)
|
.bad_is_greater_than(extensions_metadata.mtime)
|
||||||
{
|
{
|
||||||
extension_index_needs_rebuild = false;
|
extension_index_needs_rebuild = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Immediately load all of the extensions in the initial manifest. If the
|
// Immediately load all of the extensions in the initial manifest. If the
|
||||||
// index needs to be rebuild, then enqueue
|
// index needs to be rebuild, then enqueue
|
||||||
|
@ -392,14 +389,13 @@ impl ExtensionStore {
|
||||||
|
|
||||||
if let Some(path::Component::Normal(extension_dir_name)) =
|
if let Some(path::Component::Normal(extension_dir_name)) =
|
||||||
event_path.components().next()
|
event_path.components().next()
|
||||||
|
&& let Some(extension_id) = extension_dir_name.to_str()
|
||||||
{
|
{
|
||||||
if let Some(extension_id) = extension_dir_name.to_str() {
|
|
||||||
reload_tx.unbounded_send(Some(extension_id.into())).ok();
|
reload_tx.unbounded_send(Some(extension_id.into())).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this
|
this
|
||||||
|
@ -763,8 +759,8 @@ impl ExtensionStore {
|
||||||
if let ExtensionOperation::Install = operation {
|
if let ExtensionOperation::Install = operation {
|
||||||
this.update( cx, |this, cx| {
|
this.update( cx, |this, cx| {
|
||||||
cx.emit(Event::ExtensionInstalled(extension_id.clone()));
|
cx.emit(Event::ExtensionInstalled(extension_id.clone()));
|
||||||
if let Some(events) = ExtensionEvents::try_global(cx) {
|
if let Some(events) = ExtensionEvents::try_global(cx)
|
||||||
if let Some(manifest) = this.extension_manifest_for_id(&extension_id) {
|
&& let Some(manifest) = this.extension_manifest_for_id(&extension_id) {
|
||||||
events.update(cx, |this, cx| {
|
events.update(cx, |this, cx| {
|
||||||
this.emit(
|
this.emit(
|
||||||
extension::Event::ExtensionInstalled(manifest.clone()),
|
extension::Event::ExtensionInstalled(manifest.clone()),
|
||||||
|
@ -772,7 +768,6 @@ impl ExtensionStore {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
@ -912,13 +907,13 @@ impl ExtensionStore {
|
||||||
|
|
||||||
extension_store.update(cx, |_, cx| {
|
extension_store.update(cx, |_, cx| {
|
||||||
cx.emit(Event::ExtensionUninstalled(extension_id.clone()));
|
cx.emit(Event::ExtensionUninstalled(extension_id.clone()));
|
||||||
if let Some(events) = ExtensionEvents::try_global(cx) {
|
if let Some(events) = ExtensionEvents::try_global(cx)
|
||||||
if let Some(manifest) = extension_manifest {
|
&& let Some(manifest) = extension_manifest
|
||||||
|
{
|
||||||
events.update(cx, |this, cx| {
|
events.update(cx, |this, cx| {
|
||||||
this.emit(extension::Event::ExtensionUninstalled(manifest.clone()), cx)
|
this.emit(extension::Event::ExtensionUninstalled(manifest.clone()), cx)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
anyhow::Ok(())
|
anyhow::Ok(())
|
||||||
|
@ -997,13 +992,13 @@ impl ExtensionStore {
|
||||||
this.update(cx, |this, cx| this.reload(None, cx))?.await;
|
this.update(cx, |this, cx| this.reload(None, cx))?.await;
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
cx.emit(Event::ExtensionInstalled(extension_id.clone()));
|
cx.emit(Event::ExtensionInstalled(extension_id.clone()));
|
||||||
if let Some(events) = ExtensionEvents::try_global(cx) {
|
if let Some(events) = ExtensionEvents::try_global(cx)
|
||||||
if let Some(manifest) = this.extension_manifest_for_id(&extension_id) {
|
&& let Some(manifest) = this.extension_manifest_for_id(&extension_id)
|
||||||
|
{
|
||||||
events.update(cx, |this, cx| {
|
events.update(cx, |this, cx| {
|
||||||
this.emit(extension::Event::ExtensionInstalled(manifest.clone()), cx)
|
this.emit(extension::Event::ExtensionInstalled(manifest.clone()), cx)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1788,11 +1783,11 @@ impl ExtensionStore {
|
||||||
let connection_options = client.read(cx).connection_options();
|
let connection_options = client.read(cx).connection_options();
|
||||||
let ssh_url = connection_options.ssh_url();
|
let ssh_url = connection_options.ssh_url();
|
||||||
|
|
||||||
if let Some(existing_client) = self.ssh_clients.get(&ssh_url) {
|
if let Some(existing_client) = self.ssh_clients.get(&ssh_url)
|
||||||
if existing_client.upgrade().is_some() {
|
&& existing_client.upgrade().is_some()
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.ssh_clients.insert(ssh_url, client.downgrade());
|
self.ssh_clients.insert(ssh_url, client.downgrade());
|
||||||
self.ssh_registered_tx.unbounded_send(()).ok();
|
self.ssh_registered_tx.unbounded_send(()).ok();
|
||||||
|
|
|
@ -701,8 +701,8 @@ pub fn parse_wasm_extension_version(
|
||||||
for part in wasmparser::Parser::new(0).parse_all(wasm_bytes) {
|
for part in wasmparser::Parser::new(0).parse_all(wasm_bytes) {
|
||||||
if let wasmparser::Payload::CustomSection(s) =
|
if let wasmparser::Payload::CustomSection(s) =
|
||||||
part.context("error parsing wasm extension")?
|
part.context("error parsing wasm extension")?
|
||||||
|
&& s.name() == "zed:api-version"
|
||||||
{
|
{
|
||||||
if s.name() == "zed:api-version" {
|
|
||||||
version = parse_wasm_extension_version_custom_section(s.data());
|
version = parse_wasm_extension_version_custom_section(s.data());
|
||||||
if version.is_none() {
|
if version.is_none() {
|
||||||
bail!(
|
bail!(
|
||||||
|
@ -713,7 +713,6 @@ pub fn parse_wasm_extension_version(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// The reason we wait until we're done parsing all of the Wasm bytes to return the version
|
// The reason we wait until we're done parsing all of the Wasm bytes to return the version
|
||||||
// is to work around a panic that can happen inside of Wasmtime when the bytes are invalid.
|
// is to work around a panic that can happen inside of Wasmtime when the bytes are invalid.
|
||||||
|
|
|
@ -1031,8 +1031,8 @@ impl ExtensionsPage {
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.extension_manifest_for_id(&extension_id)
|
.extension_manifest_for_id(&extension_id)
|
||||||
.cloned()
|
.cloned()
|
||||||
|
&& let Some(events) = extension::ExtensionEvents::try_global(cx)
|
||||||
{
|
{
|
||||||
if let Some(events) = extension::ExtensionEvents::try_global(cx) {
|
|
||||||
events.update(cx, |this, cx| {
|
events.update(cx, |this, cx| {
|
||||||
this.emit(
|
this.emit(
|
||||||
extension::Event::ConfigureExtensionRequested(manifest),
|
extension::Event::ConfigureExtensionRequested(manifest),
|
||||||
|
@ -1041,7 +1041,6 @@ impl ExtensionsPage {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
upgrade: if installed_version == extension.manifest.version {
|
upgrade: if installed_version == extension.manifest.version {
|
||||||
|
|
|
@ -209,13 +209,13 @@ impl FileFinder {
|
||||||
let Some(init_modifiers) = self.init_modifiers.take() else {
|
let Some(init_modifiers) = self.init_modifiers.take() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if self.picker.read(cx).delegate.has_changed_selected_index {
|
if self.picker.read(cx).delegate.has_changed_selected_index
|
||||||
if !event.modified() || !init_modifiers.is_subset_of(event) {
|
&& (!event.modified() || !init_modifiers.is_subset_of(event))
|
||||||
|
{
|
||||||
self.init_modifiers = None;
|
self.init_modifiers = None;
|
||||||
window.dispatch_action(menu::Confirm.boxed_clone(), cx);
|
window.dispatch_action(menu::Confirm.boxed_clone(), cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_select_prev(
|
fn handle_select_prev(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -323,8 +323,9 @@ impl FileFinder {
|
||||||
) {
|
) {
|
||||||
self.picker.update(cx, |picker, cx| {
|
self.picker.update(cx, |picker, cx| {
|
||||||
let delegate = &mut picker.delegate;
|
let delegate = &mut picker.delegate;
|
||||||
if let Some(workspace) = delegate.workspace.upgrade() {
|
if let Some(workspace) = delegate.workspace.upgrade()
|
||||||
if let Some(m) = delegate.matches.get(delegate.selected_index()) {
|
&& let Some(m) = delegate.matches.get(delegate.selected_index())
|
||||||
|
{
|
||||||
let path = match &m {
|
let path = match &m {
|
||||||
Match::History { path, .. } => {
|
Match::History { path, .. } => {
|
||||||
let worktree_id = path.project.worktree_id;
|
let worktree_id = path.project.worktree_id;
|
||||||
|
@ -344,7 +345,6 @@ impl FileFinder {
|
||||||
});
|
});
|
||||||
open_task.detach_and_log_err(cx);
|
open_task.detach_and_log_err(cx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,8 +675,9 @@ impl Matches {
|
||||||
let path_str = panel_match.0.path.to_string_lossy();
|
let path_str = panel_match.0.path.to_string_lossy();
|
||||||
let filename_str = filename.to_string_lossy();
|
let filename_str = filename.to_string_lossy();
|
||||||
|
|
||||||
if let Some(filename_pos) = path_str.rfind(&*filename_str) {
|
if let Some(filename_pos) = path_str.rfind(&*filename_str)
|
||||||
if panel_match.0.positions[0] >= filename_pos {
|
&& panel_match.0.positions[0] >= filename_pos
|
||||||
|
{
|
||||||
let mut prev_position = panel_match.0.positions[0];
|
let mut prev_position = panel_match.0.positions[0];
|
||||||
for p in &panel_match.0.positions[1..] {
|
for p in &panel_match.0.positions[1..] {
|
||||||
if *p != prev_position + 1 {
|
if *p != prev_position + 1 {
|
||||||
|
@ -687,7 +688,6 @@ impl Matches {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -1045,11 +1045,11 @@ impl FileFinderDelegate {
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let mut path = Arc::clone(project_relative_path);
|
let mut path = Arc::clone(project_relative_path);
|
||||||
if project_relative_path.as_ref() == Path::new("") {
|
if project_relative_path.as_ref() == Path::new("")
|
||||||
if let Some(absolute_path) = &entry_path.absolute {
|
&& let Some(absolute_path) = &entry_path.absolute
|
||||||
|
{
|
||||||
path = Arc::from(absolute_path.as_path());
|
path = Arc::from(absolute_path.as_path());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut path_match = PathMatch {
|
let mut path_match = PathMatch {
|
||||||
score: ix as f64,
|
score: ix as f64,
|
||||||
|
@ -1078,11 +1078,11 @@ impl FileFinderDelegate {
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
if file_name_positions.is_empty() {
|
if file_name_positions.is_empty()
|
||||||
if let Some(user_home_path) = std::env::var("HOME").ok() {
|
&& let Some(user_home_path) = std::env::var("HOME").ok()
|
||||||
|
{
|
||||||
let user_home_path = user_home_path.trim();
|
let user_home_path = user_home_path.trim();
|
||||||
if !user_home_path.is_empty() {
|
if !user_home_path.is_empty() && full_path.starts_with(user_home_path) {
|
||||||
if full_path.starts_with(user_home_path) {
|
|
||||||
full_path.replace_range(0..user_home_path.len(), "~");
|
full_path.replace_range(0..user_home_path.len(), "~");
|
||||||
full_path_positions.retain_mut(|pos| {
|
full_path_positions.retain_mut(|pos| {
|
||||||
if *pos >= user_home_path.len() {
|
if *pos >= user_home_path.len() {
|
||||||
|
@ -1095,8 +1095,6 @@ impl FileFinderDelegate {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if full_path.is_ascii() {
|
if full_path.is_ascii() {
|
||||||
let file_finder_settings = FileFinderSettings::get_global(cx);
|
let file_finder_settings = FileFinderSettings::get_global(cx);
|
||||||
|
@ -1242,16 +1240,15 @@ impl FileFinderDelegate {
|
||||||
|
|
||||||
/// Skips first history match (that is displayed topmost) if it's currently opened.
|
/// Skips first history match (that is displayed topmost) if it's currently opened.
|
||||||
fn calculate_selected_index(&self, cx: &mut Context<Picker<Self>>) -> usize {
|
fn calculate_selected_index(&self, cx: &mut Context<Picker<Self>>) -> usize {
|
||||||
if FileFinderSettings::get_global(cx).skip_focus_for_active_in_search {
|
if FileFinderSettings::get_global(cx).skip_focus_for_active_in_search
|
||||||
if let Some(Match::History { path, .. }) = self.matches.get(0) {
|
&& let Some(Match::History { path, .. }) = self.matches.get(0)
|
||||||
if Some(path) == self.currently_opened_path.as_ref() {
|
&& Some(path) == self.currently_opened_path.as_ref()
|
||||||
|
{
|
||||||
let elements_after_first = self.matches.len() - 1;
|
let elements_after_first = self.matches.len() - 1;
|
||||||
if elements_after_first > 0 {
|
if elements_after_first > 0 {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -1310,12 +1307,12 @@ impl PickerDelegate for FileFinderDelegate {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_, m)| !matches!(m, Match::History { .. }))
|
.find(|(_, m)| !matches!(m, Match::History { .. }))
|
||||||
.map(|(i, _)| i);
|
.map(|(i, _)| i);
|
||||||
if let Some(first_non_history_index) = first_non_history_index {
|
if let Some(first_non_history_index) = first_non_history_index
|
||||||
if first_non_history_index > 0 {
|
&& first_non_history_index > 0
|
||||||
|
{
|
||||||
return vec![first_non_history_index - 1];
|
return vec![first_non_history_index - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1436,8 +1433,9 @@ impl PickerDelegate for FileFinderDelegate {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Picker<FileFinderDelegate>>,
|
cx: &mut Context<Picker<FileFinderDelegate>>,
|
||||||
) {
|
) {
|
||||||
if let Some(m) = self.matches.get(self.selected_index()) {
|
if let Some(m) = self.matches.get(self.selected_index())
|
||||||
if let Some(workspace) = self.workspace.upgrade() {
|
&& let Some(workspace) = self.workspace.upgrade()
|
||||||
|
{
|
||||||
let open_task = workspace.update(cx, |workspace, cx| {
|
let open_task = workspace.update(cx, |workspace, cx| {
|
||||||
let split_or_open =
|
let split_or_open =
|
||||||
|workspace: &mut Workspace,
|
|workspace: &mut Workspace,
|
||||||
|
@ -1568,20 +1566,16 @@ impl PickerDelegate for FileFinderDelegate {
|
||||||
|
|
||||||
cx.spawn_in(window, async move |_, cx| {
|
cx.spawn_in(window, async move |_, cx| {
|
||||||
let item = open_task.await.notify_async_err(cx)?;
|
let item = open_task.await.notify_async_err(cx)?;
|
||||||
if let Some(row) = row {
|
if let Some(row) = row
|
||||||
if let Some(active_editor) = item.downcast::<Editor>() {
|
&& let Some(active_editor) = item.downcast::<Editor>()
|
||||||
|
{
|
||||||
active_editor
|
active_editor
|
||||||
.downgrade()
|
.downgrade()
|
||||||
.update_in(cx, |editor, window, cx| {
|
.update_in(cx, |editor, window, cx| {
|
||||||
editor.go_to_singleton_buffer_point(
|
editor.go_to_singleton_buffer_point(Point::new(row, col), window, cx);
|
||||||
Point::new(row, col),
|
|
||||||
window,
|
|
||||||
cx,
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
.log_err();
|
.log_err();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
finder.update(cx, |_, cx| cx.emit(DismissEvent)).ok()?;
|
finder.update(cx, |_, cx| cx.emit(DismissEvent)).ok()?;
|
||||||
|
|
||||||
Some(())
|
Some(())
|
||||||
|
@ -1589,7 +1583,6 @@ impl PickerDelegate for FileFinderDelegate {
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<FileFinderDelegate>>) {
|
fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<FileFinderDelegate>>) {
|
||||||
self.file_finder
|
self.file_finder
|
||||||
|
|
|
@ -75,8 +75,9 @@ impl OpenPathDelegate {
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let mut i = selected_match_index;
|
let mut i = selected_match_index;
|
||||||
if let Some(user_input) = user_input {
|
if let Some(user_input) = user_input
|
||||||
if !user_input.exists || !user_input.is_dir {
|
&& (!user_input.exists || !user_input.is_dir)
|
||||||
|
{
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
return Some(CandidateInfo {
|
return Some(CandidateInfo {
|
||||||
path: user_input.file.clone(),
|
path: user_input.file.clone(),
|
||||||
|
@ -86,7 +87,6 @@ impl OpenPathDelegate {
|
||||||
i -= 1;
|
i -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let id = self.string_matches.get(i)?.candidate_id;
|
let id = self.string_matches.get(i)?.candidate_id;
|
||||||
entries.iter().find(|entry| entry.path.id == id).cloned()
|
entries.iter().find(|entry| entry.path.id == id).cloned()
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue