Detailed changes
@@ -1,6 +1,6 @@
//! The Zed Rust Extension API allows you write extensions for [Zed](https://zed.dev/) in Rust.
-/// Provides access to Zed settings.
+pub mod http_client;
pub mod settings;
use core::fmt;
@@ -19,10 +19,6 @@ pub use wit::{
github_release_by_tag_name, latest_github_release, GithubRelease, GithubReleaseAsset,
GithubReleaseOptions,
},
- zed::extension::http_client::{
- fetch, fetch_stream, HttpMethod, HttpRequest, HttpResponse, HttpResponseStream,
- RedirectPolicy,
- },
zed::extension::nodejs::{
node_binary_path, npm_install_package, npm_package_installed_version,
npm_package_latest_version,
@@ -0,0 +1,95 @@
+//! An HTTP client.
+
+pub use crate::wit::zed::extension::http_client::{
+ fetch, fetch_stream, HttpMethod, HttpRequest, HttpResponse, HttpResponseStream, RedirectPolicy,
+};
+
+impl HttpRequest {
+ /// Returns a builder for an [`HttpRequest`].
+ pub fn builder() -> HttpRequestBuilder {
+ HttpRequestBuilder::new()
+ }
+
+ /// Executes the [`HttpRequest`] with [`fetch`].
+ pub fn fetch(&self) -> Result<HttpResponse, String> {
+ fetch(self)
+ }
+
+ /// Executes the [`HttpRequest`] with [`fetch_stream`].
+ pub fn fetch_stream(&self) -> Result<HttpResponseStream, String> {
+ fetch_stream(&self)
+ }
+}
+
+/// A builder for an [`HttpRequest`].
+#[derive(Clone)]
+pub struct HttpRequestBuilder {
+ method: Option<HttpMethod>,
+ url: Option<String>,
+ headers: Vec<(String, String)>,
+ body: Option<Vec<u8>>,
+ redirect_policy: RedirectPolicy,
+}
+
+impl HttpRequestBuilder {
+ /// Returns a new [`HttpRequestBuilder`].
+ pub fn new() -> Self {
+ HttpRequestBuilder {
+ method: None,
+ url: None,
+ headers: Vec::new(),
+ body: None,
+ redirect_policy: RedirectPolicy::NoFollow,
+ }
+ }
+
+ /// Sets the HTTP method for the request.
+ pub fn method(mut self, method: HttpMethod) -> Self {
+ self.method = Some(method);
+ self
+ }
+
+ /// Sets the URL for the request.
+ pub fn url(mut self, url: impl Into<String>) -> Self {
+ self.url = Some(url.into());
+ self
+ }
+
+ /// Adds a header to the request.
+ pub fn header(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
+ self.headers.push((name.into(), value.into()));
+ self
+ }
+
+ /// Adds the specified headers to the request.
+ pub fn headers(mut self, headers: impl IntoIterator<Item = (String, String)>) -> Self {
+ self.headers.extend(headers);
+ self
+ }
+
+ /// Sets the body of the request.
+ pub fn body(mut self, body: impl Into<Vec<u8>>) -> Self {
+ self.body = Some(body.into());
+ self
+ }
+
+ /// Sets the redirect policy for the request.
+ pub fn redirect_policy(mut self, policy: RedirectPolicy) -> Self {
+ self.redirect_policy = policy;
+ self
+ }
+
+ /// Builds the [`HttpRequest`].
+ pub fn build(self) -> Result<HttpRequest, String> {
+ let method = self.method.ok_or_else(|| "Method not set".to_string())?;
+ let url = self.url.ok_or_else(|| "URL not set".to_string())?;
+
+ Ok(HttpRequest {
+ method,
+ url,
+ headers: self.headers,
+ body: self.body,
+ redirect_policy: self.redirect_policy,
+ })
+ }
+}
@@ -1,3 +1,5 @@
+//! Provides access to Zed settings.
+
#[path = "../wit/since_v0.1.0/settings.rs"]
mod types;
@@ -1,11 +1,11 @@
mod hexdocs;
use std::{fs, io};
+use zed::http_client::{HttpMethod, HttpRequest, RedirectPolicy};
use zed::lsp::CompletionKind;
use zed::{
- CodeLabel, CodeLabelSpan, HttpMethod, HttpRequest, KeyValueStore, LanguageServerId,
- RedirectPolicy, SlashCommand, SlashCommandArgumentCompletion, SlashCommandOutput,
- SlashCommandOutputSection,
+ CodeLabel, CodeLabelSpan, KeyValueStore, LanguageServerId, SlashCommand,
+ SlashCommandArgumentCompletion, SlashCommandOutput, SlashCommandOutputSection,
};
use zed_extension_api::{self as zed, Result};
@@ -194,23 +194,20 @@ impl zed::Extension for GleamExtension {
.ok_or_else(|| "missing package name".to_string())?;
let module_path = components.map(ToString::to_string).collect::<Vec<_>>();
- let response = zed::fetch(&HttpRequest {
- method: HttpMethod::Get,
- url: format!(
+ let response = HttpRequest::builder()
+ .method(HttpMethod::Get)
+ .url(format!(
"https://hexdocs.pm/{package_name}{maybe_path}",
maybe_path = if !module_path.is_empty() {
format!("/{}.html", module_path.join("/"))
} else {
String::new()
}
- ),
- headers: vec![(
- "User-Agent".to_string(),
- "Zed (Gleam Extension)".to_string(),
- )],
- body: None,
- redirect_policy: RedirectPolicy::FollowAll,
- })?;
+ ))
+ .header("User-Agent", "Zed (Gleam Extension)")
+ .redirect_policy(RedirectPolicy::FollowAll)
+ .build()?
+ .fetch()?;
let (markdown, _modules) =
convert_hexdocs_to_markdown(&mut io::Cursor::new(response.body))?;
@@ -11,7 +11,8 @@ use html_to_markdown::{
StartTagOutcome, TagHandler,
};
use zed_extension_api::{
- self as zed, HttpMethod, HttpRequest, KeyValueStore, RedirectPolicy, Result,
+ http_client::{HttpMethod, HttpRequest, RedirectPolicy},
+ KeyValueStore, Result,
};
pub fn index(package: String, database: &KeyValueStore) -> Result<()> {
@@ -20,13 +21,13 @@ pub fn index(package: String, database: &KeyValueStore) -> Result<()> {
"Zed (Gleam Extension)".to_string(),
)];
- let response = zed::fetch(&HttpRequest {
- method: HttpMethod::Get,
- url: format!("https://hexdocs.pm/{package}"),
- headers: headers.clone(),
- body: None,
- redirect_policy: RedirectPolicy::FollowAll,
- })?;
+ let response = HttpRequest::builder()
+ .method(HttpMethod::Get)
+ .url(format!("https://hexdocs.pm/{package}"))
+ .headers(headers.clone())
+ .redirect_policy(RedirectPolicy::FollowAll)
+ .build()?
+ .fetch()?;
let (package_root_markdown, modules) =
convert_hexdocs_to_markdown(&mut io::Cursor::new(&response.body))?;
@@ -34,13 +35,13 @@ pub fn index(package: String, database: &KeyValueStore) -> Result<()> {
database.insert(&package, &package_root_markdown)?;
for module in modules {
- let response = zed::fetch(&HttpRequest {
- method: HttpMethod::Get,
- url: format!("https://hexdocs.pm/{package}/{module}.html"),
- headers: headers.clone(),
- body: None,
- redirect_policy: RedirectPolicy::FollowAll,
- })?;
+ let response = HttpRequest::builder()
+ .method(HttpMethod::Get)
+ .url(format!("https://hexdocs.pm/{package}/{module}.html"))
+ .headers(headers.clone())
+ .redirect_policy(RedirectPolicy::FollowAll)
+ .build()?
+ .fetch()?;
let (markdown, _modules) =
convert_hexdocs_to_markdown(&mut io::Cursor::new(&response.body))?;