@@ -388,7 +388,7 @@ dependencies = [
"fuzzy",
"gpui",
"heed",
- "html_to_markdown",
+ "html_to_markdown 0.1.0",
"http 0.1.0",
"indoc",
"language",
@@ -5237,6 +5237,18 @@ dependencies = [
"regex",
]
+[[package]]
+name = "html_to_markdown"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e608e8dd0939bfb6b516d96a5919751b835297a02230aecb88d2fc84ebebaa8a"
+dependencies = [
+ "anyhow",
+ "html5ever",
+ "markup5ever_rcdom",
+ "regex",
+]
+
[[package]]
name = "http"
version = "0.1.0"
@@ -9019,7 +9031,7 @@ dependencies = [
"fuzzy",
"gpui",
"heed",
- "html_to_markdown",
+ "html_to_markdown 0.1.0",
"http 0.1.0",
"indexmap 1.9.3",
"indoc",
@@ -13779,6 +13791,7 @@ dependencies = [
name = "zed_gleam"
version = "0.1.3"
dependencies = [
+ "html_to_markdown 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"zed_extension_api 0.0.7",
]
@@ -18,3 +18,8 @@ commit = "8432ffe32ccd360534837256747beb5b1c82fca1"
description = "Returns information about the current Gleam project."
requires_argument = false
tooltip_text = "Insert Gleam project data"
+
+[slash_commands.gleam-docs]
+description = "Returns Gleam docs."
+requires_argument = true
+tooltip_text = "Insert Gleam docs"
@@ -1,10 +1,13 @@
+use html_to_markdown::{convert_html_to_markdown, TagHandler};
+use std::cell::RefCell;
use std::fs;
+use std::rc::Rc;
use zed::lsp::CompletionKind;
use zed::{
CodeLabel, CodeLabelSpan, LanguageServerId, SlashCommand, SlashCommandOutput,
SlashCommandOutputSection,
};
-use zed_extension_api::{self as zed, Result};
+use zed_extension_api::{self as zed, fetch, HttpRequest, Result};
struct GleamExtension {
cached_binary_path: Option<String>,
@@ -164,10 +167,55 @@ impl zed::Extension for GleamExtension {
fn run_slash_command(
&self,
command: SlashCommand,
- _argument: Option<String>,
+ argument: Option<String>,
worktree: &zed::Worktree,
) -> Result<SlashCommandOutput, String> {
match command.name.as_str() {
+ "gleam-docs" => {
+ let argument = argument.ok_or_else(|| "missing argument".to_string())?;
+
+ let mut components = argument.split('/');
+ let package_name = components
+ .next()
+ .ok_or_else(|| "missing package name".to_string())?;
+ let module_path = components.map(ToString::to_string).collect::<Vec<_>>();
+
+ let response = fetch(&HttpRequest {
+ url: format!(
+ "https://hexdocs.pm/{package_name}{maybe_path}",
+ maybe_path = if !module_path.is_empty() {
+ format!("/{}.html", module_path.join("/"))
+ } else {
+ String::new()
+ }
+ ),
+ })?;
+
+ let mut handlers: Vec<TagHandler> = vec![
+ Rc::new(RefCell::new(
+ html_to_markdown::markdown::WebpageChromeRemover,
+ )),
+ Rc::new(RefCell::new(html_to_markdown::markdown::ParagraphHandler)),
+ Rc::new(RefCell::new(html_to_markdown::markdown::HeadingHandler)),
+ Rc::new(RefCell::new(html_to_markdown::markdown::ListHandler)),
+ Rc::new(RefCell::new(html_to_markdown::markdown::TableHandler::new())),
+ Rc::new(RefCell::new(html_to_markdown::markdown::StyledTextHandler)),
+ ];
+
+ let markdown = convert_html_to_markdown(response.body.as_bytes(), &mut handlers)
+ .map_err(|err| format!("failed to convert docs to Markdown {err}"))?;
+
+ let mut text = String::new();
+ text.push_str(&markdown);
+
+ Ok(SlashCommandOutput {
+ sections: vec![SlashCommandOutputSection {
+ range: (0..text.len()).into(),
+ label: format!("gleam-docs: {package_name} {}", module_path.join("/")),
+ }],
+ text,
+ })
+ }
"gleam-project" => {
let mut text = String::new();
text.push_str("You are in a Gleam project.\n");