Ensure context inserted via commands is syntax-highlighted (#13133)
Release Notes: - N/A
This commit is contained in:
parent
bedf57db89
commit
2b46a4a0e9
4 changed files with 61 additions and 47 deletions
|
@ -1,10 +1,13 @@
|
||||||
use super::{file_command::FilePlaceholder, SlashCommand, SlashCommandOutput};
|
use super::{
|
||||||
|
file_command::{codeblock_fence_for_path, FilePlaceholder},
|
||||||
|
SlashCommand, SlashCommandOutput,
|
||||||
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use assistant_slash_command::SlashCommandOutputSection;
|
use assistant_slash_command::SlashCommandOutputSection;
|
||||||
use editor::Editor;
|
use editor::Editor;
|
||||||
use gpui::{AppContext, Task, WeakView};
|
use gpui::{AppContext, Task, WeakView};
|
||||||
use language::LspAdapterDelegate;
|
use language::LspAdapterDelegate;
|
||||||
use std::{borrow::Cow, sync::Arc};
|
use std::sync::Arc;
|
||||||
use ui::{IntoElement, WindowContext};
|
use ui::{IntoElement, WindowContext};
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
|
||||||
|
@ -60,14 +63,8 @@ impl SlashCommand for ActiveSlashCommand {
|
||||||
let text = cx.background_executor().spawn({
|
let text = cx.background_executor().spawn({
|
||||||
let path = path.clone();
|
let path = path.clone();
|
||||||
async move {
|
async move {
|
||||||
let path = path
|
let mut output = String::new();
|
||||||
.as_ref()
|
output.push_str(&codeblock_fence_for_path(path.as_deref(), None));
|
||||||
.map(|path| path.to_string_lossy())
|
|
||||||
.unwrap_or_else(|| Cow::Borrowed("untitled"));
|
|
||||||
|
|
||||||
let mut output = String::with_capacity(path.len() + snapshot.len() + 9);
|
|
||||||
output.push_str("```");
|
|
||||||
output.push_str(&path);
|
|
||||||
output.push('\n');
|
output.push('\n');
|
||||||
for chunk in snapshot.as_rope().chunks() {
|
for chunk in snapshot.as_rope().chunks() {
|
||||||
output.push_str(chunk);
|
output.push_str(chunk);
|
||||||
|
|
|
@ -6,6 +6,7 @@ use gpui::{AppContext, RenderOnce, SharedString, Task, View, WeakView};
|
||||||
use language::{LineEnding, LspAdapterDelegate};
|
use language::{LineEnding, LspAdapterDelegate};
|
||||||
use project::PathMatchCandidateSet;
|
use project::PathMatchCandidateSet;
|
||||||
use std::{
|
use std::{
|
||||||
|
fmt::Write,
|
||||||
ops::Range,
|
ops::Range,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::{atomic::AtomicBool, Arc},
|
sync::{atomic::AtomicBool, Arc},
|
||||||
|
@ -155,20 +156,20 @@ impl SlashCommand for FileSlashCommand {
|
||||||
};
|
};
|
||||||
|
|
||||||
let fs = workspace.read(cx).app_state().fs.clone();
|
let fs = workspace.read(cx).app_state().fs.clone();
|
||||||
let argument = argument.to_string();
|
let text = cx.background_executor().spawn({
|
||||||
let text = cx.background_executor().spawn(async move {
|
let path = path.clone();
|
||||||
let mut content = fs.load(&abs_path).await?;
|
async move {
|
||||||
LineEnding::normalize(&mut content);
|
let mut content = fs.load(&abs_path).await?;
|
||||||
let mut output = String::with_capacity(argument.len() + content.len() + 9);
|
LineEnding::normalize(&mut content);
|
||||||
output.push_str("```");
|
let mut output = String::new();
|
||||||
output.push_str(&argument);
|
output.push_str(&codeblock_fence_for_path(Some(&path), None));
|
||||||
output.push('\n');
|
output.push_str(&content);
|
||||||
output.push_str(&content);
|
if !output.ends_with('\n') {
|
||||||
if !output.ends_with('\n') {
|
output.push('\n');
|
||||||
output.push('\n');
|
}
|
||||||
|
output.push_str("```");
|
||||||
|
anyhow::Ok(output)
|
||||||
}
|
}
|
||||||
output.push_str("```");
|
|
||||||
anyhow::Ok(output)
|
|
||||||
});
|
});
|
||||||
cx.foreground_executor().spawn(async move {
|
cx.foreground_executor().spawn(async move {
|
||||||
let text = text.await?;
|
let text = text.await?;
|
||||||
|
@ -224,3 +225,25 @@ impl RenderOnce for FilePlaceholder {
|
||||||
.on_click(move |_, cx| unfold(cx))
|
.on_click(move |_, cx| unfold(cx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn codeblock_fence_for_path(path: Option<&Path>, row_range: Option<Range<u32>>) -> String {
|
||||||
|
let mut text = String::new();
|
||||||
|
write!(text, "```").unwrap();
|
||||||
|
|
||||||
|
if let Some(path) = path {
|
||||||
|
if let Some(extension) = path.extension().and_then(|ext| ext.to_str()) {
|
||||||
|
write!(text, "{} ", extension).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(text, "{}", path.display()).unwrap();
|
||||||
|
} else {
|
||||||
|
write!(text, "untitled").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(row_range) = row_range {
|
||||||
|
write!(text, ":{}-{}", row_range.start + 1, row_range.end + 1).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
text.push('\n');
|
||||||
|
text
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use super::{file_command::FilePlaceholder, SlashCommand, SlashCommandOutput};
|
use super::{
|
||||||
|
file_command::{codeblock_fence_for_path, FilePlaceholder},
|
||||||
|
SlashCommand, SlashCommandOutput,
|
||||||
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use assistant_slash_command::SlashCommandOutputSection;
|
use assistant_slash_command::SlashCommandOutputSection;
|
||||||
use gpui::{AppContext, Task, WeakView};
|
use gpui::{AppContext, Task, WeakView};
|
||||||
|
@ -125,9 +128,8 @@ impl SlashCommand for SearchSlashCommand {
|
||||||
let range_start = result.range.start.min(file_content.len());
|
let range_start = result.range.start.min(file_content.len());
|
||||||
let range_end = result.range.end.min(file_content.len());
|
let range_end = result.range.end.min(file_content.len());
|
||||||
|
|
||||||
let start_line =
|
let start_row = file_content[0..range_start].matches('\n').count() as u32;
|
||||||
file_content[0..range_start].matches('\n').count() as u32 + 1;
|
let end_row = file_content[0..range_end].matches('\n').count() as u32;
|
||||||
let end_line = file_content[0..range_end].matches('\n').count() as u32 + 1;
|
|
||||||
let start_line_byte_offset = file_content[0..range_start]
|
let start_line_byte_offset = file_content[0..range_start]
|
||||||
.rfind('\n')
|
.rfind('\n')
|
||||||
.map(|pos| pos + 1)
|
.map(|pos| pos + 1)
|
||||||
|
@ -138,14 +140,11 @@ impl SlashCommand for SearchSlashCommand {
|
||||||
.unwrap_or_else(|| file_content.len());
|
.unwrap_or_else(|| file_content.len());
|
||||||
|
|
||||||
let section_start_ix = text.len();
|
let section_start_ix = text.len();
|
||||||
writeln!(
|
text.push_str(&codeblock_fence_for_path(
|
||||||
text,
|
Some(&result.path),
|
||||||
"```{}:{}-{}",
|
Some(start_row..end_row),
|
||||||
result.path.display(),
|
));
|
||||||
start_line,
|
|
||||||
end_line,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let mut excerpt =
|
let mut excerpt =
|
||||||
file_content[start_line_byte_offset..end_line_byte_offset].to_string();
|
file_content[start_line_byte_offset..end_line_byte_offset].to_string();
|
||||||
LineEnding::normalize(&mut excerpt);
|
LineEnding::normalize(&mut excerpt);
|
||||||
|
@ -159,7 +158,7 @@ impl SlashCommand for SearchSlashCommand {
|
||||||
FilePlaceholder {
|
FilePlaceholder {
|
||||||
id,
|
id,
|
||||||
path: Some(full_path.clone()),
|
path: Some(full_path.clone()),
|
||||||
line_range: Some(start_line..end_line),
|
line_range: Some(start_row..end_row),
|
||||||
unfold,
|
unfold,
|
||||||
}
|
}
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
use super::{file_command::FilePlaceholder, SlashCommand, SlashCommandOutput};
|
use super::{
|
||||||
|
file_command::{codeblock_fence_for_path, FilePlaceholder},
|
||||||
|
SlashCommand, SlashCommandOutput,
|
||||||
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use assistant_slash_command::SlashCommandOutputSection;
|
use assistant_slash_command::SlashCommandOutputSection;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use editor::Editor;
|
use editor::Editor;
|
||||||
use gpui::{AppContext, Entity, Task, WeakView};
|
use gpui::{AppContext, Entity, Task, WeakView};
|
||||||
use language::LspAdapterDelegate;
|
use language::LspAdapterDelegate;
|
||||||
use std::{fmt::Write, path::Path, sync::Arc};
|
use std::{fmt::Write, sync::Arc};
|
||||||
use ui::{IntoElement, WindowContext};
|
use ui::{IntoElement, WindowContext};
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
|
||||||
|
@ -77,15 +80,7 @@ impl SlashCommand for TabsSlashCommand {
|
||||||
let mut text = String::new();
|
let mut text = String::new();
|
||||||
for (full_path, buffer, _) in open_buffers {
|
for (full_path, buffer, _) in open_buffers {
|
||||||
let section_start_ix = text.len();
|
let section_start_ix = text.len();
|
||||||
writeln!(
|
text.push_str(&codeblock_fence_for_path(full_path.as_deref(), None));
|
||||||
text,
|
|
||||||
"```{}\n",
|
|
||||||
full_path
|
|
||||||
.as_deref()
|
|
||||||
.unwrap_or(Path::new("untitled"))
|
|
||||||
.display()
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
for chunk in buffer.as_rope().chunks() {
|
for chunk in buffer.as_rope().chunks() {
|
||||||
text.push_str(chunk);
|
text.push_str(chunk);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue