logiguard fork v3: full patch set on verified 8c74db0 tree

Includes prior-session patches (carry forward so the app compiles):
  - crates/gpui/build.rs: cross-compile manifest fix
  - crates/gpui/src/platform.rs: PlatformWindow::activate_with_token trait method
  - crates/gpui/src/window.rs: Window::activate_with_token public API
  - crates/gpui_linux/src/linux/wayland/window.rs: WaylandWindow::activate_with_token + activate() keyboard-serial fix

Plus the focus-serial fix:
  - serial.rs: SerialKind::KeyboardEnter
  - client.rs: store wl_keyboard.enter serial; latest_serial_of()

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Mohamad Khani
2026-07-14 01:52:12 +03:30
commit b9819977a5
3984 changed files with 1487015 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
[package]
name = "zed_extension_api"
version = "0.8.0"
description = "APIs for creating Zed extensions in Rust"
repository = "https://github.com/zed-industries/zed"
documentation = "https://docs.rs/zed_extension_api"
keywords = ["zed", "extension"]
edition.workspace = true
# Change back to `true` when we're ready to publish v0.8.0.
publish = false
license = "Apache-2.0"
[lints]
workspace = true
[lib]
path = "src/extension_api.rs"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
wit-bindgen = "0.41"
[package.metadata.component]
target = { path = "wit" }

View File

@@ -0,0 +1 @@
../../LICENSE-APACHE

View File

@@ -0,0 +1,12 @@
# Pending Changes
This is a list of pending changes to the Zed extension API that require a breaking change.
This list should be updated as we notice things that should be changed so that we can batch them up in a single release.
## vNext
### Slash Commands
- Rename `SlashCommand.tooltip_text` to `SlashCommand.menu_text`
- We may even want to remove it entirely, as right now this is only used for featured slash commands, and slash commands defined by extensions aren't currently able to be featured.

View File

@@ -0,0 +1,77 @@
# The Zed Rust Extension API
This crate lets you write extensions for Zed in Rust.
## Extension Manifest
You'll need an `extension.toml` file at the root of your extension directory, with the following structure:
```toml
id = "my-extension"
name = "My Extension"
description = "..."
version = "0.0.1"
schema_version = 1
authors = ["Your Name <you@example.com>"]
repository = "https://github.com/your/extension-repository"
```
## Cargo metadata
Zed extensions are packaged as WebAssembly files. In your Cargo.toml, you'll
need to set your `crate-type` accordingly:
```toml
[dependencies]
zed_extension_api = "0.6.0"
[lib]
crate-type = ["cdylib"]
```
## Implementing an Extension
To define your extension, create a type that implements the `Extension` trait, and register it.
```rust
use zed_extension_api as zed;
struct MyExtension {
// ... state
}
impl zed::Extension for MyExtension {
// ...
}
zed::register_extension!(MyExtension);
```
## Testing your extension
To run your extension in Zed as you're developing it:
- Make sure you have [Rust installed](https://www.rust-lang.org/learn/get-started)
- Have the `wasm32-wasip2` target installed (`rustup target add wasm32-wasip2`)
- Open the extensions view using the `zed: extensions` action in the command palette.
- Click the `Install Dev Extension` button in the top right
- Choose the path to your extension directory.
## Compatible Zed versions
Extensions created using newer versions of the Zed extension API won't be compatible with older versions of Zed.
Here is the compatibility of the `zed_extension_api` with versions of Zed:
| Zed version | `zed_extension_api` version |
| ----------- | --------------------------- |
| `0.192.x` | `0.0.1` - `0.6.0` |
| `0.186.x` | `0.0.1` - `0.5.0` |
| `0.184.x` | `0.0.1` - `0.4.0` |
| `0.178.x` | `0.0.1` - `0.3.0` |
| `0.162.x` | `0.0.1` - `0.2.0` |
| `0.149.x` | `0.0.1` - `0.1.0` |
| `0.131.x` | `0.0.1` - `0.0.6` |
| `0.130.x` | `0.0.1` - `0.0.5` |
| `0.129.x` | `0.0.1` - `0.0.4` |
| `0.128.x` | `0.0.1` |

View File

@@ -0,0 +1,15 @@
fn main() {
let version = std::env::var("CARGO_PKG_VERSION").unwrap();
let out_dir = std::env::var("OUT_DIR").unwrap();
let mut parts = version.split(|c: char| !c.is_ascii_digit());
let major = parts.next().unwrap().parse::<u16>().unwrap().to_be_bytes();
let minor = parts.next().unwrap().parse::<u16>().unwrap().to_be_bytes();
let patch = parts.next().unwrap().parse::<u16>().unwrap().to_be_bytes();
std::fs::write(
std::path::Path::new(&out_dir).join("version_bytes"),
[major[0], major[1], minor[0], minor[1], patch[0], patch[1]],
)
.unwrap();
}

View File

@@ -0,0 +1,639 @@
//! The Zed Rust Extension API allows you write extensions for [Zed](https://zed.dev/) in Rust.
pub mod http_client;
pub mod process;
pub mod settings;
use core::fmt;
use wit::*;
pub use serde_json;
// WIT re-exports.
//
// We explicitly enumerate the symbols we want to re-export, as there are some
// that we may want to shadow to provide a cleaner Rust API.
pub use wit::{
CodeLabel, CodeLabelSpan, CodeLabelSpanLiteral, Command, DownloadedFileType, EnvVars,
KeyValueStore, LanguageServerInstallationStatus, Project, Range, Worktree, download_file,
make_file_executable,
zed::extension::context_server::ContextServerConfiguration,
zed::extension::dap::{
AttachRequest, BuildTaskDefinition, BuildTaskDefinitionTemplatePayload, BuildTaskTemplate,
DebugAdapterBinary, DebugConfig, DebugRequest, DebugScenario, DebugTaskDefinition,
LaunchRequest, StartDebuggingRequestArguments, StartDebuggingRequestArgumentsRequest,
TaskTemplate, TcpArguments, TcpArgumentsTemplate, resolve_tcp_template,
},
zed::extension::github::{
GithubRelease, GithubReleaseAsset, GithubReleaseOptions, github_release_by_tag_name,
latest_github_release,
},
zed::extension::nodejs::{
node_binary_path, npm_install_package, npm_package_installed_version,
npm_package_latest_version,
},
zed::extension::platform::{Architecture, Os, current_platform},
zed::extension::slash_command::{
SlashCommand, SlashCommandArgumentCompletion, SlashCommandOutput, SlashCommandOutputSection,
},
};
// Undocumented WIT re-exports.
//
// These are symbols that need to be public for the purposes of implementing
// the extension host, but aren't relevant to extension authors.
#[doc(hidden)]
pub use wit::Guest;
/// Constructs for interacting with language servers over the
/// Language Server Protocol (LSP).
pub mod lsp {
pub use crate::wit::zed::extension::lsp::{
Completion, CompletionKind, InsertTextFormat, Symbol, SymbolKind,
};
}
/// A result returned from a Zed extension.
pub type Result<T, E = String> = core::result::Result<T, E>;
/// Updates the installation status for the given language server.
pub fn set_language_server_installation_status(
language_server_id: &LanguageServerId,
status: &LanguageServerInstallationStatus,
) {
wit::set_language_server_installation_status(&language_server_id.0, status)
}
/// A Zed extension.
pub trait Extension: Send + Sync {
/// Returns a new instance of the extension.
fn new() -> Self
where
Self: Sized;
/// Returns the command used to start the language server for the specified
/// language.
fn language_server_command(
&mut self,
_language_server_id: &LanguageServerId,
_worktree: &Worktree,
) -> Result<Command> {
Err("`language_server_command` not implemented".to_string())
}
/// Returns the initialization options to pass to the specified language server.
fn language_server_initialization_options(
&mut self,
_language_server_id: &LanguageServerId,
_worktree: &Worktree,
) -> Result<Option<serde_json::Value>> {
Ok(None)
}
/// Returns the workspace configuration options to pass to the language server.
fn language_server_workspace_configuration(
&mut self,
_language_server_id: &LanguageServerId,
_worktree: &Worktree,
) -> Result<Option<serde_json::Value>> {
Ok(None)
}
/// Returns the JSON schema for the initialization options.
///
/// The schema must conform to the JSON Schema speification.
fn language_server_initialization_options_schema(
&mut self,
_language_server_id: &LanguageServerId,
_worktree: &Worktree,
) -> Option<serde_json::Value> {
None
}
/// Returns the JSON schema for the workspace configuration.
///
/// The schema must conform to the JSON Schema specification.
fn language_server_workspace_configuration_schema(
&mut self,
_language_server_id: &LanguageServerId,
_worktree: &Worktree,
) -> Option<serde_json::Value> {
None
}
/// Returns the initialization options to pass to the other language server.
fn language_server_additional_initialization_options(
&mut self,
_language_server_id: &LanguageServerId,
_target_language_server_id: &LanguageServerId,
_worktree: &Worktree,
) -> Result<Option<serde_json::Value>> {
Ok(None)
}
/// Returns the workspace configuration options to pass to the other language server.
fn language_server_additional_workspace_configuration(
&mut self,
_language_server_id: &LanguageServerId,
_target_language_server_id: &LanguageServerId,
_worktree: &Worktree,
) -> Result<Option<serde_json::Value>> {
Ok(None)
}
/// Returns the label for the given completion.
fn label_for_completion(
&self,
_language_server_id: &LanguageServerId,
_completion: Completion,
) -> Option<CodeLabel> {
None
}
/// Returns the label for the given symbol.
fn label_for_symbol(
&self,
_language_server_id: &LanguageServerId,
_symbol: Symbol,
) -> Option<CodeLabel> {
None
}
/// Returns the completions that should be shown when completing the provided slash command with the given query.
fn complete_slash_command_argument(
&self,
_command: SlashCommand,
_args: Vec<String>,
) -> Result<Vec<SlashCommandArgumentCompletion>, String> {
Ok(Vec::new())
}
/// Returns the output from running the provided slash command.
fn run_slash_command(
&self,
_command: SlashCommand,
_args: Vec<String>,
_worktree: Option<&Worktree>,
) -> Result<SlashCommandOutput, String> {
Err("`run_slash_command` not implemented".to_string())
}
/// Returns the command used to start a context server.
fn context_server_command(
&mut self,
_context_server_id: &ContextServerId,
_project: &Project,
) -> Result<Command> {
Err("`context_server_command` not implemented".to_string())
}
/// Returns the configuration options for the specified context server.
fn context_server_configuration(
&mut self,
_context_server_id: &ContextServerId,
_project: &Project,
) -> Result<Option<ContextServerConfiguration>> {
Ok(None)
}
/// Returns a list of package names as suggestions to be included in the
/// search results of the `/docs` slash command.
///
/// This can be used to provide completions for known packages (e.g., from the
/// local project or a registry) before a package has been indexed.
fn suggest_docs_packages(&self, _provider: String) -> Result<Vec<String>, String> {
Ok(Vec::new())
}
/// Indexes the docs for the specified package.
fn index_docs(
&self,
_provider: String,
_package: String,
_database: &KeyValueStore,
) -> Result<(), String> {
Err("`index_docs` not implemented".to_string())
}
/// Returns the debug adapter binary for the specified adapter name and configuration.
fn get_dap_binary(
&mut self,
_adapter_name: String,
_config: DebugTaskDefinition,
_user_provided_debug_adapter_path: Option<String>,
_worktree: &Worktree,
) -> Result<DebugAdapterBinary, String> {
Err("`get_dap_binary` not implemented".to_string())
}
/// Determines whether the specified adapter configuration should *launch* a new debuggee process
/// or *attach* to an existing one. This function should not perform any further validation (outside of determining the kind of a request).
/// This function should return an error when the kind cannot be determined (rather than fall back to a known default).
fn dap_request_kind(
&mut self,
_adapter_name: String,
_config: serde_json::Value,
) -> Result<StartDebuggingRequestArgumentsRequest, String> {
Err("`dap_request_kind` not implemented".to_string())
}
/// Converts a high-level definition of a debug scenario (originating in a new session UI) to a "low-level" configuration suitable for a particular adapter.
///
/// In layman's terms: given a program, list of arguments, current working directory and environment variables,
/// create a configuration that can be used to start a debug session.
fn dap_config_to_scenario(&mut self, _config: DebugConfig) -> Result<DebugScenario, String> {
Err("`dap_config_to_scenario` not implemented".to_string())
}
/// Locators are entities that convert a Zed task into a debug scenario.
///
/// They can be provided even by extensions that don't provide a debug adapter.
/// For all tasks applicable to a given buffer, Zed will query all locators to find one that can turn the task into a debug scenario.
/// A converted debug scenario can include a build task (it shouldn't contain any configuration in such case); a build task result will later
/// be resolved with [`Extension::run_dap_locator`].
///
/// To work through a real-world example, take a `cargo run` task and a hypothetical `cargo` locator:
/// 1. We may need to modify the task; in this case, it is problematic that `cargo run` spawns a binary. We should turn `cargo run` into a debug scenario with
/// `cargo build` task. This is the decision we make at `dap_locator_create_scenario` scope.
/// 2. Then, after the build task finishes, we will run `run_dap_locator` of the locator that produced the build task to find the program to be debugged. This function
/// should give us a debugger-agnostic configuration for launching a debug target (that we end up resolving with [`Extension::dap_config_to_scenario`]). It's almost as if the user
/// found the artifact path by themselves.
///
/// Note that you're not obliged to use build tasks with locators. Specifically, it is sufficient to provide a debug configuration directly in the return value of
/// `dap_locator_create_scenario` if you're able to do that. Make sure to not fill out `build` field in that case, as that will prevent Zed from running second phase of resolution in such case.
/// This might be of particular relevance to interpreted languages.
fn dap_locator_create_scenario(
&mut self,
_locator_name: String,
_build_task: TaskTemplate,
_resolved_label: String,
_debug_adapter_name: String,
) -> Option<DebugScenario> {
None
}
/// Runs the second phase of locator resolution.
/// See [`Extension::dap_locator_create_scenario`] for a hefty comment on locators.
fn run_dap_locator(
&mut self,
_locator_name: String,
_build_task: TaskTemplate,
) -> Result<DebugRequest, String> {
Err("`run_dap_locator` not implemented".to_string())
}
}
/// Registers the provided type as a Zed extension.
///
/// The type must implement the [`Extension`] trait.
#[macro_export]
macro_rules! register_extension {
($extension_type:ty) => {
#[cfg(target_os = "wasi")]
mod wasi_ext {
unsafe extern "C" {
static mut errno: i32;
pub static mut __wasilibc_cwd: *mut std::ffi::c_char;
}
pub fn init_cwd() {
unsafe {
// Ensure that our chdir function is linked, instead of the
// one from wasi-libc in the chdir.o translation unit. Otherwise
// we risk linking in `__wasilibc_find_relpath_alloc` which
// is a weak symbol and is being used by
// `__wasilibc_find_relpath`, which we do not want on
// Windows.
chdir(std::ptr::null());
__wasilibc_cwd = std::ffi::CString::new(std::env::var("PWD").unwrap())
.unwrap()
.into_raw()
.cast();
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn chdir(raw_path: *const std::ffi::c_char) -> i32 {
// Forbid extensions from changing CWD and so return an appropriate error code.
errno = 58; // NOTSUP
return -1;
}
}
#[unsafe(export_name = "init-extension")]
pub extern "C" fn __init_extension() {
#[cfg(target_os = "wasi")]
wasi_ext::init_cwd();
zed_extension_api::register_extension(|| {
Box::new(<$extension_type as zed_extension_api::Extension>::new())
});
}
};
}
#[doc(hidden)]
pub fn register_extension(build_extension: fn() -> Box<dyn Extension>) {
unsafe { EXTENSION = Some((build_extension)()) }
}
fn extension() -> &'static mut dyn Extension {
#[expect(static_mut_refs)]
unsafe {
EXTENSION.as_deref_mut().unwrap()
}
}
static mut EXTENSION: Option<Box<dyn Extension>> = None;
#[cfg(target_arch = "wasm32")]
#[unsafe(link_section = "zed:api-version")]
#[doc(hidden)]
pub static ZED_API_VERSION: [u8; 6] = *include_bytes!(concat!(env!("OUT_DIR"), "/version_bytes"));
mod wit {
wit_bindgen::generate!({
skip: ["init-extension"],
path: "./wit/since_v0.8.0",
});
}
wit::export!(Component);
struct Component;
impl wit::Guest for Component {
fn language_server_command(
language_server_id: String,
worktree: &wit::Worktree,
) -> Result<wit::Command> {
let language_server_id = LanguageServerId(language_server_id);
extension().language_server_command(&language_server_id, worktree)
}
fn language_server_initialization_options(
language_server_id: String,
worktree: &Worktree,
) -> Result<Option<String>, String> {
let language_server_id = LanguageServerId(language_server_id);
Ok(extension()
.language_server_initialization_options(&language_server_id, worktree)?
.and_then(|value| serde_json::to_string(&value).ok()))
}
fn language_server_workspace_configuration(
language_server_id: String,
worktree: &Worktree,
) -> Result<Option<String>, String> {
let language_server_id = LanguageServerId(language_server_id);
Ok(extension()
.language_server_workspace_configuration(&language_server_id, worktree)?
.and_then(|value| serde_json::to_string(&value).ok()))
}
fn language_server_initialization_options_schema(
language_server_id: String,
worktree: &Worktree,
) -> Option<String> {
let language_server_id = LanguageServerId(language_server_id);
extension()
.language_server_initialization_options_schema(&language_server_id, worktree)
.and_then(|value| serde_json::to_string(&value).ok())
}
fn language_server_workspace_configuration_schema(
language_server_id: String,
worktree: &Worktree,
) -> Option<String> {
let language_server_id = LanguageServerId(language_server_id);
extension()
.language_server_workspace_configuration_schema(&language_server_id, worktree)
.and_then(|value| serde_json::to_string(&value).ok())
}
fn language_server_additional_initialization_options(
language_server_id: String,
target_language_server_id: String,
worktree: &Worktree,
) -> Result<Option<String>, String> {
let language_server_id = LanguageServerId(language_server_id);
let target_language_server_id = LanguageServerId(target_language_server_id);
Ok(extension()
.language_server_additional_initialization_options(
&language_server_id,
&target_language_server_id,
worktree,
)?
.and_then(|value| serde_json::to_string(&value).ok()))
}
fn language_server_additional_workspace_configuration(
language_server_id: String,
target_language_server_id: String,
worktree: &Worktree,
) -> Result<Option<String>, String> {
let language_server_id = LanguageServerId(language_server_id);
let target_language_server_id = LanguageServerId(target_language_server_id);
Ok(extension()
.language_server_additional_workspace_configuration(
&language_server_id,
&target_language_server_id,
worktree,
)?
.and_then(|value| serde_json::to_string(&value).ok()))
}
fn labels_for_completions(
language_server_id: String,
completions: Vec<Completion>,
) -> Result<Vec<Option<CodeLabel>>, String> {
let language_server_id = LanguageServerId(language_server_id);
let mut labels = Vec::new();
for (ix, completion) in completions.into_iter().enumerate() {
let label = extension().label_for_completion(&language_server_id, completion);
if let Some(label) = label {
labels.resize(ix + 1, None);
*labels.last_mut().unwrap() = Some(label);
}
}
Ok(labels)
}
fn labels_for_symbols(
language_server_id: String,
symbols: Vec<Symbol>,
) -> Result<Vec<Option<CodeLabel>>, String> {
let language_server_id = LanguageServerId(language_server_id);
let mut labels = Vec::new();
for (ix, symbol) in symbols.into_iter().enumerate() {
let label = extension().label_for_symbol(&language_server_id, symbol);
if let Some(label) = label {
labels.resize(ix + 1, None);
*labels.last_mut().unwrap() = Some(label);
}
}
Ok(labels)
}
fn complete_slash_command_argument(
command: SlashCommand,
args: Vec<String>,
) -> Result<Vec<SlashCommandArgumentCompletion>, String> {
extension().complete_slash_command_argument(command, args)
}
fn run_slash_command(
command: SlashCommand,
args: Vec<String>,
worktree: Option<&Worktree>,
) -> Result<SlashCommandOutput, String> {
extension().run_slash_command(command, args, worktree)
}
fn context_server_command(
context_server_id: String,
project: &Project,
) -> Result<wit::Command> {
let context_server_id = ContextServerId(context_server_id);
extension().context_server_command(&context_server_id, project)
}
fn context_server_configuration(
context_server_id: String,
project: &Project,
) -> Result<Option<ContextServerConfiguration>, String> {
let context_server_id = ContextServerId(context_server_id);
extension().context_server_configuration(&context_server_id, project)
}
fn suggest_docs_packages(provider: String) -> Result<Vec<String>, String> {
extension().suggest_docs_packages(provider)
}
fn index_docs(
provider: String,
package: String,
database: &KeyValueStore,
) -> Result<(), String> {
extension().index_docs(provider, package, database)
}
fn get_dap_binary(
adapter_name: String,
config: DebugTaskDefinition,
user_installed_path: Option<String>,
worktree: &Worktree,
) -> Result<wit::DebugAdapterBinary, String> {
extension().get_dap_binary(adapter_name, config, user_installed_path, worktree)
}
fn dap_request_kind(
adapter_name: String,
config: String,
) -> Result<StartDebuggingRequestArgumentsRequest, String> {
extension().dap_request_kind(
adapter_name,
serde_json::from_str(&config).map_err(|e| format!("Failed to parse config: {e}"))?,
)
}
fn dap_config_to_scenario(config: DebugConfig) -> Result<DebugScenario, String> {
extension().dap_config_to_scenario(config)
}
fn dap_locator_create_scenario(
locator_name: String,
build_task: TaskTemplate,
resolved_label: String,
debug_adapter_name: String,
) -> Option<DebugScenario> {
extension().dap_locator_create_scenario(
locator_name,
build_task,
resolved_label,
debug_adapter_name,
)
}
fn run_dap_locator(
locator_name: String,
build_task: TaskTemplate,
) -> Result<DebugRequest, String> {
extension().run_dap_locator(locator_name, build_task)
}
}
/// The ID of a language server.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub struct LanguageServerId(String);
impl LanguageServerId {
pub fn new(value: String) -> Self {
Self(value)
}
}
impl AsRef<str> for LanguageServerId {
fn as_ref(&self) -> &str {
&self.0
}
}
impl fmt::Display for LanguageServerId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
/// The ID of a context server.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub struct ContextServerId(String);
impl ContextServerId {
pub fn new(value: String) -> Self {
Self(value)
}
}
impl AsRef<str> for ContextServerId {
fn as_ref(&self) -> &str {
&self.0
}
}
impl fmt::Display for ContextServerId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl CodeLabelSpan {
/// Returns a [`CodeLabelSpan::CodeRange`].
pub fn code_range(range: impl Into<wit::Range>) -> Self {
Self::CodeRange(range.into())
}
/// Returns a [`CodeLabelSpan::Literal`].
pub fn literal(text: impl Into<String>, highlight_name: Option<String>) -> Self {
Self::Literal(CodeLabelSpanLiteral {
text: text.into(),
highlight_name,
})
}
}
impl From<std::ops::Range<u32>> for wit::Range {
fn from(value: std::ops::Range<u32>) -> Self {
Self {
start: value.start,
end: value.end,
}
}
}
impl From<std::ops::Range<usize>> for wit::Range {
fn from(value: std::ops::Range<usize>) -> Self {
Self {
start: value.start as u32,
end: value.end as u32,
}
}
}

View File

@@ -0,0 +1,101 @@
//! An HTTP client.
pub use crate::wit::zed::extension::http_client::{
HttpMethod, HttpRequest, HttpResponse, HttpResponseStream, RedirectPolicy, fetch, fetch_stream,
};
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 Default for HttpRequestBuilder {
fn default() -> Self {
Self::new()
}
}
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,
})
}
}

View File

@@ -0,0 +1,44 @@
//! A module for working with processes.
use crate::wit::zed::extension::process;
pub use crate::wit::zed::extension::process::{Command, Output};
impl Command {
pub fn new(program: impl Into<String>) -> Self {
Self {
command: program.into(),
args: Vec::new(),
env: Vec::new(),
}
}
pub fn arg(mut self, arg: impl Into<String>) -> Self {
self.args.push(arg.into());
self
}
pub fn args(mut self, args: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.args.extend(args.into_iter().map(Into::into));
self
}
pub fn env(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.env.push((key.into(), value.into()));
self
}
pub fn envs(
mut self,
envs: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
) -> Self {
self.env.extend(
envs.into_iter()
.map(|(key, value)| (key.into(), value.into())),
);
self
}
pub fn output(&mut self) -> Result<Output, String> {
process::run_command(self)
}
}

View File

@@ -0,0 +1,56 @@
//! Provides access to Zed settings.
#[path = "../wit/since_v0.8.0/settings.rs"]
mod types;
use crate::{Project, Result, SettingsLocation, Worktree, wit};
use serde_json;
pub use types::*;
impl LanguageSettings {
/// Returns the [`LanguageSettings`] for the given language.
pub fn for_worktree(language: Option<&str>, worktree: &Worktree) -> Result<Self> {
get_settings("language", language, Some(worktree.id()))
}
}
impl LspSettings {
/// Returns the [`LspSettings`] for the given language server.
pub fn for_worktree(language_server_name: &str, worktree: &Worktree) -> Result<Self> {
get_settings("lsp", Some(language_server_name), Some(worktree.id()))
}
}
impl ContextServerSettings {
/// Returns the [`ContextServerSettings`] for the given context server.
pub fn for_project(context_server_id: &str, project: &Project) -> Result<Self> {
let global_setting: Self = get_settings("context_servers", Some(context_server_id), None)?;
for worktree_id in project.worktree_ids() {
let settings = get_settings(
"context_servers",
Some(context_server_id),
Some(worktree_id),
)?;
if settings != global_setting {
return Ok(settings);
}
}
Ok(global_setting)
}
}
fn get_settings<T: serde::de::DeserializeOwned>(
settings_type: &str,
settings_name: Option<&str>,
worktree_id: Option<u64>,
) -> Result<T> {
let location = worktree_id.map(|worktree_id| SettingsLocation {
worktree_id,
path: String::new(),
});
let settings_json = wit::get_settings(location.as_ref(), settings_type, settings_name)?;
let settings: T = serde_json::from_str(&settings_json).map_err(|err| err.to_string())?;
Ok(settings)
}

View File

@@ -0,0 +1,70 @@
package zed:extension;
world extension {
use github.{github-release, github-release-options};
use platform.{os, architecture};
export init-extension: func();
enum downloaded-file-type {
gzip,
gzip-tar,
zip,
uncompressed,
}
variant language-server-installation-status {
checking-for-update,
downloaded,
downloading,
cached,
failed(string),
}
/// Gets the current operating system and architecture
import current-platform: func() -> tuple<os, architecture>;
/// Get the path to the node binary used by Zed.
import node-binary-path: func() -> result<string, string>;
/// Gets the latest version of the given NPM package.
import npm-package-latest-version: func(package-name: string) -> result<string, string>;
/// Returns the installed version of the given NPM package, if it exists.
import npm-package-installed-version: func(package-name: string) -> result<option<string>, string>;
/// Installs the specified NPM package.
import npm-install-package: func(package-name: string, version: string) -> result<_, string>;
/// Gets the latest release for the given GitHub repository.
import latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
/// Downloads a file from the given url, and saves it to the given filename within the extension's
/// working directory. Extracts the file according to the given file type.
import download-file: func(url: string, output-filename: string, file-type: downloaded-file-type) -> result<_, string>;
/// Updates the installation status for the given language server.
import set-language-server-installation-status: func(language-server-name: string, status: language-server-installation-status);
type env-vars = list<tuple<string, string>>;
record command {
command: string,
args: list<string>,
env: env-vars,
}
resource worktree {
read-text-file: func(path: string) -> result<string, string>;
which: func(binary-name: string) -> option<string>;
shell-env: func() -> env-vars;
}
record language-server-config {
name: string,
language-name: string,
}
export language-server-command: func(config: language-server-config, worktree: borrow<worktree>) -> result<command, string>;
export language-server-initialization-options: func(config: language-server-config, worktree: borrow<worktree>) -> result<option<string>, string>;
}

View File

@@ -0,0 +1,28 @@
interface github {
/// A GitHub release.
record github-release {
/// The version of the release.
version: string,
/// The list of assets attached to the release.
assets: list<github-release-asset>,
}
/// An asset from a GitHub release.
record github-release-asset {
/// The name of the asset.
name: string,
/// The download URL for the asset.
download-url: string,
}
/// The options used to filter down GitHub releases.
record github-release-options {
/// Whether releases without assets should be included.
require-assets: bool,
/// Whether pre-releases should be included.
pre-release: bool,
}
/// Returns the latest release for the given GitHub repository.
latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
}

View File

@@ -0,0 +1,24 @@
interface platform {
/// An operating system.
enum os {
/// macOS.
mac,
/// Linux.
linux,
/// Windows.
windows,
}
/// A platform architecture.
enum architecture {
/// AArch64 (e.g., Apple Silicon).
aarch64,
/// x86.
x86,
/// x86-64.
x8664,
}
/// Gets the current operating system and architecture.
current-platform: func() -> tuple<os, architecture>;
}

View File

@@ -0,0 +1,72 @@
package zed:extension;
world extension {
use github.{github-release, github-release-options};
use platform.{os, architecture};
export init-extension: func();
enum downloaded-file-type {
gzip,
gzip-tar,
zip,
uncompressed,
}
variant language-server-installation-status {
none,
downloading,
checking-for-update,
failed(string),
}
/// Gets the current operating system and architecture
import current-platform: func() -> tuple<os, architecture>;
/// Get the path to the node binary used by Zed.
import node-binary-path: func() -> result<string, string>;
/// Gets the latest version of the given NPM package.
import npm-package-latest-version: func(package-name: string) -> result<string, string>;
/// Returns the installed version of the given NPM package, if it exists.
import npm-package-installed-version: func(package-name: string) -> result<option<string>, string>;
/// Installs the specified NPM package.
import npm-install-package: func(package-name: string, version: string) -> result<_, string>;
/// Gets the latest release for the given GitHub repository.
import latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
/// Downloads a file from the given url, and saves it to the given path within the extension's
/// working directory. Extracts the file according to the given file type.
import download-file: func(url: string, file-path: string, file-type: downloaded-file-type) -> result<_, string>;
/// Makes the file at the given path executable.
import make-file-executable: func(filepath: string) -> result<_, string>;
/// Updates the installation status for the given language server.
import set-language-server-installation-status: func(language-server-name: string, status: language-server-installation-status);
type env-vars = list<tuple<string, string>>;
record command {
command: string,
args: list<string>,
env: env-vars,
}
resource worktree {
read-text-file: func(path: string) -> result<string, string>;
which: func(binary-name: string) -> option<string>;
shell-env: func() -> env-vars;
}
record language-server-config {
name: string,
language-name: string,
}
export language-server-command: func(config: language-server-config, worktree: borrow<worktree>) -> result<command, string>;
export language-server-initialization-options: func(config: language-server-config, worktree: borrow<worktree>) -> result<option<string>, string>;
}

View File

@@ -0,0 +1,28 @@
interface github {
/// A GitHub release.
record github-release {
/// The version of the release.
version: string,
/// The list of assets attached to the release.
assets: list<github-release-asset>,
}
/// An asset from a GitHub release.
record github-release-asset {
/// The name of the asset.
name: string,
/// The download URL for the asset.
download-url: string,
}
/// The options used to filter down GitHub releases.
record github-release-options {
/// Whether releases without assets should be included.
require-assets: bool,
/// Whether pre-releases should be included.
pre-release: bool,
}
/// Returns the latest release for the given GitHub repository.
latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
}

View File

@@ -0,0 +1,24 @@
interface platform {
/// An operating system.
enum os {
/// macOS.
mac,
/// Linux.
linux,
/// Windows.
windows,
}
/// A platform architecture.
enum architecture {
/// AArch64 (e.g., Apple Silicon).
aarch64,
/// x86.
x86,
/// x86-64.
x8664,
}
/// Gets the current operating system and architecture.
current-platform: func() -> tuple<os, architecture>;
}

View File

@@ -0,0 +1,130 @@
package zed:extension;
world extension {
import github;
import platform;
import nodejs;
use lsp.{completion, symbol};
/// Initializes the extension.
export init-extension: func();
/// The type of a downloaded file.
enum downloaded-file-type {
/// A gzipped file (`.gz`).
gzip,
/// A gzipped tar archive (`.tar.gz`).
gzip-tar,
/// A ZIP file (`.zip`).
zip,
/// An uncompressed file.
uncompressed,
}
/// The installation status for a language server.
variant language-server-installation-status {
/// The language server has no installation status.
none,
/// The language server is being downloaded.
downloading,
/// The language server is checking for updates.
checking-for-update,
/// The language server installation failed for specified reason.
failed(string),
}
record settings-location {
worktree-id: u64,
path: string,
}
import get-settings: func(path: option<settings-location>, category: string, key: option<string>) -> result<string, string>;
/// Downloads a file from the given URL and saves it to the given path within the extension's
/// working directory.
///
/// The file will be extracted according to the given file type.
import download-file: func(url: string, file-path: string, file-type: downloaded-file-type) -> result<_, string>;
/// Makes the file at the given path executable.
import make-file-executable: func(filepath: string) -> result<_, string>;
/// Updates the installation status for the given language server.
import set-language-server-installation-status: func(language-server-name: string, status: language-server-installation-status);
/// A list of environment variables.
type env-vars = list<tuple<string, string>>;
/// A command.
record command {
/// The command to execute.
command: string,
/// The arguments to pass to the command.
args: list<string>,
/// The environment variables to set for the command.
env: env-vars,
}
/// A Zed worktree.
resource worktree {
/// Returns the ID of the worktree.
id: func() -> u64;
/// Returns the root path of the worktree.
root-path: func() -> string;
/// Returns the textual contents of the specified file in the worktree.
read-text-file: func(path: string) -> result<string, string>;
/// Returns the path to the given binary name, if one is present on the `$PATH`.
which: func(binary-name: string) -> option<string>;
/// Returns the current shell environment.
shell-env: func() -> env-vars;
}
/// Returns the command used to start up the language server.
export language-server-command: func(language-server-id: string, worktree: borrow<worktree>) -> result<command, string>;
/// Returns the initialization options to pass to the language server on startup.
///
/// The initialization options are represented as a JSON string.
export language-server-initialization-options: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the workspace configuration options to pass to the language server.
export language-server-workspace-configuration: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// A label containing some code.
record code-label {
/// The source code to parse with Tree-sitter.
code: string,
/// The spans to display in the label.
spans: list<code-label-span>,
/// The range of the displayed label to include when filtering.
filter-range: range,
}
/// A span within a code label.
variant code-label-span {
/// A range into the parsed code.
code-range(range),
/// A span containing a code literal.
literal(code-label-span-literal),
}
/// A span containing a code literal.
record code-label-span-literal {
/// The literal text.
text: string,
/// The name of the highlight to use for this literal.
highlight-name: option<string>,
}
/// A (half-open) range (`[start, end)`).
record range {
/// The start of the range (inclusive).
start: u32,
/// The end of the range (exclusive).
end: u32,
}
export labels-for-completions: func(language-server-id: string, completions: list<completion>) -> result<list<option<code-label>>, string>;
export labels-for-symbols: func(language-server-id: string, symbols: list<symbol>) -> result<list<option<code-label>>, string>;
}

View File

@@ -0,0 +1,28 @@
interface github {
/// A GitHub release.
record github-release {
/// The version of the release.
version: string,
/// The list of assets attached to the release.
assets: list<github-release-asset>,
}
/// An asset from a GitHub release.
record github-release-asset {
/// The name of the asset.
name: string,
/// The download URL for the asset.
download-url: string,
}
/// The options used to filter down GitHub releases.
record github-release-options {
/// Whether releases without assets should be included.
require-assets: bool,
/// Whether pre-releases should be included.
pre-release: bool,
}
/// Returns the latest release for the given GitHub repository.
latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
}

View File

@@ -0,0 +1,83 @@
interface lsp {
/// An LSP completion.
record completion {
label: string,
detail: option<string>,
kind: option<completion-kind>,
insert-text-format: option<insert-text-format>,
}
/// The kind of an LSP completion.
variant completion-kind {
text,
method,
function,
%constructor,
field,
variable,
class,
%interface,
module,
property,
unit,
value,
%enum,
keyword,
snippet,
color,
file,
reference,
folder,
enum-member,
constant,
struct,
event,
operator,
type-parameter,
other(s32),
}
/// Defines how to interpret the insert text in a completion item.
variant insert-text-format {
plain-text,
snippet,
other(s32),
}
/// An LSP symbol.
record symbol {
kind: symbol-kind,
name: string,
}
/// The kind of an LSP symbol.
variant symbol-kind {
file,
module,
namespace,
%package,
class,
method,
property,
field,
%constructor,
%enum,
%interface,
function,
variable,
constant,
%string,
number,
boolean,
array,
object,
key,
null,
enum-member,
struct,
event,
operator,
type-parameter,
other(s32),
}
}

View File

@@ -0,0 +1,13 @@
interface nodejs {
/// Returns the path to the Node binary used by Zed.
node-binary-path: func() -> result<string, string>;
/// Returns the latest version of the given NPM package.
npm-package-latest-version: func(package-name: string) -> result<string, string>;
/// Returns the installed version of the given NPM package, if it exists.
npm-package-installed-version: func(package-name: string) -> result<option<string>, string>;
/// Installs the specified NPM package.
npm-install-package: func(package-name: string, version: string) -> result<_, string>;
}

View File

@@ -0,0 +1,24 @@
interface platform {
/// An operating system.
enum os {
/// macOS.
mac,
/// Linux.
linux,
/// Windows.
windows,
}
/// A platform architecture.
enum architecture {
/// AArch64 (e.g., Apple Silicon).
aarch64,
/// x86.
x86,
/// x86-64.
x8664,
}
/// Gets the current operating system and architecture.
current-platform: func() -> tuple<os, architecture>;
}

View File

@@ -0,0 +1,29 @@
use serde::{Deserialize, Serialize};
use std::num::NonZeroU32;
/// The settings for a particular language.
#[derive(Debug, Serialize, Deserialize)]
pub struct LanguageSettings {
/// How many columns a tab should occupy.
pub tab_size: NonZeroU32,
}
/// The settings for a particular language server.
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct LspSettings {
/// The settings for the language server binary.
pub binary: Option<BinarySettings>,
/// The initialization options to pass to the language server.
pub initialization_options: Option<serde_json::Value>,
/// The settings to pass to language server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a language server binary.
#[derive(Debug, Serialize, Deserialize)]
pub struct BinarySettings {
/// The path to the binary.
pub path: Option<String>,
/// The arguments to pass to the binary.
pub arguments: Option<Vec<String>>,
}

View File

@@ -0,0 +1,9 @@
interface common {
/// A (half-open) range (`[start, end)`).
record range {
/// The start of the range (inclusive).
start: u32,
/// The end of the range (exclusive).
end: u32,
}
}

View File

@@ -0,0 +1,147 @@
package zed:extension;
world extension {
import github;
import http-client;
import platform;
import nodejs;
use common.{range};
use lsp.{completion, symbol};
use slash-command.{slash-command, slash-command-argument-completion, slash-command-output};
/// Initializes the extension.
export init-extension: func();
/// The type of a downloaded file.
enum downloaded-file-type {
/// A gzipped file (`.gz`).
gzip,
/// A gzipped tar archive (`.tar.gz`).
gzip-tar,
/// A ZIP file (`.zip`).
zip,
/// An uncompressed file.
uncompressed,
}
/// The installation status for a language server.
variant language-server-installation-status {
/// The language server has no installation status.
none,
/// The language server is being downloaded.
downloading,
/// The language server is checking for updates.
checking-for-update,
/// The language server installation failed for specified reason.
failed(string),
}
record settings-location {
worktree-id: u64,
path: string,
}
import get-settings: func(path: option<settings-location>, category: string, key: option<string>) -> result<string, string>;
/// Downloads a file from the given URL and saves it to the given path within the extension's
/// working directory.
///
/// The file will be extracted according to the given file type.
import download-file: func(url: string, file-path: string, file-type: downloaded-file-type) -> result<_, string>;
/// Makes the file at the given path executable.
import make-file-executable: func(filepath: string) -> result<_, string>;
/// Updates the installation status for the given language server.
import set-language-server-installation-status: func(language-server-name: string, status: language-server-installation-status);
/// A list of environment variables.
type env-vars = list<tuple<string, string>>;
/// A command.
record command {
/// The command to execute.
command: string,
/// The arguments to pass to the command.
args: list<string>,
/// The environment variables to set for the command.
env: env-vars,
}
/// A Zed worktree.
resource worktree {
/// Returns the ID of the worktree.
id: func() -> u64;
/// Returns the root path of the worktree.
root-path: func() -> string;
/// Returns the textual contents of the specified file in the worktree.
read-text-file: func(path: string) -> result<string, string>;
/// Returns the path to the given binary name, if one is present on the `$PATH`.
which: func(binary-name: string) -> option<string>;
/// Returns the current shell environment.
shell-env: func() -> env-vars;
}
/// A key-value store.
resource key-value-store {
/// Inserts an entry under the specified key.
insert: func(key: string, value: string) -> result<_, string>;
}
/// Returns the command used to start up the language server.
export language-server-command: func(language-server-id: string, worktree: borrow<worktree>) -> result<command, string>;
/// Returns the initialization options to pass to the language server on startup.
///
/// The initialization options are represented as a JSON string.
export language-server-initialization-options: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the workspace configuration options to pass to the language server.
export language-server-workspace-configuration: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// A label containing some code.
record code-label {
/// The source code to parse with Tree-sitter.
code: string,
/// The spans to display in the label.
spans: list<code-label-span>,
/// The range of the displayed label to include when filtering.
filter-range: range,
}
/// A span within a code label.
variant code-label-span {
/// A range into the parsed code.
code-range(range),
/// A span containing a code literal.
literal(code-label-span-literal),
}
/// A span containing a code literal.
record code-label-span-literal {
/// The literal text.
text: string,
/// The name of the highlight to use for this literal.
highlight-name: option<string>,
}
export labels-for-completions: func(language-server-id: string, completions: list<completion>) -> result<list<option<code-label>>, string>;
export labels-for-symbols: func(language-server-id: string, symbols: list<symbol>) -> result<list<option<code-label>>, string>;
/// Returns the completions that should be shown when completing the provided slash command with the given query.
export complete-slash-command-argument: func(command: slash-command, args: list<string>) -> result<list<slash-command-argument-completion>, string>;
/// Returns the output from running the provided slash command.
export run-slash-command: func(command: slash-command, args: list<string>, worktree: option<borrow<worktree>>) -> result<slash-command-output, string>;
/// Returns a list of packages as suggestions to be included in the `/docs`
/// search results.
///
/// This can be used to provide completions for known packages (e.g., from the
/// local project or a registry) before a package has been indexed.
export suggest-docs-packages: func(provider-name: string) -> result<list<string>, string>;
/// Indexes the docs for the specified package.
export index-docs: func(provider-name: string, package-name: string, database: borrow<key-value-store>) -> result<_, string>;
}

View File

@@ -0,0 +1,33 @@
interface github {
/// A GitHub release.
record github-release {
/// The version of the release.
version: string,
/// The list of assets attached to the release.
assets: list<github-release-asset>,
}
/// An asset from a GitHub release.
record github-release-asset {
/// The name of the asset.
name: string,
/// The download URL for the asset.
download-url: string,
}
/// The options used to filter down GitHub releases.
record github-release-options {
/// Whether releases without assets should be included.
require-assets: bool,
/// Whether pre-releases should be included.
pre-release: bool,
}
/// Returns the latest release for the given GitHub repository.
latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
/// Returns the GitHub release with the specified tag name for the given GitHub repository.
///
/// Returns an error if a release with the given tag name does not exist.
github-release-by-tag-name: func(repo: string, tag: string) -> result<github-release, string>;
}

View File

@@ -0,0 +1,67 @@
interface http-client {
/// An HTTP request.
record http-request {
/// The HTTP method for the request.
method: http-method,
/// The URL to which the request should be made.
url: string,
/// The headers for the request.
headers: list<tuple<string, string>>,
/// The request body.
body: option<list<u8>>,
/// The policy to use for redirects.
redirect-policy: redirect-policy,
}
/// HTTP methods.
enum http-method {
/// `GET`
get,
/// `HEAD`
head,
/// `POST`
post,
/// `PUT`
put,
/// `DELETE`
delete,
/// `OPTIONS`
options,
/// `PATCH`
patch,
}
/// The policy for dealing with redirects received from the server.
variant redirect-policy {
/// Redirects from the server will not be followed.
///
/// This is the default behavior.
no-follow,
/// Redirects from the server will be followed up to the specified limit.
follow-limit(u32),
/// All redirects from the server will be followed.
follow-all,
}
/// An HTTP response.
record http-response {
/// The response headers.
headers: list<tuple<string, string>>,
/// The response body.
body: list<u8>,
}
/// Performs an HTTP request and returns the response.
fetch: func(req: http-request) -> result<http-response, string>;
/// An HTTP response stream.
resource http-response-stream {
/// Retrieves the next chunk of data from the response stream.
///
/// Returns `Ok(None)` if the stream has ended.
next-chunk: func() -> result<option<list<u8>>, string>;
}
/// Performs an HTTP request and returns a response stream.
fetch-stream: func(req: http-request) -> result<http-response-stream, string>;
}

View File

@@ -0,0 +1,83 @@
interface lsp {
/// An LSP completion.
record completion {
label: string,
detail: option<string>,
kind: option<completion-kind>,
insert-text-format: option<insert-text-format>,
}
/// The kind of an LSP completion.
variant completion-kind {
text,
method,
function,
%constructor,
field,
variable,
class,
%interface,
module,
property,
unit,
value,
%enum,
keyword,
snippet,
color,
file,
reference,
folder,
enum-member,
constant,
struct,
event,
operator,
type-parameter,
other(s32),
}
/// Defines how to interpret the insert text in a completion item.
variant insert-text-format {
plain-text,
snippet,
other(s32),
}
/// An LSP symbol.
record symbol {
kind: symbol-kind,
name: string,
}
/// The kind of an LSP symbol.
variant symbol-kind {
file,
module,
namespace,
%package,
class,
method,
property,
field,
%constructor,
%enum,
%interface,
function,
variable,
constant,
%string,
number,
boolean,
array,
object,
key,
null,
enum-member,
struct,
event,
operator,
type-parameter,
other(s32),
}
}

View File

@@ -0,0 +1,13 @@
interface nodejs {
/// Returns the path to the Node binary used by Zed.
node-binary-path: func() -> result<string, string>;
/// Returns the latest version of the given NPM package.
npm-package-latest-version: func(package-name: string) -> result<string, string>;
/// Returns the installed version of the given NPM package, if it exists.
npm-package-installed-version: func(package-name: string) -> result<option<string>, string>;
/// Installs the specified NPM package.
npm-install-package: func(package-name: string, version: string) -> result<_, string>;
}

View File

@@ -0,0 +1,24 @@
interface platform {
/// An operating system.
enum os {
/// macOS.
mac,
/// Linux.
linux,
/// Windows.
windows,
}
/// A platform architecture.
enum architecture {
/// AArch64 (e.g., Apple Silicon).
aarch64,
/// x86.
x86,
/// x86-64.
x8664,
}
/// Gets the current operating system and architecture.
current-platform: func() -> tuple<os, architecture>;
}

View File

@@ -0,0 +1,29 @@
use serde::{Deserialize, Serialize};
use std::num::NonZeroU32;
/// The settings for a particular language.
#[derive(Debug, Serialize, Deserialize)]
pub struct LanguageSettings {
/// How many columns a tab should occupy.
pub tab_size: NonZeroU32,
}
/// The settings for a particular language server.
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct LspSettings {
/// The settings for the language server binary.
pub binary: Option<BinarySettings>,
/// The initialization options to pass to the language server.
pub initialization_options: Option<serde_json::Value>,
/// The settings to pass to language server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a language server binary.
#[derive(Debug, Serialize, Deserialize)]
pub struct BinarySettings {
/// The path to the binary.
pub path: Option<String>,
/// The arguments to pass to the binary.
pub arguments: Option<Vec<String>>,
}

View File

@@ -0,0 +1,41 @@
interface slash-command {
use common.{range};
/// A slash command for use in the Assistant.
record slash-command {
/// The name of the slash command.
name: string,
/// The description of the slash command.
description: string,
/// The tooltip text to display for the run button.
tooltip-text: string,
/// Whether this slash command requires an argument.
requires-argument: bool,
}
/// The output of a slash command.
record slash-command-output {
/// The text produced by the slash command.
text: string,
/// The list of sections to show in the slash command placeholder.
sections: list<slash-command-output-section>,
}
/// A section in the slash command output.
record slash-command-output-section {
/// The range this section occupies.
range: range,
/// The label to display in the placeholder for this section.
label: string,
}
/// A completion for a slash command argument.
record slash-command-argument-completion {
/// The label to display for this completion.
label: string,
/// The new text that should be inserted into the command when this completion is accepted.
new-text: string,
/// Whether the command should be run when accepting this completion.
run-command: bool,
}
}

View File

@@ -0,0 +1,9 @@
interface common {
/// A (half-open) range (`[start, end)`).
record range {
/// The start of the range (inclusive).
start: u32,
/// The end of the range (exclusive).
end: u32,
}
}

View File

@@ -0,0 +1,156 @@
package zed:extension;
world extension {
import github;
import http-client;
import platform;
import nodejs;
use common.{range};
use lsp.{completion, symbol};
use slash-command.{slash-command, slash-command-argument-completion, slash-command-output};
/// Initializes the extension.
export init-extension: func();
/// The type of a downloaded file.
enum downloaded-file-type {
/// A gzipped file (`.gz`).
gzip,
/// A gzipped tar archive (`.tar.gz`).
gzip-tar,
/// A ZIP file (`.zip`).
zip,
/// An uncompressed file.
uncompressed,
}
/// The installation status for a language server.
variant language-server-installation-status {
/// The language server has no installation status.
none,
/// The language server is being downloaded.
downloading,
/// The language server is checking for updates.
checking-for-update,
/// The language server installation failed for specified reason.
failed(string),
}
record settings-location {
worktree-id: u64,
path: string,
}
import get-settings: func(path: option<settings-location>, category: string, key: option<string>) -> result<string, string>;
/// Downloads a file from the given URL and saves it to the given path within the extension's
/// working directory.
///
/// The file will be extracted according to the given file type.
import download-file: func(url: string, file-path: string, file-type: downloaded-file-type) -> result<_, string>;
/// Makes the file at the given path executable.
import make-file-executable: func(filepath: string) -> result<_, string>;
/// Updates the installation status for the given language server.
import set-language-server-installation-status: func(language-server-name: string, status: language-server-installation-status);
/// A list of environment variables.
type env-vars = list<tuple<string, string>>;
/// A command.
record command {
/// The command to execute.
command: string,
/// The arguments to pass to the command.
args: list<string>,
/// The environment variables to set for the command.
env: env-vars,
}
/// A Zed worktree.
resource worktree {
/// Returns the ID of the worktree.
id: func() -> u64;
/// Returns the root path of the worktree.
root-path: func() -> string;
/// Returns the textual contents of the specified file in the worktree.
read-text-file: func(path: string) -> result<string, string>;
/// Returns the path to the given binary name, if one is present on the `$PATH`.
which: func(binary-name: string) -> option<string>;
/// Returns the current shell environment.
shell-env: func() -> env-vars;
}
/// A Zed project.
resource project {
/// Returns the IDs of all of the worktrees in this project.
worktree-ids: func() -> list<u64>;
}
/// A key-value store.
resource key-value-store {
/// Inserts an entry under the specified key.
insert: func(key: string, value: string) -> result<_, string>;
}
/// Returns the command used to start up the language server.
export language-server-command: func(language-server-id: string, worktree: borrow<worktree>) -> result<command, string>;
/// Returns the initialization options to pass to the language server on startup.
///
/// The initialization options are represented as a JSON string.
export language-server-initialization-options: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the workspace configuration options to pass to the language server.
export language-server-workspace-configuration: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// A label containing some code.
record code-label {
/// The source code to parse with Tree-sitter.
code: string,
/// The spans to display in the label.
spans: list<code-label-span>,
/// The range of the displayed label to include when filtering.
filter-range: range,
}
/// A span within a code label.
variant code-label-span {
/// A range into the parsed code.
code-range(range),
/// A span containing a code literal.
literal(code-label-span-literal),
}
/// A span containing a code literal.
record code-label-span-literal {
/// The literal text.
text: string,
/// The name of the highlight to use for this literal.
highlight-name: option<string>,
}
export labels-for-completions: func(language-server-id: string, completions: list<completion>) -> result<list<option<code-label>>, string>;
export labels-for-symbols: func(language-server-id: string, symbols: list<symbol>) -> result<list<option<code-label>>, string>;
/// Returns the completions that should be shown when completing the provided slash command with the given query.
export complete-slash-command-argument: func(command: slash-command, args: list<string>) -> result<list<slash-command-argument-completion>, string>;
/// Returns the output from running the provided slash command.
export run-slash-command: func(command: slash-command, args: list<string>, worktree: option<borrow<worktree>>) -> result<slash-command-output, string>;
/// Returns the command used to start up a context server.
export context-server-command: func(context-server-id: string, project: borrow<project>) -> result<command, string>;
/// Returns a list of packages as suggestions to be included in the `/docs`
/// search results.
///
/// This can be used to provide completions for known packages (e.g., from the
/// local project or a registry) before a package has been indexed.
export suggest-docs-packages: func(provider-name: string) -> result<list<string>, string>;
/// Indexes the docs for the specified package.
export index-docs: func(provider-name: string, package-name: string, database: borrow<key-value-store>) -> result<_, string>;
}

View File

@@ -0,0 +1,35 @@
interface github {
/// A GitHub release.
record github-release {
/// The version of the release.
version: string,
/// The list of assets attached to the release.
assets: list<github-release-asset>,
}
/// An asset from a GitHub release.
record github-release-asset {
/// The name of the asset.
name: string,
/// The download URL for the asset.
download-url: string,
}
/// The options used to filter down GitHub releases.
record github-release-options {
/// Whether releases without assets should be included.
require-assets: bool,
/// Whether pre-releases should be included.
pre-release: bool,
}
/// Returns the latest release for the given GitHub repository.
///
/// Takes repo as a string in the form "<owner-name>/<repo-name>", for example: "zed-industries/zed".
latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
/// Returns the GitHub release with the specified tag name for the given GitHub repository.
///
/// Returns an error if a release with the given tag name does not exist.
github-release-by-tag-name: func(repo: string, tag: string) -> result<github-release, string>;
}

View File

@@ -0,0 +1,67 @@
interface http-client {
/// An HTTP request.
record http-request {
/// The HTTP method for the request.
method: http-method,
/// The URL to which the request should be made.
url: string,
/// The headers for the request.
headers: list<tuple<string, string>>,
/// The request body.
body: option<list<u8>>,
/// The policy to use for redirects.
redirect-policy: redirect-policy,
}
/// HTTP methods.
enum http-method {
/// `GET`
get,
/// `HEAD`
head,
/// `POST`
post,
/// `PUT`
put,
/// `DELETE`
delete,
/// `OPTIONS`
options,
/// `PATCH`
patch,
}
/// The policy for dealing with redirects received from the server.
variant redirect-policy {
/// Redirects from the server will not be followed.
///
/// This is the default behavior.
no-follow,
/// Redirects from the server will be followed up to the specified limit.
follow-limit(u32),
/// All redirects from the server will be followed.
follow-all,
}
/// An HTTP response.
record http-response {
/// The response headers.
headers: list<tuple<string, string>>,
/// The response body.
body: list<u8>,
}
/// Performs an HTTP request and returns the response.
fetch: func(req: http-request) -> result<http-response, string>;
/// An HTTP response stream.
resource http-response-stream {
/// Retrieves the next chunk of data from the response stream.
///
/// Returns `Ok(None)` if the stream has ended.
next-chunk: func() -> result<option<list<u8>>, string>;
}
/// Performs an HTTP request and returns a response stream.
fetch-stream: func(req: http-request) -> result<http-response-stream, string>;
}

View File

@@ -0,0 +1,90 @@
interface lsp {
/// An LSP completion.
record completion {
label: string,
label-details: option<completion-label-details>,
detail: option<string>,
kind: option<completion-kind>,
insert-text-format: option<insert-text-format>,
}
/// The kind of an LSP completion.
variant completion-kind {
text,
method,
function,
%constructor,
field,
variable,
class,
%interface,
module,
property,
unit,
value,
%enum,
keyword,
snippet,
color,
file,
reference,
folder,
enum-member,
constant,
struct,
event,
operator,
type-parameter,
other(s32),
}
/// Label details for an LSP completion.
record completion-label-details {
detail: option<string>,
description: option<string>,
}
/// Defines how to interpret the insert text in a completion item.
variant insert-text-format {
plain-text,
snippet,
other(s32),
}
/// An LSP symbol.
record symbol {
kind: symbol-kind,
name: string,
}
/// The kind of an LSP symbol.
variant symbol-kind {
file,
module,
namespace,
%package,
class,
method,
property,
field,
%constructor,
%enum,
%interface,
function,
variable,
constant,
%string,
number,
boolean,
array,
object,
key,
null,
enum-member,
struct,
event,
operator,
type-parameter,
other(s32),
}
}

View File

@@ -0,0 +1,13 @@
interface nodejs {
/// Returns the path to the Node binary used by Zed.
node-binary-path: func() -> result<string, string>;
/// Returns the latest version of the given NPM package.
npm-package-latest-version: func(package-name: string) -> result<string, string>;
/// Returns the installed version of the given NPM package, if it exists.
npm-package-installed-version: func(package-name: string) -> result<option<string>, string>;
/// Installs the specified NPM package.
npm-install-package: func(package-name: string, version: string) -> result<_, string>;
}

View File

@@ -0,0 +1,24 @@
interface platform {
/// An operating system.
enum os {
/// macOS.
mac,
/// Linux.
linux,
/// Windows.
windows,
}
/// A platform architecture.
enum architecture {
/// AArch64 (e.g., Apple Silicon).
aarch64,
/// x86.
x86,
/// x86-64.
x8664,
}
/// Gets the current operating system and architecture.
current-platform: func() -> tuple<os, architecture>;
}

View File

@@ -0,0 +1,40 @@
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, num::NonZeroU32};
/// The settings for a particular language.
#[derive(Debug, Serialize, Deserialize)]
pub struct LanguageSettings {
/// How many columns a tab should occupy.
pub tab_size: NonZeroU32,
}
/// The settings for a particular language server.
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct LspSettings {
/// The settings for the language server binary.
pub binary: Option<CommandSettings>,
/// The initialization options to pass to the language server.
pub initialization_options: Option<serde_json::Value>,
/// The settings to pass to language server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a particular context server.
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct ContextServerSettings {
/// The settings for the context server binary.
pub command: Option<CommandSettings>,
/// The settings to pass to the context server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a command.
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct CommandSettings {
/// The path to the command.
pub path: Option<String>,
/// The arguments to pass to the command.
pub arguments: Option<Vec<String>>,
/// The environment variables.
pub env: Option<HashMap<String, String>>,
}

View File

@@ -0,0 +1,41 @@
interface slash-command {
use common.{range};
/// A slash command for use in the Assistant.
record slash-command {
/// The name of the slash command.
name: string,
/// The description of the slash command.
description: string,
/// The tooltip text to display for the run button.
tooltip-text: string,
/// Whether this slash command requires an argument.
requires-argument: bool,
}
/// The output of a slash command.
record slash-command-output {
/// The text produced by the slash command.
text: string,
/// The list of sections to show in the slash command placeholder.
sections: list<slash-command-output-section>,
}
/// A section in the slash command output.
record slash-command-output-section {
/// The range this section occupies.
range: range,
/// The label to display in the placeholder for this section.
label: string,
}
/// A completion for a slash command argument.
record slash-command-argument-completion {
/// The label to display for this completion.
label: string,
/// The new text that should be inserted into the command when this completion is accepted.
new-text: string,
/// Whether the command should be run when accepting this completion.
run-command: bool,
}
}

View File

@@ -0,0 +1,12 @@
interface common {
/// A (half-open) range (`[start, end)`).
record range {
/// The start of the range (inclusive).
start: u32,
/// The end of the range (exclusive).
end: u32,
}
/// A list of environment variables.
type env-vars = list<tuple<string, string>>;
}

View File

@@ -0,0 +1,145 @@
package zed:extension;
world extension {
import github;
import http-client;
import platform;
import process;
import nodejs;
use common.{env-vars, range};
use lsp.{completion, symbol};
use process.{command};
use slash-command.{slash-command, slash-command-argument-completion, slash-command-output};
/// Initializes the extension.
export init-extension: func();
/// The type of a downloaded file.
enum downloaded-file-type {
/// A gzipped file (`.gz`).
gzip,
/// A gzipped tar archive (`.tar.gz`).
gzip-tar,
/// A ZIP file (`.zip`).
zip,
/// An uncompressed file.
uncompressed,
}
/// The installation status for a language server.
variant language-server-installation-status {
/// The language server has no installation status.
none,
/// The language server is being downloaded.
downloading,
/// The language server is checking for updates.
checking-for-update,
/// The language server installation failed for specified reason.
failed(string),
}
record settings-location {
worktree-id: u64,
path: string,
}
import get-settings: func(path: option<settings-location>, category: string, key: option<string>) -> result<string, string>;
/// Downloads a file from the given URL and saves it to the given path within the extension's
/// working directory.
///
/// The file will be extracted according to the given file type.
import download-file: func(url: string, file-path: string, file-type: downloaded-file-type) -> result<_, string>;
/// Makes the file at the given path executable.
import make-file-executable: func(filepath: string) -> result<_, string>;
/// Updates the installation status for the given language server.
import set-language-server-installation-status: func(language-server-name: string, status: language-server-installation-status);
/// A Zed worktree.
resource worktree {
/// Returns the ID of the worktree.
id: func() -> u64;
/// Returns the root path of the worktree.
root-path: func() -> string;
/// Returns the textual contents of the specified file in the worktree.
read-text-file: func(path: string) -> result<string, string>;
/// Returns the path to the given binary name, if one is present on the `$PATH`.
which: func(binary-name: string) -> option<string>;
/// Returns the current shell environment.
shell-env: func() -> env-vars;
}
/// A Zed project.
resource project {
/// Returns the IDs of all of the worktrees in this project.
worktree-ids: func() -> list<u64>;
}
/// A key-value store.
resource key-value-store {
/// Inserts an entry under the specified key.
insert: func(key: string, value: string) -> result<_, string>;
}
/// Returns the command used to start up the language server.
export language-server-command: func(language-server-id: string, worktree: borrow<worktree>) -> result<command, string>;
/// Returns the initialization options to pass to the language server on startup.
///
/// The initialization options are represented as a JSON string.
export language-server-initialization-options: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the workspace configuration options to pass to the language server.
export language-server-workspace-configuration: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// A label containing some code.
record code-label {
/// The source code to parse with Tree-sitter.
code: string,
/// The spans to display in the label.
spans: list<code-label-span>,
/// The range of the displayed label to include when filtering.
filter-range: range,
}
/// A span within a code label.
variant code-label-span {
/// A range into the parsed code.
code-range(range),
/// A span containing a code literal.
literal(code-label-span-literal),
}
/// A span containing a code literal.
record code-label-span-literal {
/// The literal text.
text: string,
/// The name of the highlight to use for this literal.
highlight-name: option<string>,
}
export labels-for-completions: func(language-server-id: string, completions: list<completion>) -> result<list<option<code-label>>, string>;
export labels-for-symbols: func(language-server-id: string, symbols: list<symbol>) -> result<list<option<code-label>>, string>;
/// Returns the completions that should be shown when completing the provided slash command with the given query.
export complete-slash-command-argument: func(command: slash-command, args: list<string>) -> result<list<slash-command-argument-completion>, string>;
/// Returns the output from running the provided slash command.
export run-slash-command: func(command: slash-command, args: list<string>, worktree: option<borrow<worktree>>) -> result<slash-command-output, string>;
/// Returns the command used to start up a context server.
export context-server-command: func(context-server-id: string, project: borrow<project>) -> result<command, string>;
/// Returns a list of packages as suggestions to be included in the `/docs`
/// search results.
///
/// This can be used to provide completions for known packages (e.g., from the
/// local project or a registry) before a package has been indexed.
export suggest-docs-packages: func(provider-name: string) -> result<list<string>, string>;
/// Indexes the docs for the specified package.
export index-docs: func(provider-name: string, package-name: string, database: borrow<key-value-store>) -> result<_, string>;
}

View File

@@ -0,0 +1,35 @@
interface github {
/// A GitHub release.
record github-release {
/// The version of the release.
version: string,
/// The list of assets attached to the release.
assets: list<github-release-asset>,
}
/// An asset from a GitHub release.
record github-release-asset {
/// The name of the asset.
name: string,
/// The download URL for the asset.
download-url: string,
}
/// The options used to filter down GitHub releases.
record github-release-options {
/// Whether releases without assets should be included.
require-assets: bool,
/// Whether pre-releases should be included.
pre-release: bool,
}
/// Returns the latest release for the given GitHub repository.
///
/// Takes repo as a string in the form "<owner-name>/<repo-name>", for example: "zed-industries/zed".
latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
/// Returns the GitHub release with the specified tag name for the given GitHub repository.
///
/// Returns an error if a release with the given tag name does not exist.
github-release-by-tag-name: func(repo: string, tag: string) -> result<github-release, string>;
}

View File

@@ -0,0 +1,67 @@
interface http-client {
/// An HTTP request.
record http-request {
/// The HTTP method for the request.
method: http-method,
/// The URL to which the request should be made.
url: string,
/// The headers for the request.
headers: list<tuple<string, string>>,
/// The request body.
body: option<list<u8>>,
/// The policy to use for redirects.
redirect-policy: redirect-policy,
}
/// HTTP methods.
enum http-method {
/// `GET`
get,
/// `HEAD`
head,
/// `POST`
post,
/// `PUT`
put,
/// `DELETE`
delete,
/// `OPTIONS`
options,
/// `PATCH`
patch,
}
/// The policy for dealing with redirects received from the server.
variant redirect-policy {
/// Redirects from the server will not be followed.
///
/// This is the default behavior.
no-follow,
/// Redirects from the server will be followed up to the specified limit.
follow-limit(u32),
/// All redirects from the server will be followed.
follow-all,
}
/// An HTTP response.
record http-response {
/// The response headers.
headers: list<tuple<string, string>>,
/// The response body.
body: list<u8>,
}
/// Performs an HTTP request and returns the response.
fetch: func(req: http-request) -> result<http-response, string>;
/// An HTTP response stream.
resource http-response-stream {
/// Retrieves the next chunk of data from the response stream.
///
/// Returns `Ok(None)` if the stream has ended.
next-chunk: func() -> result<option<list<u8>>, string>;
}
/// Performs an HTTP request and returns a response stream.
fetch-stream: func(req: http-request) -> result<http-response-stream, string>;
}

View File

@@ -0,0 +1,90 @@
interface lsp {
/// An LSP completion.
record completion {
label: string,
label-details: option<completion-label-details>,
detail: option<string>,
kind: option<completion-kind>,
insert-text-format: option<insert-text-format>,
}
/// The kind of an LSP completion.
variant completion-kind {
text,
method,
function,
%constructor,
field,
variable,
class,
%interface,
module,
property,
unit,
value,
%enum,
keyword,
snippet,
color,
file,
reference,
folder,
enum-member,
constant,
struct,
event,
operator,
type-parameter,
other(s32),
}
/// Label details for an LSP completion.
record completion-label-details {
detail: option<string>,
description: option<string>,
}
/// Defines how to interpret the insert text in a completion item.
variant insert-text-format {
plain-text,
snippet,
other(s32),
}
/// An LSP symbol.
record symbol {
kind: symbol-kind,
name: string,
}
/// The kind of an LSP symbol.
variant symbol-kind {
file,
module,
namespace,
%package,
class,
method,
property,
field,
%constructor,
%enum,
%interface,
function,
variable,
constant,
%string,
number,
boolean,
array,
object,
key,
null,
enum-member,
struct,
event,
operator,
type-parameter,
other(s32),
}
}

View File

@@ -0,0 +1,13 @@
interface nodejs {
/// Returns the path to the Node binary used by Zed.
node-binary-path: func() -> result<string, string>;
/// Returns the latest version of the given NPM package.
npm-package-latest-version: func(package-name: string) -> result<string, string>;
/// Returns the installed version of the given NPM package, if it exists.
npm-package-installed-version: func(package-name: string) -> result<option<string>, string>;
/// Installs the specified NPM package.
npm-install-package: func(package-name: string, version: string) -> result<_, string>;
}

View File

@@ -0,0 +1,24 @@
interface platform {
/// An operating system.
enum os {
/// macOS.
mac,
/// Linux.
linux,
/// Windows.
windows,
}
/// A platform architecture.
enum architecture {
/// AArch64 (e.g., Apple Silicon).
aarch64,
/// x86.
x86,
/// x86-64.
x8664,
}
/// Gets the current operating system and architecture.
current-platform: func() -> tuple<os, architecture>;
}

View File

@@ -0,0 +1,29 @@
interface process {
use common.{env-vars};
/// A command.
record command {
/// The command to execute.
command: string,
/// The arguments to pass to the command.
args: list<string>,
/// The environment variables to set for the command.
env: env-vars,
}
/// The output of a finished process.
record output {
/// The status (exit code) of the process.
///
/// On Unix, this will be `None` if the process was terminated by a signal.
status: option<s32>,
/// The data that the process wrote to stdout.
stdout: list<u8>,
/// The data that the process wrote to stderr.
stderr: list<u8>,
}
/// Executes the given command as a child process, waiting for it to finish
/// and collecting all of its output.
run-command: func(command: command) -> result<output, string>;
}

View File

@@ -0,0 +1,40 @@
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, num::NonZeroU32};
/// The settings for a particular language.
#[derive(Debug, Serialize, Deserialize)]
pub struct LanguageSettings {
/// How many columns a tab should occupy.
pub tab_size: NonZeroU32,
}
/// The settings for a particular language server.
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct LspSettings {
/// The settings for the language server binary.
pub binary: Option<CommandSettings>,
/// The initialization options to pass to the language server.
pub initialization_options: Option<serde_json::Value>,
/// The settings to pass to language server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a particular context server.
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct ContextServerSettings {
/// The settings for the context server binary.
pub command: Option<CommandSettings>,
/// The settings to pass to the context server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a command.
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct CommandSettings {
/// The path to the command.
pub path: Option<String>,
/// The arguments to pass to the command.
pub arguments: Option<Vec<String>>,
/// The environment variables.
pub env: Option<HashMap<String, String>>,
}

View File

@@ -0,0 +1,41 @@
interface slash-command {
use common.{range};
/// A slash command for use in the Assistant.
record slash-command {
/// The name of the slash command.
name: string,
/// The description of the slash command.
description: string,
/// The tooltip text to display for the run button.
tooltip-text: string,
/// Whether this slash command requires an argument.
requires-argument: bool,
}
/// The output of a slash command.
record slash-command-output {
/// The text produced by the slash command.
text: string,
/// The list of sections to show in the slash command placeholder.
sections: list<slash-command-output-section>,
}
/// A section in the slash command output.
record slash-command-output-section {
/// The range this section occupies.
range: range,
/// The label to display in the placeholder for this section.
label: string,
}
/// A completion for a slash command argument.
record slash-command-argument-completion {
/// The label to display for this completion.
label: string,
/// The new text that should be inserted into the command when this completion is accepted.
new-text: string,
/// Whether the command should be run when accepting this completion.
run-command: bool,
}
}

View File

@@ -0,0 +1,12 @@
interface common {
/// A (half-open) range (`[start, end)`).
record range {
/// The start of the range (inclusive).
start: u32,
/// The end of the range (exclusive).
end: u32,
}
/// A list of environment variables.
type env-vars = list<tuple<string, string>>;
}

View File

@@ -0,0 +1,151 @@
package zed:extension;
world extension {
import github;
import http-client;
import platform;
import process;
import nodejs;
use common.{env-vars, range};
use lsp.{completion, symbol};
use process.{command};
use slash-command.{slash-command, slash-command-argument-completion, slash-command-output};
/// Initializes the extension.
export init-extension: func();
/// The type of a downloaded file.
enum downloaded-file-type {
/// A gzipped file (`.gz`).
gzip,
/// A gzipped tar archive (`.tar.gz`).
gzip-tar,
/// A ZIP file (`.zip`).
zip,
/// An uncompressed file.
uncompressed,
}
/// The installation status for a language server.
variant language-server-installation-status {
/// The language server has no installation status.
none,
/// The language server is being downloaded.
downloading,
/// The language server is checking for updates.
checking-for-update,
/// The language server installation failed for specified reason.
failed(string),
}
record settings-location {
worktree-id: u64,
path: string,
}
import get-settings: func(path: option<settings-location>, category: string, key: option<string>) -> result<string, string>;
/// Downloads a file from the given URL and saves it to the given path within the extension's
/// working directory.
///
/// The file will be extracted according to the given file type.
import download-file: func(url: string, file-path: string, file-type: downloaded-file-type) -> result<_, string>;
/// Makes the file at the given path executable.
import make-file-executable: func(filepath: string) -> result<_, string>;
/// Updates the installation status for the given language server.
import set-language-server-installation-status: func(language-server-name: string, status: language-server-installation-status);
/// A Zed worktree.
resource worktree {
/// Returns the ID of the worktree.
id: func() -> u64;
/// Returns the root path of the worktree.
root-path: func() -> string;
/// Returns the textual contents of the specified file in the worktree.
read-text-file: func(path: string) -> result<string, string>;
/// Returns the path to the given binary name, if one is present on the `$PATH`.
which: func(binary-name: string) -> option<string>;
/// Returns the current shell environment.
shell-env: func() -> env-vars;
}
/// A Zed project.
resource project {
/// Returns the IDs of all of the worktrees in this project.
worktree-ids: func() -> list<u64>;
}
/// A key-value store.
resource key-value-store {
/// Inserts an entry under the specified key.
insert: func(key: string, value: string) -> result<_, string>;
}
/// Returns the command used to start up the language server.
export language-server-command: func(language-server-id: string, worktree: borrow<worktree>) -> result<command, string>;
/// Returns the initialization options to pass to the language server on startup.
///
/// The initialization options are represented as a JSON string.
export language-server-initialization-options: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the workspace configuration options to pass to the language server.
export language-server-workspace-configuration: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the initialization options to pass to the other language server.
export language-server-additional-initialization-options: func(language-server-id: string, target-language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the workspace configuration options to pass to the other language server.
export language-server-additional-workspace-configuration: func(language-server-id: string, target-language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// A label containing some code.
record code-label {
/// The source code to parse with Tree-sitter.
code: string,
/// The spans to display in the label.
spans: list<code-label-span>,
/// The range of the displayed label to include when filtering.
filter-range: range,
}
/// A span within a code label.
variant code-label-span {
/// A range into the parsed code.
code-range(range),
/// A span containing a code literal.
literal(code-label-span-literal),
}
/// A span containing a code literal.
record code-label-span-literal {
/// The literal text.
text: string,
/// The name of the highlight to use for this literal.
highlight-name: option<string>,
}
export labels-for-completions: func(language-server-id: string, completions: list<completion>) -> result<list<option<code-label>>, string>;
export labels-for-symbols: func(language-server-id: string, symbols: list<symbol>) -> result<list<option<code-label>>, string>;
/// Returns the completions that should be shown when completing the provided slash command with the given query.
export complete-slash-command-argument: func(command: slash-command, args: list<string>) -> result<list<slash-command-argument-completion>, string>;
/// Returns the output from running the provided slash command.
export run-slash-command: func(command: slash-command, args: list<string>, worktree: option<borrow<worktree>>) -> result<slash-command-output, string>;
/// Returns the command used to start up a context server.
export context-server-command: func(context-server-id: string, project: borrow<project>) -> result<command, string>;
/// Returns a list of packages as suggestions to be included in the `/docs`
/// search results.
///
/// This can be used to provide completions for known packages (e.g., from the
/// local project or a registry) before a package has been indexed.
export suggest-docs-packages: func(provider-name: string) -> result<list<string>, string>;
/// Indexes the docs for the specified package.
export index-docs: func(provider-name: string, package-name: string, database: borrow<key-value-store>) -> result<_, string>;
}

View File

@@ -0,0 +1,35 @@
interface github {
/// A GitHub release.
record github-release {
/// The version of the release.
version: string,
/// The list of assets attached to the release.
assets: list<github-release-asset>,
}
/// An asset from a GitHub release.
record github-release-asset {
/// The name of the asset.
name: string,
/// The download URL for the asset.
download-url: string,
}
/// The options used to filter down GitHub releases.
record github-release-options {
/// Whether releases without assets should be included.
require-assets: bool,
/// Whether pre-releases should be included.
pre-release: bool,
}
/// Returns the latest release for the given GitHub repository.
///
/// Takes repo as a string in the form "<owner-name>/<repo-name>", for example: "zed-industries/zed".
latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
/// Returns the GitHub release with the specified tag name for the given GitHub repository.
///
/// Returns an error if a release with the given tag name does not exist.
github-release-by-tag-name: func(repo: string, tag: string) -> result<github-release, string>;
}

View File

@@ -0,0 +1,67 @@
interface http-client {
/// An HTTP request.
record http-request {
/// The HTTP method for the request.
method: http-method,
/// The URL to which the request should be made.
url: string,
/// The headers for the request.
headers: list<tuple<string, string>>,
/// The request body.
body: option<list<u8>>,
/// The policy to use for redirects.
redirect-policy: redirect-policy,
}
/// HTTP methods.
enum http-method {
/// `GET`
get,
/// `HEAD`
head,
/// `POST`
post,
/// `PUT`
put,
/// `DELETE`
delete,
/// `OPTIONS`
options,
/// `PATCH`
patch,
}
/// The policy for dealing with redirects received from the server.
variant redirect-policy {
/// Redirects from the server will not be followed.
///
/// This is the default behavior.
no-follow,
/// Redirects from the server will be followed up to the specified limit.
follow-limit(u32),
/// All redirects from the server will be followed.
follow-all,
}
/// An HTTP response.
record http-response {
/// The response headers.
headers: list<tuple<string, string>>,
/// The response body.
body: list<u8>,
}
/// Performs an HTTP request and returns the response.
fetch: func(req: http-request) -> result<http-response, string>;
/// An HTTP response stream.
resource http-response-stream {
/// Retrieves the next chunk of data from the response stream.
///
/// Returns `Ok(None)` if the stream has ended.
next-chunk: func() -> result<option<list<u8>>, string>;
}
/// Performs an HTTP request and returns a response stream.
fetch-stream: func(req: http-request) -> result<http-response-stream, string>;
}

View File

@@ -0,0 +1,90 @@
interface lsp {
/// An LSP completion.
record completion {
label: string,
label-details: option<completion-label-details>,
detail: option<string>,
kind: option<completion-kind>,
insert-text-format: option<insert-text-format>,
}
/// The kind of an LSP completion.
variant completion-kind {
text,
method,
function,
%constructor,
field,
variable,
class,
%interface,
module,
property,
unit,
value,
%enum,
keyword,
snippet,
color,
file,
reference,
folder,
enum-member,
constant,
struct,
event,
operator,
type-parameter,
other(s32),
}
/// Label details for an LSP completion.
record completion-label-details {
detail: option<string>,
description: option<string>,
}
/// Defines how to interpret the insert text in a completion item.
variant insert-text-format {
plain-text,
snippet,
other(s32),
}
/// An LSP symbol.
record symbol {
kind: symbol-kind,
name: string,
}
/// The kind of an LSP symbol.
variant symbol-kind {
file,
module,
namespace,
%package,
class,
method,
property,
field,
%constructor,
%enum,
%interface,
function,
variable,
constant,
%string,
number,
boolean,
array,
object,
key,
null,
enum-member,
struct,
event,
operator,
type-parameter,
other(s32),
}
}

View File

@@ -0,0 +1,13 @@
interface nodejs {
/// Returns the path to the Node binary used by Zed.
node-binary-path: func() -> result<string, string>;
/// Returns the latest version of the given NPM package.
npm-package-latest-version: func(package-name: string) -> result<string, string>;
/// Returns the installed version of the given NPM package, if it exists.
npm-package-installed-version: func(package-name: string) -> result<option<string>, string>;
/// Installs the specified NPM package.
npm-install-package: func(package-name: string, version: string) -> result<_, string>;
}

View File

@@ -0,0 +1,24 @@
interface platform {
/// An operating system.
enum os {
/// macOS.
mac,
/// Linux.
linux,
/// Windows.
windows,
}
/// A platform architecture.
enum architecture {
/// AArch64 (e.g., Apple Silicon).
aarch64,
/// x86.
x86,
/// x86-64.
x8664,
}
/// Gets the current operating system and architecture.
current-platform: func() -> tuple<os, architecture>;
}

View File

@@ -0,0 +1,29 @@
interface process {
use common.{env-vars};
/// A command.
record command {
/// The command to execute.
command: string,
/// The arguments to pass to the command.
args: list<string>,
/// The environment variables to set for the command.
env: env-vars,
}
/// The output of a finished process.
record output {
/// The status (exit code) of the process.
///
/// On Unix, this will be `None` if the process was terminated by a signal.
status: option<s32>,
/// The data that the process wrote to stdout.
stdout: list<u8>,
/// The data that the process wrote to stderr.
stderr: list<u8>,
}
/// Executes the given command as a child process, waiting for it to finish
/// and collecting all of its output.
run-command: func(command: command) -> result<output, string>;
}

View File

@@ -0,0 +1,40 @@
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, num::NonZeroU32};
/// The settings for a particular language.
#[derive(Debug, Serialize, Deserialize)]
pub struct LanguageSettings {
/// How many columns a tab should occupy.
pub tab_size: NonZeroU32,
}
/// The settings for a particular language server.
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct LspSettings {
/// The settings for the language server binary.
pub binary: Option<CommandSettings>,
/// The initialization options to pass to the language server.
pub initialization_options: Option<serde_json::Value>,
/// The settings to pass to language server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a particular context server.
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct ContextServerSettings {
/// The settings for the context server binary.
pub command: Option<CommandSettings>,
/// The settings to pass to the context server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a command.
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct CommandSettings {
/// The path to the command.
pub path: Option<String>,
/// The arguments to pass to the command.
pub arguments: Option<Vec<String>>,
/// The environment variables.
pub env: Option<HashMap<String, String>>,
}

View File

@@ -0,0 +1,41 @@
interface slash-command {
use common.{range};
/// A slash command for use in the Assistant.
record slash-command {
/// The name of the slash command.
name: string,
/// The description of the slash command.
description: string,
/// The tooltip text to display for the run button.
tooltip-text: string,
/// Whether this slash command requires an argument.
requires-argument: bool,
}
/// The output of a slash command.
record slash-command-output {
/// The text produced by the slash command.
text: string,
/// The list of sections to show in the slash command placeholder.
sections: list<slash-command-output-section>,
}
/// A section in the slash command output.
record slash-command-output-section {
/// The range this section occupies.
range: range,
/// The label to display in the placeholder for this section.
label: string,
}
/// A completion for a slash command argument.
record slash-command-argument-completion {
/// The label to display for this completion.
label: string,
/// The new text that should be inserted into the command when this completion is accepted.
new-text: string,
/// Whether the command should be run when accepting this completion.
run-command: bool,
}
}

View File

@@ -0,0 +1,12 @@
interface common {
/// A (half-open) range (`[start, end)`).
record range {
/// The start of the range (inclusive).
start: u32,
/// The end of the range (exclusive).
end: u32,
}
/// A list of environment variables.
type env-vars = list<tuple<string, string>>;
}

View File

@@ -0,0 +1,11 @@
interface context-server {
/// Configuration for context server setup and installation.
record context-server-configuration {
/// Installation instructions in Markdown format.
installation-instructions: string,
/// JSON schema for settings validation.
settings-schema: string,
/// Default settings template.
default-settings: string,
}
}

View File

@@ -0,0 +1,156 @@
package zed:extension;
world extension {
import context-server;
import github;
import http-client;
import platform;
import process;
import nodejs;
use common.{env-vars, range};
use context-server.{context-server-configuration};
use lsp.{completion, symbol};
use process.{command};
use slash-command.{slash-command, slash-command-argument-completion, slash-command-output};
/// Initializes the extension.
export init-extension: func();
/// The type of a downloaded file.
enum downloaded-file-type {
/// A gzipped file (`.gz`).
gzip,
/// A gzipped tar archive (`.tar.gz`).
gzip-tar,
/// A ZIP file (`.zip`).
zip,
/// An uncompressed file.
uncompressed,
}
/// The installation status for a language server.
variant language-server-installation-status {
/// The language server has no installation status.
none,
/// The language server is being downloaded.
downloading,
/// The language server is checking for updates.
checking-for-update,
/// The language server installation failed for specified reason.
failed(string),
}
record settings-location {
worktree-id: u64,
path: string,
}
import get-settings: func(path: option<settings-location>, category: string, key: option<string>) -> result<string, string>;
/// Downloads a file from the given URL and saves it to the given path within the extension's
/// working directory.
///
/// The file will be extracted according to the given file type.
import download-file: func(url: string, file-path: string, file-type: downloaded-file-type) -> result<_, string>;
/// Makes the file at the given path executable.
import make-file-executable: func(filepath: string) -> result<_, string>;
/// Updates the installation status for the given language server.
import set-language-server-installation-status: func(language-server-name: string, status: language-server-installation-status);
/// A Zed worktree.
resource worktree {
/// Returns the ID of the worktree.
id: func() -> u64;
/// Returns the root path of the worktree.
root-path: func() -> string;
/// Returns the textual contents of the specified file in the worktree.
read-text-file: func(path: string) -> result<string, string>;
/// Returns the path to the given binary name, if one is present on the `$PATH`.
which: func(binary-name: string) -> option<string>;
/// Returns the current shell environment.
shell-env: func() -> env-vars;
}
/// A Zed project.
resource project {
/// Returns the IDs of all of the worktrees in this project.
worktree-ids: func() -> list<u64>;
}
/// A key-value store.
resource key-value-store {
/// Inserts an entry under the specified key.
insert: func(key: string, value: string) -> result<_, string>;
}
/// Returns the command used to start up the language server.
export language-server-command: func(language-server-id: string, worktree: borrow<worktree>) -> result<command, string>;
/// Returns the initialization options to pass to the language server on startup.
///
/// The initialization options are represented as a JSON string.
export language-server-initialization-options: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the workspace configuration options to pass to the language server.
export language-server-workspace-configuration: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the initialization options to pass to the other language server.
export language-server-additional-initialization-options: func(language-server-id: string, target-language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the workspace configuration options to pass to the other language server.
export language-server-additional-workspace-configuration: func(language-server-id: string, target-language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// A label containing some code.
record code-label {
/// The source code to parse with Tree-sitter.
code: string,
/// The spans to display in the label.
spans: list<code-label-span>,
/// The range of the displayed label to include when filtering.
filter-range: range,
}
/// A span within a code label.
variant code-label-span {
/// A range into the parsed code.
code-range(range),
/// A span containing a code literal.
literal(code-label-span-literal),
}
/// A span containing a code literal.
record code-label-span-literal {
/// The literal text.
text: string,
/// The name of the highlight to use for this literal.
highlight-name: option<string>,
}
export labels-for-completions: func(language-server-id: string, completions: list<completion>) -> result<list<option<code-label>>, string>;
export labels-for-symbols: func(language-server-id: string, symbols: list<symbol>) -> result<list<option<code-label>>, string>;
/// Returns the completions that should be shown when completing the provided slash command with the given query.
export complete-slash-command-argument: func(command: slash-command, args: list<string>) -> result<list<slash-command-argument-completion>, string>;
/// Returns the output from running the provided slash command.
export run-slash-command: func(command: slash-command, args: list<string>, worktree: option<borrow<worktree>>) -> result<slash-command-output, string>;
/// Returns the command used to start up a context server.
export context-server-command: func(context-server-id: string, project: borrow<project>) -> result<command, string>;
/// Returns the configuration for a context server.
export context-server-configuration: func(context-server-id: string, project: borrow<project>) -> result<option<context-server-configuration>, string>;
/// Returns a list of packages as suggestions to be included in the `/docs`
/// search results.
///
/// This can be used to provide completions for known packages (e.g., from the
/// local project or a registry) before a package has been indexed.
export suggest-docs-packages: func(provider-name: string) -> result<list<string>, string>;
/// Indexes the docs for the specified package.
export index-docs: func(provider-name: string, package-name: string, database: borrow<key-value-store>) -> result<_, string>;
}

View File

@@ -0,0 +1,35 @@
interface github {
/// A GitHub release.
record github-release {
/// The version of the release.
version: string,
/// The list of assets attached to the release.
assets: list<github-release-asset>,
}
/// An asset from a GitHub release.
record github-release-asset {
/// The name of the asset.
name: string,
/// The download URL for the asset.
download-url: string,
}
/// The options used to filter down GitHub releases.
record github-release-options {
/// Whether releases without assets should be included.
require-assets: bool,
/// Whether pre-releases should be included.
pre-release: bool,
}
/// Returns the latest release for the given GitHub repository.
///
/// Takes repo as a string in the form "<owner-name>/<repo-name>", for example: "zed-industries/zed".
latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
/// Returns the GitHub release with the specified tag name for the given GitHub repository.
///
/// Returns an error if a release with the given tag name does not exist.
github-release-by-tag-name: func(repo: string, tag: string) -> result<github-release, string>;
}

View File

@@ -0,0 +1,67 @@
interface http-client {
/// An HTTP request.
record http-request {
/// The HTTP method for the request.
method: http-method,
/// The URL to which the request should be made.
url: string,
/// The headers for the request.
headers: list<tuple<string, string>>,
/// The request body.
body: option<list<u8>>,
/// The policy to use for redirects.
redirect-policy: redirect-policy,
}
/// HTTP methods.
enum http-method {
/// `GET`
get,
/// `HEAD`
head,
/// `POST`
post,
/// `PUT`
put,
/// `DELETE`
delete,
/// `OPTIONS`
options,
/// `PATCH`
patch,
}
/// The policy for dealing with redirects received from the server.
variant redirect-policy {
/// Redirects from the server will not be followed.
///
/// This is the default behavior.
no-follow,
/// Redirects from the server will be followed up to the specified limit.
follow-limit(u32),
/// All redirects from the server will be followed.
follow-all,
}
/// An HTTP response.
record http-response {
/// The response headers.
headers: list<tuple<string, string>>,
/// The response body.
body: list<u8>,
}
/// Performs an HTTP request and returns the response.
fetch: func(req: http-request) -> result<http-response, string>;
/// An HTTP response stream.
resource http-response-stream {
/// Retrieves the next chunk of data from the response stream.
///
/// Returns `Ok(None)` if the stream has ended.
next-chunk: func() -> result<option<list<u8>>, string>;
}
/// Performs an HTTP request and returns a response stream.
fetch-stream: func(req: http-request) -> result<http-response-stream, string>;
}

View File

@@ -0,0 +1,90 @@
interface lsp {
/// An LSP completion.
record completion {
label: string,
label-details: option<completion-label-details>,
detail: option<string>,
kind: option<completion-kind>,
insert-text-format: option<insert-text-format>,
}
/// The kind of an LSP completion.
variant completion-kind {
text,
method,
function,
%constructor,
field,
variable,
class,
%interface,
module,
property,
unit,
value,
%enum,
keyword,
snippet,
color,
file,
reference,
folder,
enum-member,
constant,
struct,
event,
operator,
type-parameter,
other(s32),
}
/// Label details for an LSP completion.
record completion-label-details {
detail: option<string>,
description: option<string>,
}
/// Defines how to interpret the insert text in a completion item.
variant insert-text-format {
plain-text,
snippet,
other(s32),
}
/// An LSP symbol.
record symbol {
kind: symbol-kind,
name: string,
}
/// The kind of an LSP symbol.
variant symbol-kind {
file,
module,
namespace,
%package,
class,
method,
property,
field,
%constructor,
%enum,
%interface,
function,
variable,
constant,
%string,
number,
boolean,
array,
object,
key,
null,
enum-member,
struct,
event,
operator,
type-parameter,
other(s32),
}
}

View File

@@ -0,0 +1,13 @@
interface nodejs {
/// Returns the path to the Node binary used by Zed.
node-binary-path: func() -> result<string, string>;
/// Returns the latest version of the given NPM package.
npm-package-latest-version: func(package-name: string) -> result<string, string>;
/// Returns the installed version of the given NPM package, if it exists.
npm-package-installed-version: func(package-name: string) -> result<option<string>, string>;
/// Installs the specified NPM package.
npm-install-package: func(package-name: string, version: string) -> result<_, string>;
}

View File

@@ -0,0 +1,24 @@
interface platform {
/// An operating system.
enum os {
/// macOS.
mac,
/// Linux.
linux,
/// Windows.
windows,
}
/// A platform architecture.
enum architecture {
/// AArch64 (e.g., Apple Silicon).
aarch64,
/// x86.
x86,
/// x86-64.
x8664,
}
/// Gets the current operating system and architecture.
current-platform: func() -> tuple<os, architecture>;
}

View File

@@ -0,0 +1,29 @@
interface process {
use common.{env-vars};
/// A command.
record command {
/// The command to execute.
command: string,
/// The arguments to pass to the command.
args: list<string>,
/// The environment variables to set for the command.
env: env-vars,
}
/// The output of a finished process.
record output {
/// The status (exit code) of the process.
///
/// On Unix, this will be `None` if the process was terminated by a signal.
status: option<s32>,
/// The data that the process wrote to stdout.
stdout: list<u8>,
/// The data that the process wrote to stderr.
stderr: list<u8>,
}
/// Executes the given command as a child process, waiting for it to finish
/// and collecting all of its output.
run-command: func(command: command) -> result<output, string>;
}

View File

@@ -0,0 +1,40 @@
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, num::NonZeroU32};
/// The settings for a particular language.
#[derive(Debug, Serialize, Deserialize)]
pub struct LanguageSettings {
/// How many columns a tab should occupy.
pub tab_size: NonZeroU32,
}
/// The settings for a particular language server.
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct LspSettings {
/// The settings for the language server binary.
pub binary: Option<CommandSettings>,
/// The initialization options to pass to the language server.
pub initialization_options: Option<serde_json::Value>,
/// The settings to pass to language server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a particular context server.
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct ContextServerSettings {
/// The settings for the context server binary.
pub command: Option<CommandSettings>,
/// The settings to pass to the context server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a command.
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct CommandSettings {
/// The path to the command.
pub path: Option<String>,
/// The arguments to pass to the command.
pub arguments: Option<Vec<String>>,
/// The environment variables.
pub env: Option<HashMap<String, String>>,
}

View File

@@ -0,0 +1,41 @@
interface slash-command {
use common.{range};
/// A slash command for use in the Assistant.
record slash-command {
/// The name of the slash command.
name: string,
/// The description of the slash command.
description: string,
/// The tooltip text to display for the run button.
tooltip-text: string,
/// Whether this slash command requires an argument.
requires-argument: bool,
}
/// The output of a slash command.
record slash-command-output {
/// The text produced by the slash command.
text: string,
/// The list of sections to show in the slash command placeholder.
sections: list<slash-command-output-section>,
}
/// A section in the slash command output.
record slash-command-output-section {
/// The range this section occupies.
range: range,
/// The label to display in the placeholder for this section.
label: string,
}
/// A completion for a slash command argument.
record slash-command-argument-completion {
/// The label to display for this completion.
label: string,
/// The new text that should be inserted into the command when this completion is accepted.
new-text: string,
/// Whether the command should be run when accepting this completion.
run-command: bool,
}
}

View File

@@ -0,0 +1,12 @@
interface common {
/// A (half-open) range (`[start, end)`).
record range {
/// The start of the range (inclusive).
start: u32,
/// The end of the range (exclusive).
end: u32,
}
/// A list of environment variables.
type env-vars = list<tuple<string, string>>;
}

View File

@@ -0,0 +1,11 @@
interface context-server {
/// Configuration for context server setup and installation.
record context-server-configuration {
/// Installation instructions in Markdown format.
installation-instructions: string,
/// JSON schema for settings validation.
settings-schema: string,
/// Default settings template.
default-settings: string,
}
}

View File

@@ -0,0 +1,123 @@
interface dap {
use common.{env-vars};
/// Resolves a specified TcpArgumentsTemplate into TcpArguments
resolve-tcp-template: func(template: tcp-arguments-template) -> result<tcp-arguments, string>;
record launch-request {
program: string,
cwd: option<string>,
args: list<string>,
envs: env-vars,
}
record attach-request {
process-id: option<u32>,
}
variant debug-request {
launch(launch-request),
attach(attach-request)
}
record tcp-arguments {
port: u16,
host: u32,
timeout: option<u64>,
}
record tcp-arguments-template {
port: option<u16>,
host: option<u32>,
timeout: option<u64>,
}
/// Debug Config is the "highest-level" configuration for a debug session.
/// It comes from a new process modal UI; thus, it is essentially debug-adapter-agnostic.
/// It is expected of the extension to translate this generic configuration into something that can be debugged by the adapter (debug scenario).
record debug-config {
/// Name of the debug task
label: string,
/// The debug adapter to use
adapter: string,
request: debug-request,
stop-on-entry: option<bool>,
}
record task-template {
/// Human readable name of the task to display in the UI.
label: string,
/// Executable command to spawn.
command: string,
args: list<string>,
env: env-vars,
cwd: option<string>,
}
/// A task template with substituted task variables.
type resolved-task = task-template;
/// A task template for building a debug target.
type build-task-template = task-template;
variant build-task-definition {
by-name(string),
template(build-task-definition-template-payload )
}
record build-task-definition-template-payload {
locator-name: option<string>,
template: build-task-template
}
/// Debug Scenario is the user-facing configuration type (used in debug.json). It is still concerned with what to debug and not necessarily how to do it (except for any
/// debug-adapter-specific configuration options).
record debug-scenario {
/// Unsubstituted label for the task.DebugAdapterBinary
label: string,
/// Name of the Debug Adapter this configuration is intended for.
adapter: string,
/// An optional build step to be ran prior to starting a debug session. Build steps are used by Zed's locators to locate the executable to debug.
build: option<build-task-definition>,
/// JSON-encoded configuration for a given debug adapter.
config: string,
/// TCP connection parameters (if they were specified by user)
tcp-connection: option<tcp-arguments-template>,
}
enum start-debugging-request-arguments-request {
launch,
attach,
}
record debug-task-definition {
/// Unsubstituted label for the task.DebugAdapterBinary
label: string,
/// Name of the Debug Adapter this configuration is intended for.
adapter: string,
/// JSON-encoded configuration for a given debug adapter.
config: string,
/// TCP connection parameters (if they were specified by user)
tcp-connection: option<tcp-arguments-template>,
}
record start-debugging-request-arguments {
/// JSON-encoded configuration for a given debug adapter. It is specific to each debug adapter.
/// `configuration` will have it's Zed variable references substituted prior to being passed to the debug adapter.
configuration: string,
request: start-debugging-request-arguments-request,
}
/// The lowest-level representation of a debug session, which specifies:
/// - How to start a debug adapter process
/// - How to start a debug session with it (using DAP protocol)
/// for a given debug scenario.
record debug-adapter-binary {
command: option<string>,
arguments: list<string>,
envs: env-vars,
cwd: option<string>,
/// Zed will use TCP transport if `connection` is specified.
connection: option<tcp-arguments>,
request-args: start-debugging-request-arguments
}
}

View File

@@ -0,0 +1,167 @@
package zed:extension;
world extension {
import context-server;
import dap;
import github;
import http-client;
import platform;
import process;
import nodejs;
use common.{env-vars, range};
use context-server.{context-server-configuration};
use dap.{attach-request, build-task-template, debug-config, debug-adapter-binary, debug-task-definition, debug-request, debug-scenario, launch-request, resolved-task, start-debugging-request-arguments-request};
use lsp.{completion, symbol};
use process.{command};
use slash-command.{slash-command, slash-command-argument-completion, slash-command-output};
/// Initializes the extension.
export init-extension: func();
/// The type of a downloaded file.
enum downloaded-file-type {
/// A gzipped file (`.gz`).
gzip,
/// A gzipped tar archive (`.tar.gz`).
gzip-tar,
/// A ZIP file (`.zip`).
zip,
/// An uncompressed file.
uncompressed,
}
/// The installation status for a language server.
variant language-server-installation-status {
/// The language server has no installation status.
none,
/// The language server is being downloaded.
downloading,
/// The language server is checking for updates.
checking-for-update,
/// The language server installation failed for specified reason.
failed(string),
}
record settings-location {
worktree-id: u64,
path: string,
}
import get-settings: func(path: option<settings-location>, category: string, key: option<string>) -> result<string, string>;
/// Downloads a file from the given URL and saves it to the given path within the extension's
/// working directory.
///
/// The file will be extracted according to the given file type.
import download-file: func(url: string, file-path: string, file-type: downloaded-file-type) -> result<_, string>;
/// Makes the file at the given path executable.
import make-file-executable: func(filepath: string) -> result<_, string>;
/// Updates the installation status for the given language server.
import set-language-server-installation-status: func(language-server-name: string, status: language-server-installation-status);
/// A Zed worktree.
resource worktree {
/// Returns the ID of the worktree.
id: func() -> u64;
/// Returns the root path of the worktree.
root-path: func() -> string;
/// Returns the textual contents of the specified file in the worktree.
read-text-file: func(path: string) -> result<string, string>;
/// Returns the path to the given binary name, if one is present on the `$PATH`.
which: func(binary-name: string) -> option<string>;
/// Returns the current shell environment.
shell-env: func() -> env-vars;
}
/// A Zed project.
resource project {
/// Returns the IDs of all of the worktrees in this project.
worktree-ids: func() -> list<u64>;
}
/// A key-value store.
resource key-value-store {
/// Inserts an entry under the specified key.
insert: func(key: string, value: string) -> result<_, string>;
}
/// Returns the command used to start up the language server.
export language-server-command: func(language-server-id: string, worktree: borrow<worktree>) -> result<command, string>;
/// Returns the initialization options to pass to the language server on startup.
///
/// The initialization options are represented as a JSON string.
export language-server-initialization-options: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the workspace configuration options to pass to the language server.
export language-server-workspace-configuration: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the initialization options to pass to the other language server.
export language-server-additional-initialization-options: func(language-server-id: string, target-language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the workspace configuration options to pass to the other language server.
export language-server-additional-workspace-configuration: func(language-server-id: string, target-language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// A label containing some code.
record code-label {
/// The source code to parse with Tree-sitter.
code: string,
/// The spans to display in the label.
spans: list<code-label-span>,
/// The range of the displayed label to include when filtering.
filter-range: range,
}
/// A span within a code label.
variant code-label-span {
/// A range into the parsed code.
code-range(range),
/// A span containing a code literal.
literal(code-label-span-literal),
}
/// A span containing a code literal.
record code-label-span-literal {
/// The literal text.
text: string,
/// The name of the highlight to use for this literal.
highlight-name: option<string>,
}
export labels-for-completions: func(language-server-id: string, completions: list<completion>) -> result<list<option<code-label>>, string>;
export labels-for-symbols: func(language-server-id: string, symbols: list<symbol>) -> result<list<option<code-label>>, string>;
/// Returns the completions that should be shown when completing the provided slash command with the given query.
export complete-slash-command-argument: func(command: slash-command, args: list<string>) -> result<list<slash-command-argument-completion>, string>;
/// Returns the output from running the provided slash command.
export run-slash-command: func(command: slash-command, args: list<string>, worktree: option<borrow<worktree>>) -> result<slash-command-output, string>;
/// Returns the command used to start up a context server.
export context-server-command: func(context-server-id: string, project: borrow<project>) -> result<command, string>;
/// Returns the configuration for a context server.
export context-server-configuration: func(context-server-id: string, project: borrow<project>) -> result<option<context-server-configuration>, string>;
/// Returns a list of packages as suggestions to be included in the `/docs`
/// search results.
///
/// This can be used to provide completions for known packages (e.g., from the
/// local project or a registry) before a package has been indexed.
export suggest-docs-packages: func(provider-name: string) -> result<list<string>, string>;
/// Indexes the docs for the specified package.
export index-docs: func(provider-name: string, package-name: string, database: borrow<key-value-store>) -> result<_, string>;
/// Returns a configured debug adapter binary for a given debug task.
export get-dap-binary: func(adapter-name: string, config: debug-task-definition, user-installed-path: option<string>, worktree: borrow<worktree>) -> result<debug-adapter-binary, string>;
/// Returns the kind of a debug scenario (launch or attach).
export dap-request-kind: func(adapter-name: string, config: string) -> result<start-debugging-request-arguments-request, string>;
export dap-config-to-scenario: func(config: debug-config) -> result<debug-scenario, string>;
export dap-locator-create-scenario: func(locator-name: string, build-config-template: build-task-template, resolved-label: string, debug-adapter-name: string) -> option<debug-scenario>;
export run-dap-locator: func(locator-name: string, config: resolved-task) -> result<debug-request, string>;
}

View File

@@ -0,0 +1,35 @@
interface github {
/// A GitHub release.
record github-release {
/// The version of the release.
version: string,
/// The list of assets attached to the release.
assets: list<github-release-asset>,
}
/// An asset from a GitHub release.
record github-release-asset {
/// The name of the asset.
name: string,
/// The download URL for the asset.
download-url: string,
}
/// The options used to filter down GitHub releases.
record github-release-options {
/// Whether releases without assets should be included.
require-assets: bool,
/// Whether pre-releases should be included.
pre-release: bool,
}
/// Returns the latest release for the given GitHub repository.
///
/// Takes repo as a string in the form "<owner-name>/<repo-name>", for example: "zed-industries/zed".
latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
/// Returns the GitHub release with the specified tag name for the given GitHub repository.
///
/// Returns an error if a release with the given tag name does not exist.
github-release-by-tag-name: func(repo: string, tag: string) -> result<github-release, string>;
}

View File

@@ -0,0 +1,67 @@
interface http-client {
/// An HTTP request.
record http-request {
/// The HTTP method for the request.
method: http-method,
/// The URL to which the request should be made.
url: string,
/// The headers for the request.
headers: list<tuple<string, string>>,
/// The request body.
body: option<list<u8>>,
/// The policy to use for redirects.
redirect-policy: redirect-policy,
}
/// HTTP methods.
enum http-method {
/// `GET`
get,
/// `HEAD`
head,
/// `POST`
post,
/// `PUT`
put,
/// `DELETE`
delete,
/// `OPTIONS`
options,
/// `PATCH`
patch,
}
/// The policy for dealing with redirects received from the server.
variant redirect-policy {
/// Redirects from the server will not be followed.
///
/// This is the default behavior.
no-follow,
/// Redirects from the server will be followed up to the specified limit.
follow-limit(u32),
/// All redirects from the server will be followed.
follow-all,
}
/// An HTTP response.
record http-response {
/// The response headers.
headers: list<tuple<string, string>>,
/// The response body.
body: list<u8>,
}
/// Performs an HTTP request and returns the response.
fetch: func(req: http-request) -> result<http-response, string>;
/// An HTTP response stream.
resource http-response-stream {
/// Retrieves the next chunk of data from the response stream.
///
/// Returns `Ok(None)` if the stream has ended.
next-chunk: func() -> result<option<list<u8>>, string>;
}
/// Performs an HTTP request and returns a response stream.
fetch-stream: func(req: http-request) -> result<http-response-stream, string>;
}

View File

@@ -0,0 +1,90 @@
interface lsp {
/// An LSP completion.
record completion {
label: string,
label-details: option<completion-label-details>,
detail: option<string>,
kind: option<completion-kind>,
insert-text-format: option<insert-text-format>,
}
/// The kind of an LSP completion.
variant completion-kind {
text,
method,
function,
%constructor,
field,
variable,
class,
%interface,
module,
property,
unit,
value,
%enum,
keyword,
snippet,
color,
file,
reference,
folder,
enum-member,
constant,
struct,
event,
operator,
type-parameter,
other(s32),
}
/// Label details for an LSP completion.
record completion-label-details {
detail: option<string>,
description: option<string>,
}
/// Defines how to interpret the insert text in a completion item.
variant insert-text-format {
plain-text,
snippet,
other(s32),
}
/// An LSP symbol.
record symbol {
kind: symbol-kind,
name: string,
}
/// The kind of an LSP symbol.
variant symbol-kind {
file,
module,
namespace,
%package,
class,
method,
property,
field,
%constructor,
%enum,
%interface,
function,
variable,
constant,
%string,
number,
boolean,
array,
object,
key,
null,
enum-member,
struct,
event,
operator,
type-parameter,
other(s32),
}
}

View File

@@ -0,0 +1,13 @@
interface nodejs {
/// Returns the path to the Node binary used by Zed.
node-binary-path: func() -> result<string, string>;
/// Returns the latest version of the given NPM package.
npm-package-latest-version: func(package-name: string) -> result<string, string>;
/// Returns the installed version of the given NPM package, if it exists.
npm-package-installed-version: func(package-name: string) -> result<option<string>, string>;
/// Installs the specified NPM package.
npm-install-package: func(package-name: string, version: string) -> result<_, string>;
}

View File

@@ -0,0 +1,24 @@
interface platform {
/// An operating system.
enum os {
/// macOS.
mac,
/// Linux.
linux,
/// Windows.
windows,
}
/// A platform architecture.
enum architecture {
/// AArch64 (e.g., Apple Silicon).
aarch64,
/// x86.
x86,
/// x86-64.
x8664,
}
/// Gets the current operating system and architecture.
current-platform: func() -> tuple<os, architecture>;
}

View File

@@ -0,0 +1,29 @@
interface process {
use common.{env-vars};
/// A command.
record command {
/// The command to execute.
command: string,
/// The arguments to pass to the command.
args: list<string>,
/// The environment variables to set for the command.
env: env-vars,
}
/// The output of a finished process.
record output {
/// The status (exit code) of the process.
///
/// On Unix, this will be `None` if the process was terminated by a signal.
status: option<s32>,
/// The data that the process wrote to stdout.
stdout: list<u8>,
/// The data that the process wrote to stderr.
stderr: list<u8>,
}
/// Executes the given command as a child process, waiting for it to finish
/// and collecting all of its output.
run-command: func(command: command) -> result<output, string>;
}

View File

@@ -0,0 +1,40 @@
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, num::NonZeroU32};
/// The settings for a particular language.
#[derive(Debug, Serialize, Deserialize)]
pub struct LanguageSettings {
/// How many columns a tab should occupy.
pub tab_size: NonZeroU32,
}
/// The settings for a particular language server.
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct LspSettings {
/// The settings for the language server binary.
pub binary: Option<CommandSettings>,
/// The initialization options to pass to the language server.
pub initialization_options: Option<serde_json::Value>,
/// The settings to pass to language server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a particular context server.
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct ContextServerSettings {
/// The settings for the context server binary.
pub command: Option<CommandSettings>,
/// The settings to pass to the context server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a command.
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct CommandSettings {
/// The path to the command.
pub path: Option<String>,
/// The arguments to pass to the command.
pub arguments: Option<Vec<String>>,
/// The environment variables.
pub env: Option<HashMap<String, String>>,
}

View File

@@ -0,0 +1,41 @@
interface slash-command {
use common.{range};
/// A slash command for use in the Assistant.
record slash-command {
/// The name of the slash command.
name: string,
/// The description of the slash command.
description: string,
/// The tooltip text to display for the run button.
tooltip-text: string,
/// Whether this slash command requires an argument.
requires-argument: bool,
}
/// The output of a slash command.
record slash-command-output {
/// The text produced by the slash command.
text: string,
/// The list of sections to show in the slash command placeholder.
sections: list<slash-command-output-section>,
}
/// A section in the slash command output.
record slash-command-output-section {
/// The range this section occupies.
range: range,
/// The label to display in the placeholder for this section.
label: string,
}
/// A completion for a slash command argument.
record slash-command-argument-completion {
/// The label to display for this completion.
label: string,
/// The new text that should be inserted into the command when this completion is accepted.
new-text: string,
/// Whether the command should be run when accepting this completion.
run-command: bool,
}
}

View File

@@ -0,0 +1,12 @@
interface common {
/// A (half-open) range (`[start, end)`).
record range {
/// The start of the range (inclusive).
start: u32,
/// The end of the range (exclusive).
end: u32,
}
/// A list of environment variables.
type env-vars = list<tuple<string, string>>;
}

View File

@@ -0,0 +1,11 @@
interface context-server {
/// Configuration for context server setup and installation.
record context-server-configuration {
/// Installation instructions in Markdown format.
installation-instructions: string,
/// JSON schema for settings validation.
settings-schema: string,
/// Default settings template.
default-settings: string,
}
}

View File

@@ -0,0 +1,131 @@
interface dap {
use common.{env-vars};
/// Resolves a specified TcpArgumentsTemplate into TcpArguments
resolve-tcp-template: func(template: tcp-arguments-template) -> result<tcp-arguments, string>;
record launch-request {
program: string,
cwd: option<string>,
args: list<string>,
envs: env-vars,
}
record attach-request {
process-id: option<u32>,
}
variant debug-request {
launch(launch-request),
attach(attach-request)
}
type ipv4-address = tuple<u8, u8, u8, u8>;
type ipv6-address = tuple<u16, u16, u16, u16, u16, u16, u16, u16>;
variant ip-address {
ipv4(ipv4-address),
ipv6(ipv6-address),
}
record tcp-arguments {
port: u16,
host: ip-address,
timeout: option<u64>,
}
record tcp-arguments-template {
port: option<u16>,
host: option<ip-address>,
timeout: option<u64>,
}
/// Debug Config is the "highest-level" configuration for a debug session.
/// It comes from a new process modal UI; thus, it is essentially debug-adapter-agnostic.
/// It is expected of the extension to translate this generic configuration into something that can be debugged by the adapter (debug scenario).
record debug-config {
/// Name of the debug task
label: string,
/// The debug adapter to use
adapter: string,
request: debug-request,
stop-on-entry: option<bool>,
}
record task-template {
/// Human readable name of the task to display in the UI.
label: string,
/// Executable command to spawn.
command: string,
args: list<string>,
env: env-vars,
cwd: option<string>,
}
/// A task template with substituted task variables.
type resolved-task = task-template;
/// A task template for building a debug target.
type build-task-template = task-template;
variant build-task-definition {
by-name(string),
template(build-task-definition-template-payload )
}
record build-task-definition-template-payload {
locator-name: option<string>,
template: build-task-template
}
/// Debug Scenario is the user-facing configuration type (used in debug.json). It is still concerned with what to debug and not necessarily how to do it (except for any
/// debug-adapter-specific configuration options).
record debug-scenario {
/// Unsubstituted label for the task.DebugAdapterBinary
label: string,
/// Name of the Debug Adapter this configuration is intended for.
adapter: string,
/// An optional build step to be ran prior to starting a debug session. Build steps are used by Zed's locators to locate the executable to debug.
build: option<build-task-definition>,
/// JSON-encoded configuration for a given debug adapter.
config: string,
/// TCP connection parameters (if they were specified by user)
tcp-connection: option<tcp-arguments-template>,
}
enum start-debugging-request-arguments-request {
launch,
attach,
}
record debug-task-definition {
/// Unsubstituted label for the task.DebugAdapterBinary
label: string,
/// Name of the Debug Adapter this configuration is intended for.
adapter: string,
/// JSON-encoded configuration for a given debug adapter.
config: string,
/// TCP connection parameters (if they were specified by user)
tcp-connection: option<tcp-arguments-template>,
}
record start-debugging-request-arguments {
/// JSON-encoded configuration for a given debug adapter. It is specific to each debug adapter.
/// `configuration` will have it's Zed variable references substituted prior to being passed to the debug adapter.
configuration: string,
request: start-debugging-request-arguments-request,
}
/// The lowest-level representation of a debug session, which specifies:
/// - How to start a debug adapter process
/// - How to start a debug session with it (using DAP protocol)
/// for a given debug scenario.
record debug-adapter-binary {
command: option<string>,
arguments: list<string>,
envs: env-vars,
cwd: option<string>,
/// Zed will use TCP transport if `connection` is specified.
connection: option<tcp-arguments>,
request-args: start-debugging-request-arguments
}
}

View File

@@ -0,0 +1,179 @@
package zed:extension;
world extension {
import context-server;
import dap;
import github;
import http-client;
import platform;
import process;
import nodejs;
use common.{env-vars, range};
use context-server.{context-server-configuration};
use dap.{attach-request, build-task-template, debug-config, debug-adapter-binary, debug-task-definition, debug-request, debug-scenario, launch-request, resolved-task, start-debugging-request-arguments-request};
use lsp.{completion, symbol};
use process.{command};
use slash-command.{slash-command, slash-command-argument-completion, slash-command-output};
/// Initializes the extension.
export init-extension: func();
/// The type of a downloaded file.
enum downloaded-file-type {
/// A gzipped file (`.gz`).
gzip,
/// A gzipped tar archive (`.tar.gz`).
gzip-tar,
/// A ZIP file (`.zip`).
zip,
/// An uncompressed file.
uncompressed,
}
/// The installation status for a language server.
variant language-server-installation-status {
/// The language server has no installation status.
none,
/// The language server is being downloaded.
downloading,
/// The language server is checking for updates.
checking-for-update,
/// The language server installation failed for specified reason.
failed(string),
}
record settings-location {
worktree-id: u64,
path: string,
}
import get-settings: func(path: option<settings-location>, category: string, key: option<string>) -> result<string, string>;
/// Downloads a file from the given URL and saves it to the given path within the extension's
/// working directory.
///
/// The file will be extracted according to the given file type.
import download-file: func(url: string, file-path: string, file-type: downloaded-file-type) -> result<_, string>;
/// Makes the file at the given path executable.
///
/// This is a no-op on Windows.
import make-file-executable: func(filepath: string) -> result<_, string>;
/// Updates the installation status for the given language server.
import set-language-server-installation-status: func(language-server-name: string, status: language-server-installation-status);
/// A Zed worktree.
resource worktree {
/// Returns the ID of the worktree.
id: func() -> u64;
/// Returns the root path of the worktree.
root-path: func() -> string;
/// Returns the textual contents of the specified file in the worktree.
read-text-file: func(path: string) -> result<string, string>;
/// Returns the path to the given binary name, if one is present on the `$PATH`.
which: func(binary-name: string) -> option<string>;
/// Returns the current shell environment.
shell-env: func() -> env-vars;
}
/// A Zed project.
resource project {
/// Returns the IDs of all of the worktrees in this project.
worktree-ids: func() -> list<u64>;
}
/// A key-value store.
resource key-value-store {
/// Inserts an entry under the specified key.
insert: func(key: string, value: string) -> result<_, string>;
}
/// Returns the command used to start up the language server.
export language-server-command: func(language-server-id: string, worktree: borrow<worktree>) -> result<command, string>;
/// Returns the initialization options to pass to the language server on startup.
///
/// The initialization options are represented as a JSON string.
export language-server-initialization-options: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the workspace configuration options to pass to the language server.
export language-server-workspace-configuration: func(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the JSON schema for the initialization options.
///
/// The schema is represented as a JSON string conforming to the JSON Schema specification.
export language-server-initialization-options-schema: func(language-server-id: string, worktree: borrow<worktree>) -> option<string>;
/// Returns the JSON schema for the workspace configuration.
///
/// The schema is represented as a JSON string conforming to the JSON Schema specification.
export language-server-workspace-configuration-schema: func(language-server-id: string, worktree: borrow<worktree>) -> option<string>;
/// Returns the initialization options to pass to the other language server.
export language-server-additional-initialization-options: func(language-server-id: string, target-language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// Returns the workspace configuration options to pass to the other language server.
export language-server-additional-workspace-configuration: func(language-server-id: string, target-language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
/// A label containing some code.
record code-label {
/// The source code to parse with Tree-sitter.
code: string,
/// The spans to display in the label.
spans: list<code-label-span>,
/// The range of the displayed label to include when filtering.
filter-range: range,
}
/// A span within a code label.
variant code-label-span {
/// A range into the parsed code.
code-range(range),
/// A span containing a code literal.
literal(code-label-span-literal),
}
/// A span containing a code literal.
record code-label-span-literal {
/// The literal text.
text: string,
/// The name of the highlight to use for this literal.
highlight-name: option<string>,
}
export labels-for-completions: func(language-server-id: string, completions: list<completion>) -> result<list<option<code-label>>, string>;
export labels-for-symbols: func(language-server-id: string, symbols: list<symbol>) -> result<list<option<code-label>>, string>;
/// Returns the completions that should be shown when completing the provided slash command with the given query.
export complete-slash-command-argument: func(command: slash-command, args: list<string>) -> result<list<slash-command-argument-completion>, string>;
/// Returns the output from running the provided slash command.
export run-slash-command: func(command: slash-command, args: list<string>, worktree: option<borrow<worktree>>) -> result<slash-command-output, string>;
/// Returns the command used to start up a context server.
export context-server-command: func(context-server-id: string, project: borrow<project>) -> result<command, string>;
/// Returns the configuration for a context server.
export context-server-configuration: func(context-server-id: string, project: borrow<project>) -> result<option<context-server-configuration>, string>;
/// Returns a list of packages as suggestions to be included in the `/docs`
/// search results.
///
/// This can be used to provide completions for known packages (e.g., from the
/// local project or a registry) before a package has been indexed.
export suggest-docs-packages: func(provider-name: string) -> result<list<string>, string>;
/// Indexes the docs for the specified package.
export index-docs: func(provider-name: string, package-name: string, database: borrow<key-value-store>) -> result<_, string>;
/// Returns a configured debug adapter binary for a given debug task.
export get-dap-binary: func(adapter-name: string, config: debug-task-definition, user-installed-path: option<string>, worktree: borrow<worktree>) -> result<debug-adapter-binary, string>;
/// Returns the kind of a debug scenario (launch or attach).
export dap-request-kind: func(adapter-name: string, config: string) -> result<start-debugging-request-arguments-request, string>;
export dap-config-to-scenario: func(config: debug-config) -> result<debug-scenario, string>;
export dap-locator-create-scenario: func(locator-name: string, build-config-template: build-task-template, resolved-label: string, debug-adapter-name: string) -> option<debug-scenario>;
export run-dap-locator: func(locator-name: string, config: resolved-task) -> result<debug-request, string>;
}

View File

@@ -0,0 +1,37 @@
interface github {
/// A GitHub release.
record github-release {
/// The version of the release.
version: string,
/// The list of assets attached to the release.
assets: list<github-release-asset>,
}
/// An asset from a GitHub release.
record github-release-asset {
/// The name of the asset.
name: string,
/// The download URL for the asset.
download-url: string,
/// The SHA-256 of the release asset if provided by the GitHub API.
digest: option<string>,
}
/// The options used to filter down GitHub releases.
record github-release-options {
/// Whether releases without assets should be included.
require-assets: bool,
/// Whether pre-releases should be included.
pre-release: bool,
}
/// Returns the latest release for the given GitHub repository.
///
/// Takes repo as a string in the form "<owner-name>/<repo-name>", for example: "zed-industries/zed".
latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
/// Returns the GitHub release with the specified tag name for the given GitHub repository.
///
/// Returns an error if a release with the given tag name does not exist.
github-release-by-tag-name: func(repo: string, tag: string) -> result<github-release, string>;
}

View File

@@ -0,0 +1,67 @@
interface http-client {
/// An HTTP request.
record http-request {
/// The HTTP method for the request.
method: http-method,
/// The URL to which the request should be made.
url: string,
/// The headers for the request.
headers: list<tuple<string, string>>,
/// The request body.
body: option<list<u8>>,
/// The policy to use for redirects.
redirect-policy: redirect-policy,
}
/// HTTP methods.
enum http-method {
/// `GET`
get,
/// `HEAD`
head,
/// `POST`
post,
/// `PUT`
put,
/// `DELETE`
delete,
/// `OPTIONS`
options,
/// `PATCH`
patch,
}
/// The policy for dealing with redirects received from the server.
variant redirect-policy {
/// Redirects from the server will not be followed.
///
/// This is the default behavior.
no-follow,
/// Redirects from the server will be followed up to the specified limit.
follow-limit(u32),
/// All redirects from the server will be followed.
follow-all,
}
/// An HTTP response.
record http-response {
/// The response headers.
headers: list<tuple<string, string>>,
/// The response body.
body: list<u8>,
}
/// Performs an HTTP request and returns the response.
fetch: func(req: http-request) -> result<http-response, string>;
/// An HTTP response stream.
resource http-response-stream {
/// Retrieves the next chunk of data from the response stream.
///
/// Returns `Ok(None)` if the stream has ended.
next-chunk: func() -> result<option<list<u8>>, string>;
}
/// Performs an HTTP request and returns a response stream.
fetch-stream: func(req: http-request) -> result<http-response-stream, string>;
}

View File

@@ -0,0 +1,91 @@
interface lsp {
/// An LSP completion.
record completion {
label: string,
label-details: option<completion-label-details>,
detail: option<string>,
kind: option<completion-kind>,
insert-text-format: option<insert-text-format>,
}
/// The kind of an LSP completion.
variant completion-kind {
text,
method,
function,
%constructor,
field,
variable,
class,
%interface,
module,
property,
unit,
value,
%enum,
keyword,
snippet,
color,
file,
reference,
folder,
enum-member,
constant,
struct,
event,
operator,
type-parameter,
other(s32),
}
/// Label details for an LSP completion.
record completion-label-details {
detail: option<string>,
description: option<string>,
}
/// Defines how to interpret the insert text in a completion item.
variant insert-text-format {
plain-text,
snippet,
other(s32),
}
/// An LSP symbol.
record symbol {
kind: symbol-kind,
name: string,
container-name: option<string>,
}
/// The kind of an LSP symbol.
variant symbol-kind {
file,
module,
namespace,
%package,
class,
method,
property,
field,
%constructor,
%enum,
%interface,
function,
variable,
constant,
%string,
number,
boolean,
array,
object,
key,
null,
enum-member,
struct,
event,
operator,
type-parameter,
other(s32),
}
}

View File

@@ -0,0 +1,13 @@
interface nodejs {
/// Returns the path to the Node binary used by Zed.
node-binary-path: func() -> result<string, string>;
/// Returns the latest version of the given NPM package.
npm-package-latest-version: func(package-name: string) -> result<string, string>;
/// Returns the installed version of the given NPM package, if it exists.
npm-package-installed-version: func(package-name: string) -> result<option<string>, string>;
/// Installs the specified NPM package.
npm-install-package: func(package-name: string, version: string) -> result<_, string>;
}

View File

@@ -0,0 +1,24 @@
interface platform {
/// An operating system.
enum os {
/// macOS.
mac,
/// Linux.
linux,
/// Windows.
windows,
}
/// A platform architecture.
enum architecture {
/// AArch64 (e.g., Apple Silicon).
aarch64,
/// x86.
x86,
/// x86-64.
x8664,
}
/// Gets the current operating system and architecture.
current-platform: func() -> tuple<os, architecture>;
}

View File

@@ -0,0 +1,29 @@
interface process {
use common.{env-vars};
/// A command.
record command {
/// The command to execute.
command: string,
/// The arguments to pass to the command.
args: list<string>,
/// The environment variables to set for the command.
env: env-vars,
}
/// The output of a finished process.
record output {
/// The status (exit code) of the process.
///
/// On Unix, this will be `None` if the process was terminated by a signal.
status: option<s32>,
/// The data that the process wrote to stdout.
stdout: list<u8>,
/// The data that the process wrote to stderr.
stderr: list<u8>,
}
/// Executes the given command as a child process, waiting for it to finish
/// and collecting all of its output.
run-command: func(command: command) -> result<output, string>;
}

View File

@@ -0,0 +1,42 @@
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, num::NonZeroU32};
/// The settings for a particular language.
#[derive(Debug, Serialize, Deserialize)]
pub struct LanguageSettings {
/// How many columns a tab should occupy.
pub tab_size: NonZeroU32,
/// The preferred line length (column at which to wrap).
pub preferred_line_length: u32,
}
/// The settings for a particular language server.
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct LspSettings {
/// The settings for the language server binary.
pub binary: Option<CommandSettings>,
/// The initialization options to pass to the language server.
pub initialization_options: Option<serde_json::Value>,
/// The settings to pass to language server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a particular context server.
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct ContextServerSettings {
/// The settings for the context server binary.
pub command: Option<CommandSettings>,
/// The settings to pass to the context server.
pub settings: Option<serde_json::Value>,
}
/// The settings for a command.
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct CommandSettings {
/// The path to the command.
pub path: Option<String>,
/// The arguments to pass to the command.
pub arguments: Option<Vec<String>>,
/// The environment variables.
pub env: Option<HashMap<String, String>>,
}

View File

@@ -0,0 +1,41 @@
interface slash-command {
use common.{range};
/// A slash command for use in the Assistant.
record slash-command {
/// The name of the slash command.
name: string,
/// The description of the slash command.
description: string,
/// The tooltip text to display for the run button.
tooltip-text: string,
/// Whether this slash command requires an argument.
requires-argument: bool,
}
/// The output of a slash command.
record slash-command-output {
/// The text produced by the slash command.
text: string,
/// The list of sections to show in the slash command placeholder.
sections: list<slash-command-output-section>,
}
/// A section in the slash command output.
record slash-command-output-section {
/// The range this section occupies.
range: range,
/// The label to display in the placeholder for this section.
label: string,
}
/// A completion for a slash command argument.
record slash-command-argument-completion {
/// The label to display for this completion.
label: string,
/// The new text that should be inserted into the command when this completion is accepted.
new-text: string,
/// Whether the command should be run when accepting this completion.
run-command: bool,
}
}