Replace to_link with as_link

Co-authored-by: Cole Miller <cole@zed.dev>
This commit is contained in:
Agus Zubiaga 2025-08-13 10:54:24 -03:00
parent d8131278f1
commit 6ed2155b9a
6 changed files with 57 additions and 49 deletions

View file

@ -341,7 +341,7 @@ impl ContentBlock {
.. ..
}) => { }) => {
if let Some(uri) = MentionUri::parse(&uri).log_err() { if let Some(uri) = MentionUri::parse(&uri).log_err() {
uri.to_link() uri.as_link().to_string()
} else { } else {
uri.clone() uri.clone()
} }

View file

@ -2,6 +2,7 @@ use agent::ThreadId;
use anyhow::{Context as _, Result, bail}; use anyhow::{Context as _, Result, bail};
use prompt_store::{PromptId, UserPromptId}; use prompt_store::{PromptId, UserPromptId};
use std::{ use std::{
fmt,
ops::Range, ops::Range,
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
@ -108,7 +109,6 @@ impl MentionUri {
.to_string_lossy() .to_string_lossy()
.into_owned(), .into_owned(),
MentionUri::Symbol { name, .. } => name.clone(), MentionUri::Symbol { name, .. } => name.clone(),
// todo! better names
MentionUri::Thread { name, .. } => name.clone(), MentionUri::Thread { name, .. } => name.clone(),
MentionUri::TextThread { name, .. } => name.clone(), MentionUri::TextThread { name, .. } => name.clone(),
MentionUri::Rule { name, .. } => name.clone(), MentionUri::Rule { name, .. } => name.clone(),
@ -118,63 +118,72 @@ impl MentionUri {
} }
} }
// todo! return something that implements display to avoid extra allocs pub fn as_link<'a>(&'a self) -> MentionLink<'a> {
pub fn to_link(&self) -> String { MentionLink(self)
let name = self.name();
let uri = self.to_uri();
format!("[{name}]({uri})")
} }
pub fn to_uri(&self) -> String { pub fn to_uri(&self) -> Url {
match self { match self {
MentionUri::File(path) => { MentionUri::File(path) => {
format!("file://{}", path.display()) let mut url = Url::parse("file:///").unwrap();
url.set_path(&path.to_string_lossy());
url
} }
MentionUri::Symbol { MentionUri::Symbol {
path, path,
name, name,
line_range, line_range,
} => { } => {
let query = url::form_urlencoded::Serializer::new(String::new()) let mut url = Url::parse("file:///").unwrap();
.append_pair("symbol", name) url.set_path(&path.to_string_lossy());
.finish(); url.query_pairs_mut().append_pair("symbol", name);
format!( url.set_fragment(Some(&format!(
"file://{}?{query}#L{}:{}", "L{}:{}",
path.display(),
line_range.start + 1, line_range.start + 1,
line_range.end + 1, line_range.end + 1
) )));
url
} }
MentionUri::Selection { path, line_range } => { MentionUri::Selection { path, line_range } => {
format!( let mut url = Url::parse("file:///").unwrap();
"file://{}#L{}:{}", url.set_path(&path.to_string_lossy());
path.display(), url.set_fragment(Some(&format!(
"L{}:{}",
line_range.start + 1, line_range.start + 1,
line_range.end + 1, line_range.end + 1
) )));
url
} }
MentionUri::Thread { name, id } => { MentionUri::Thread { name, id } => {
let query = url::form_urlencoded::Serializer::new(String::new()) let mut url = Url::parse("zed:///").unwrap();
.append_pair("name", name) url.set_path(&format!("/agent/thread/{id}"));
.finish(); url.query_pairs_mut().append_pair("name", name);
format!("zed:///agent/thread/{id}?{query}") url
} }
MentionUri::TextThread { path, name } => { MentionUri::TextThread { path, name } => {
let query = url::form_urlencoded::Serializer::new(String::new()) let mut url = Url::parse("zed:///").unwrap();
.append_pair("name", name) url.set_path(&format!("/agent/text-thread/{}", path.to_string_lossy()));
.finish(); url.query_pairs_mut().append_pair("name", name);
format!("zed:///agent/text-thread/{}?{query}", path.display()) url
} }
MentionUri::Rule { name, id } => { MentionUri::Rule { name, id } => {
let query = url::form_urlencoded::Serializer::new(String::new()) let mut url = Url::parse("zed:///").unwrap();
.append_pair("name", name) url.set_path(&format!("/agent/rule/{id}"));
.finish(); url.query_pairs_mut().append_pair("name", name);
format!("zed:///agent/rule/{id}?{query}") url
} }
} }
} }
} }
pub struct MentionLink<'a>(&'a MentionUri);
impl fmt::Display for MentionLink<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[{}]({})", self.0.name(), self.0.to_uri())
}
}
fn single_query_param(url: &Url, name: &'static str) -> Result<Option<String>> { fn single_query_param(url: &Url, name: &'static str) -> Result<Option<String>> {
let pairs = url.query_pairs().collect::<Vec<_>>(); let pairs = url.query_pairs().collect::<Vec<_>>();
match pairs.as_slice() { match pairs.as_slice() {
@ -211,7 +220,7 @@ mod tests {
MentionUri::File(path) => assert_eq!(path.to_str().unwrap(), "/path/to/file.rs"), MentionUri::File(path) => assert_eq!(path.to_str().unwrap(), "/path/to/file.rs"),
_ => panic!("Expected File variant"), _ => panic!("Expected File variant"),
} }
assert_eq!(parsed.to_uri(), file_uri); assert_eq!(parsed.to_uri().to_string(), file_uri);
} }
#[test] #[test]
@ -231,7 +240,7 @@ mod tests {
} }
_ => panic!("Expected Symbol variant"), _ => panic!("Expected Symbol variant"),
} }
assert_eq!(parsed.to_uri(), symbol_uri); assert_eq!(parsed.to_uri().to_string(), symbol_uri);
} }
#[test] #[test]
@ -246,7 +255,7 @@ mod tests {
} }
_ => panic!("Expected Selection variant"), _ => panic!("Expected Selection variant"),
} }
assert_eq!(parsed.to_uri(), selection_uri); assert_eq!(parsed.to_uri().to_string(), selection_uri);
} }
#[test] #[test]
@ -263,7 +272,7 @@ mod tests {
} }
_ => panic!("Expected Thread variant"), _ => panic!("Expected Thread variant"),
} }
assert_eq!(parsed.to_uri(), thread_uri); assert_eq!(parsed.to_uri().to_string(), thread_uri);
} }
#[test] #[test]
@ -277,7 +286,7 @@ mod tests {
} }
_ => panic!("Expected Rule variant"), _ => panic!("Expected Rule variant"),
} }
assert_eq!(parsed.to_uri(), rule_uri); assert_eq!(parsed.to_uri().to_string(), rule_uri);
} }
#[test] #[test]

View file

@ -113,7 +113,7 @@ impl AgentMessage {
} }
} }
MessageContent::Mention { uri, .. } => { MessageContent::Mention { uri, .. } => {
write!(markdown, "{}", uri.to_link()).ok(); write!(markdown, "{}", uri.as_link()).ok();
} }
} }
} }
@ -1228,7 +1228,7 @@ impl AgentMessage {
} }
} }
language_model::MessageContent::Text(uri.to_link()) language_model::MessageContent::Text(uri.as_link().to_string())
} }
}; };

View file

@ -555,7 +555,7 @@ impl ContextPickerCompletionProvider {
name: title.to_string(), name: title.to_string(),
}, },
}; };
let new_text = format!("{} ", uri.to_link()); let new_text = format!("{} ", uri.as_link());
let new_text_len = new_text.len(); let new_text_len = new_text.len();
Completion { Completion {
@ -590,7 +590,7 @@ impl ContextPickerCompletionProvider {
id: rule.prompt_id.into(), id: rule.prompt_id.into(),
name: rule.title.to_string(), name: rule.title.to_string(),
}; };
let new_text = format!("{} ", uri.to_link()); let new_text = format!("{} ", uri.as_link());
let new_text_len = new_text.len(); let new_text_len = new_text.len();
Completion { Completion {
replace_range: source_range.clone(), replace_range: source_range.clone(),
@ -656,7 +656,7 @@ impl ContextPickerCompletionProvider {
}; };
let file_uri = MentionUri::File(abs_path.into()); let file_uri = MentionUri::File(abs_path.into());
let new_text = format!("{} ", file_uri.to_link()); let new_text = format!("{} ", file_uri.as_link());
let new_text_len = new_text.len(); let new_text_len = new_text.len();
Some(Completion { Some(Completion {
replace_range: source_range.clone(), replace_range: source_range.clone(),
@ -698,7 +698,7 @@ impl ContextPickerCompletionProvider {
name: symbol.name.clone(), name: symbol.name.clone(),
line_range: symbol.range.start.0.row..symbol.range.end.0.row, line_range: symbol.range.start.0.row..symbol.range.end.0.row,
}; };
let new_text = format!("{} ", uri.to_link()); let new_text = format!("{} ", uri.as_link());
let new_text_len = new_text.len(); let new_text_len = new_text.len();
Some(Completion { Some(Completion {
replace_range: source_range.clone(), replace_range: source_range.clone(),

View file

@ -32,6 +32,7 @@ use project::{CompletionIntent, Project};
use prompt_store::PromptId; use prompt_store::PromptId;
use rope::Point; use rope::Point;
use settings::{Settings as _, SettingsStore}; use settings::{Settings as _, SettingsStore};
use std::fmt::Write as _;
use std::path::PathBuf; use std::path::PathBuf;
use std::{ use std::{
cell::RefCell, collections::BTreeMap, path::Path, process::ExitStatus, rc::Rc, sync::Arc, cell::RefCell, collections::BTreeMap, path::Path, process::ExitStatus, rc::Rc, sync::Arc,
@ -439,7 +440,7 @@ impl AcpThreadView {
acp::TextResourceContents { acp::TextResourceContents {
mime_type: None, mime_type: None,
text: mention.content.clone(), text: mention.content.clone(),
uri: mention.uri.to_uri(), uri: mention.uri.to_uri().to_string(),
}, },
), ),
})); }));
@ -614,8 +615,7 @@ impl AcpThreadView {
let path = PathBuf::from(&resource.uri); let path = PathBuf::from(&resource.uri);
let project_path = project.read(cx).project_path_for_absolute_path(&path, cx); let project_path = project.read(cx).project_path_for_absolute_path(&path, cx);
let start = text.len(); let start = text.len();
let content = MentionUri::File(path).to_uri(); let _ = write!(&mut text, "{}", MentionUri::File(path).to_uri());
text.push_str(&content);
let end = text.len(); let end = text.len();
if let Some(project_path) = project_path { if let Some(project_path) = project_path {
let filename: SharedString = project_path let filename: SharedString = project_path

View file

@ -90,7 +90,6 @@ impl From<Uuid> for UserPromptId {
} }
} }
// todo! remove me
impl std::fmt::Display for PromptId { impl std::fmt::Display for PromptId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {