ocaml: Extract to zed-extensions/ocaml repository (#20825)

Marshall Bowers created

This PR extracts the OCaml extensions to the
[zed-extensions/ocaml](https://github.com/zed-extensions/ocaml)
repository.

Release Notes:

- N/A

Change summary

Cargo.lock                                                |   7 
Cargo.toml                                                |   1 
docs/src/languages/ocaml.md                               |   2 
extensions/ocaml/Cargo.toml                               |  16 
extensions/ocaml/LICENSE-APACHE                           |   1 
extensions/ocaml/extension.toml                           |  25 -
extensions/ocaml/languages/dune/config.toml               |   8 
extensions/ocaml/languages/dune/highlights.scm            |   5 
extensions/ocaml/languages/dune/injections.scm            |   2 
extensions/ocaml/languages/ocaml-interface/brackets.scm   |   2 
extensions/ocaml/languages/ocaml-interface/config.toml    |  12 
extensions/ocaml/languages/ocaml-interface/highlights.scm |   1 
extensions/ocaml/languages/ocaml-interface/indents.scm    |  21 
extensions/ocaml/languages/ocaml-interface/outline.scm    |  48 -
extensions/ocaml/languages/ocaml/brackets.scm             |   5 
extensions/ocaml/languages/ocaml/config.toml              |  14 
extensions/ocaml/languages/ocaml/highlights.scm           | 158 ------
extensions/ocaml/languages/ocaml/indents.scm              |  45 -
extensions/ocaml/languages/ocaml/outline.scm              |  59 --
extensions/ocaml/src/ocaml.rs                             | 219 ---------
20 files changed, 1 insertion(+), 650 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -15346,13 +15346,6 @@ dependencies = [
  "zed_extension_api 0.1.0",
 ]
 
-[[package]]
-name = "zed_ocaml"
-version = "0.1.1"
-dependencies = [
- "zed_extension_api 0.1.0",
-]
-
 [[package]]
 name = "zed_php"
 version = "0.2.2"

Cargo.toml 🔗

@@ -148,7 +148,6 @@ members = [
     "extensions/haskell",
     "extensions/html",
     "extensions/lua",
-    "extensions/ocaml",
     "extensions/php",
     "extensions/perplexity",
     "extensions/prisma",

docs/src/languages/ocaml.md 🔗

@@ -1,6 +1,6 @@
 # OCaml
 
-OCaml support is available through the [OCaml extension](https://github.com/zed-industries/zed/tree/main/extensions/ocaml).
+OCaml support is available through the [OCaml extension](https://github.com/zed-extensions/ocaml).
 
 - Tree Sitter: [tree-sitter/tree-sitter-ocaml](https://github.com/tree-sitter/tree-sitter-ocaml)
 - Language Server: [ocaml/ocaml-lsp](https://github.com/ocaml/ocaml-lsp)

extensions/ocaml/Cargo.toml 🔗

@@ -1,16 +0,0 @@
-[package]
-name = "zed_ocaml"
-version = "0.1.1"
-edition = "2021"
-publish = false
-license = "Apache-2.0"
-
-[lints]
-workspace = true
-
-[lib]
-path = "src/ocaml.rs"
-crate-type = ["cdylib"]
-
-[dependencies]
-zed_extension_api = "0.1.0"

extensions/ocaml/extension.toml 🔗

@@ -1,25 +0,0 @@
-id = "ocaml"
-name = "OCaml"
-description = "OCaml support."
-version = "0.1.1"
-schema_version = 1
-authors = ["Rashid Almheiri <69181766+huwaireb@users.noreply.github.com>"]
-repository = "https://github.com/zed-industries/zed"
-
-[language_servers.ocamllsp]
-name = "ocamllsp"
-languages = ["OCaml", "OCaml Interface"]
-
-[grammars.ocaml]
-repository = "https://github.com/tree-sitter/tree-sitter-ocaml"
-commit = "0b12614ded3ec7ed7ab7933a9ba4f695ba4c342e"
-path = "grammars/ocaml"
-
-[grammars.ocaml_interface]
-repository = "https://github.com/tree-sitter/tree-sitter-ocaml"
-commit = "0b12614ded3ec7ed7ab7933a9ba4f695ba4c342e"
-path = "grammars/interface"
-
-[grammars.dune]
-repository = "https://github.com/WHForks/tree-sitter-dune"
-commit = "b3f7882e1b9a1d8811011bf6f0de1c74c9c93949"

extensions/ocaml/languages/dune/config.toml 🔗

@@ -1,8 +0,0 @@
-name = "Dune"
-grammar = "dune"
-path_suffixes = ["dune", "dune-project"]
-brackets = [
-    { start = "(", end = ")", close = true, newline = true },
-    { start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] }
-]
-tab_size = 2

extensions/ocaml/languages/ocaml-interface/config.toml 🔗

@@ -1,12 +0,0 @@
-name = "OCaml Interface"
-code_fence_block_name = "ocaml"
-grammar = "ocaml_interface"
-path_suffixes = ["mli"]
-block_comment = ["(* ", " *)"]
-autoclose_before = ";,=)}"
-brackets = [
-  { start = "{", end = "}", close = true, newline = true },
-  { start = "[", end = "]", close = true, newline = true },
-  { start = "(", end = ")", close = true, newline = true }
-]
-tab_size = 2

extensions/ocaml/languages/ocaml-interface/indents.scm 🔗

@@ -1,21 +0,0 @@
-[
-  (type_binding)
-
-  (value_specification)
-  (method_specification)
-
-  (external)
-  (field_declaration)
-] @indent
-
-(_ "<" ">" @end) @indent
-(_ "{" "}" @end) @indent
-(_ "(" ")" @end) @indent
-
-(_ "object" @start "end" @end) @indent
-
-(signature
-  "sig" @start
-  "end" @end) @indent
-
-";;" @outdent

extensions/ocaml/languages/ocaml-interface/outline.scm 🔗

@@ -1,48 +0,0 @@
-(module_type_definition
-  "module" @context
-  "type" @context
-  name: (_) @name) @item
-
-(module_definition
-    "module" @context
-    (module_binding name: (_) @name)) @item
-
-(type_definition
-    "type" @context
-    (type_binding name: (_) @name)) @item
-
-(class_definition
-    "class" @context
-    (class_binding
-      "virtual"? @context
-      name: (_) @name)) @item
-
-(class_type_definition
-  "class" @context
-  "type" @context
-  (class_type_binding
-    "virtual"? @context
-    name: (_) @name)) @item
-
-(instance_variable_definition
-  "val" @context
-  "method"? @context
-  name: (_) @name) @item
-
-(method_specification
-  "method" @context
-  "virtual"? @context
-   (method_name) @name) @item
-
-(value_specification
-    "val" @context
-    (value_name) @name) @item
-
-(external
-  "external" @context
-  (value_name) @name) @item
-
-(exception_definition
-    "exception" @context
-    (constructor_declaration
-      (constructor_name) @name)) @item

extensions/ocaml/languages/ocaml/config.toml 🔗

@@ -1,14 +0,0 @@
-name = "OCaml"
-grammar = "ocaml"
-path_suffixes = ["ml"]
-block_comment = ["(* ", " *)"]
-autoclose_before = ";,=)}]"
-brackets = [
-  { start = "{", end = "}", close = true, newline = true },
-  { start = "{|", end = "|", close = true, newline = true, not_in = ["string"] },
-  { start = "[", end = "]", close = true, newline = true },
-  { start = "[|", end = "|", close = true, newline = true, not_in = ["string"] },
-  { start = "(", end = ")", close = true, newline = true },
-  { start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] }
-]
-tab_size = 2

extensions/ocaml/languages/ocaml/highlights.scm 🔗

@@ -1,158 +0,0 @@
-; Modules
-;--------
-
-[(module_name) (module_type_name)] @title
-
-; Types
-;------
-
-[(class_name) (class_type_name) (type_constructor)] @type
-
-(tag) @variant ;; Polymorphic Variants
-(constructor_name) @constructor ;; Exceptions, variants and the like
-
-; Functions
-;----------
-
-(let_binding
-  pattern: (value_name) @function
-  (parameter))
-
-(let_binding
-  pattern: (value_name) @function
-  body: [(fun_expression) (function_expression)])
-
-(value_specification (value_name) @function)
-
-(external (value_name) @function)
-
-(method_name) @function
-
-(infix_expression
-  left: (value_path (value_name) @function)
-  operator: (concat_operator) @operator
-  (#eq? @operator "@@"))
-
-(infix_expression
-  operator: (rel_operator) @operator
-  right: (value_path (value_name) @function)
-  (#eq? @operator "|>"))
-
-(application_expression
-  function: (value_path (value_name) @function))
-
-; Variables
-;----------
-
-(value_pattern) @variable
-
-(type_variable) @variable.special
-
-; Properties
-;-----------
-
-[(field_name) (instance_variable_name)] @property
-
-; Labels
-;-------
-
-[(label_name) (parameter)] @label
-
-(parameter
-    pattern: (value_pattern) @label)
-; despite the above rule, we should still label value_pattern as a variable
-; when a label name is present
-(parameter
-    (label_name)
-    pattern: (value_pattern) @variable)
-
-; Constants
-;----------
-
-(boolean) @boolean
-
-[(number) (signed_number)] @number
-
-[(string) (character)] @string
-
-(quoted_string "{" @string "}" @string) @string
-(quoted_string_content) @string
-
-
-(escape_sequence) @string.escape
-
-[
-  (conversion_specification)
-  (pretty_printing_indication)
-] @punctuation.special
-
-; Operators
-;----------
-
-(match_expression (match_operator) @keyword)
-
-(value_definition [(let_operator) (let_and_operator)] @keyword)
-
-[
-  (prefix_operator)
-  (sign_operator)
-  (pow_operator)
-  (mult_operator)
-  (add_operator)
-  (concat_operator)
-  (rel_operator)
-  (and_operator)
-  (or_operator)
-  (assign_operator)
-  (hash_operator)
-  (indexing_operator)
-  (let_operator)
-  (let_and_operator)
-  (match_operator)
-] @operator
-
-["*" "#" "::" "<-"] @operator
-
-; Keywords
-;---------
-
-[
-  "and" "as" "assert" "begin" "class" "constraint" "do" "done" "downto" "else"
-  "end" "exception" "external" "for" "fun" "function" "functor" "if" "in"
-  "include" "inherit" "initializer" "lazy" "let" "match" "method" "module"
-  "mutable" "new" "nonrec" "object" "of" "open" "private" "rec" "sig" "struct"
-  "then" "to" "try" "type" "val" "virtual" "when" "while" "with"
-] @keyword
-
-; Punctuation
-;------------
-
-["(" ")" "[" "]" "{" "}" "[|" "|]" "[<" "[>" "[@@" "[@" "[%"] @punctuation.bracket
-
-(object_type ["<" ">"] @punctuation.bracket)
-
-[
-  "," "." ";" ":" "=" "|" "~" "?" "+" "-" "!" ">" "&"
-  "->" ";;" ":>" "+=" ":=" ".."
-] @punctuation.delimiter
-
-; Attributes
-;-----------
-
-[
-  (attribute)
-  (item_attribute)
-  (floating_attribute)
-  (extension)
-  (item_extension)
-  (quoted_extension)
-  (quoted_item_extension)
-
-] @attribute
-
-(attribute_id) @tag
-
-; Comments
-;---------
-
-[(comment) (line_number_directive) (directive) (shebang)] @comment

extensions/ocaml/languages/ocaml/indents.scm 🔗

@@ -1,45 +0,0 @@
-[
-  (let_binding)
-  (type_binding)
-
-  (method_definition)
-
-  (external)
-  (value_specification)
-  (method_specification)
-
-  (match_case)
-
-  (function_expression)
-
-  (field_declaration)
-  (field_expression)
-
-  (application_expression)
-] @indent
-
-(_ "[" "]" @end) @indent
-(_ "[|" "|]" @end) @indent
-(_ "<" ">" @end) @indent
-(_ "{" "}" @end) @indent
-(_ "(" ")" @end) @indent
-
-(_ "object" @start "end" @end) @indent
-
-(structure
-  "struct" @start
-  "end" @end) @indent
-
-(signature
-  "sig" @start
-  "end" @end) @indent
-
-(parenthesized_expression
-  "begin" @start
-  "end") @indent
-
-(do_clause
-  "do" @start
-  "done" @end) @indent
-
-";;" @outdent

extensions/ocaml/languages/ocaml/outline.scm 🔗

@@ -1,59 +0,0 @@
-(_structure_item/value_definition
-    "let" @context
-    (let_binding
-      pattern: (_) @name)) @item
-
-(_structure_item/exception_definition
-  "exception" @context
-  (constructor_declaration
-    (constructor_name) @name)) @item
-
-(_structure_item/module_definition
-  "module" @context
-  (module_binding
-    name: (module_name) @name)) @item
-
-(module_type_definition
-  "module" @context
-  "type" @context
-  name: (_) @name) @item
-
-(type_definition
-  "type" @context
-  (type_binding name: (_) @name)) @item
-
-(value_specification
-  "val" @context
-  (value_name) @name) @item
-
-(class_definition
-  "class" @context
-  (class_binding
-    "virtual"? @context
-    name: (_) @name)) @item
-
-(class_type_definition
-  "class" @context
-  "type" @context
-  (class_type_binding
-    "virtual"? @context
-    name: (_) @name)) @item
-
-(instance_variable_definition
-  "val" @context
-  "method"? @context
-  name: (_) @name) @item
-
-(method_specification
-  "method" @context
-  "virtual"? @context
-   (method_name) @name) @item
-
-(method_definition
-  "method" @context
-  "virtual"? @context
-  name: (_) @name) @item
-
-(external
-  "external" @context
-  (value_name) @name) @item

extensions/ocaml/src/ocaml.rs 🔗

@@ -1,219 +0,0 @@
-use std::ops::Range;
-use zed::lsp::{Completion, CompletionKind, Symbol, SymbolKind};
-use zed::{CodeLabel, CodeLabelSpan};
-use zed_extension_api::{self as zed, Result};
-
-const OPERATOR_CHAR: [char; 17] = [
-    '~', '!', '?', '%', '<', ':', '.', '$', '&', '*', '+', '-', '/', '=', '>', '@', '^',
-];
-
-struct OcamlExtension;
-
-impl zed::Extension for OcamlExtension {
-    fn new() -> Self {
-        Self
-    }
-
-    fn language_server_command(
-        &mut self,
-        _language_server_id: &zed::LanguageServerId,
-        worktree: &zed::Worktree,
-    ) -> Result<zed::Command> {
-        let path = worktree.which("ocamllsp").ok_or_else(|| {
-            "ocamllsp (ocaml-language-server) must be installed manually.".to_string()
-        })?;
-
-        Ok(zed::Command {
-            command: path,
-            args: Vec::new(),
-            env: worktree.shell_env(),
-        })
-    }
-
-    fn label_for_completion(
-        &self,
-        _language_server_id: &zed::LanguageServerId,
-        completion: Completion,
-    ) -> Option<CodeLabel> {
-        let name = &completion.label;
-        let detail = completion.detail.as_ref().map(|s| s.replace('\n', " "));
-
-        match completion.kind.zip(detail) {
-            Some((CompletionKind::Constructor | CompletionKind::EnumMember, detail)) => {
-                let (argument, return_t) = detail
-                    .split_once("->")
-                    .map_or((None, detail.as_str()), |(arg, typ)| {
-                        (Some(arg.trim()), typ.trim())
-                    });
-
-                let type_decl = "type t = ";
-                let type_of = argument.map(|_| " of ").unwrap_or_default();
-                let argument = argument.unwrap_or_default();
-                let terminator = "\n";
-                let let_decl = "let _ ";
-                let let_colon = ": ";
-                let let_suffix = " = ()";
-                let code = format!(
-                    "{type_decl}{name}{type_of}{argument}{terminator}{let_decl}{let_colon}{return_t}{let_suffix}"
-                );
-
-                let name_start = type_decl.len();
-                let argument_end = name_start + name.len() + type_of.len() + argument.len();
-                let colon_start = argument_end + terminator.len() + let_decl.len();
-                let return_type_end = code.len() - let_suffix.len();
-                Some(CodeLabel {
-                    code,
-                    spans: vec![
-                        CodeLabelSpan::code_range(name_start..argument_end),
-                        CodeLabelSpan::code_range(colon_start..return_type_end),
-                    ],
-                    filter_range: (0..name.len()).into(),
-                })
-            }
-
-            Some((CompletionKind::Field, detail)) => {
-                let filter_range_start = if name.starts_with(['~', '?']) { 1 } else { 0 };
-
-                let record_prefix = "type t = { ";
-                let record_suffix = "; }";
-                let code = format!("{record_prefix}{name} : {detail}{record_suffix}");
-
-                Some(CodeLabel {
-                    spans: vec![CodeLabelSpan::code_range(
-                        record_prefix.len()..code.len() - record_suffix.len(),
-                    )],
-                    code,
-                    filter_range: (filter_range_start..name.len()).into(),
-                })
-            }
-
-            Some((CompletionKind::Value, detail)) => {
-                let let_prefix = "let ";
-                let suffix = " = ()";
-                let (l_paren, r_paren) = if name.contains(OPERATOR_CHAR) {
-                    ("( ", " )")
-                } else {
-                    ("", "")
-                };
-                let code = format!("{let_prefix}{l_paren}{name}{r_paren} : {detail}{suffix}");
-
-                let name_start = let_prefix.len() + l_paren.len();
-                let name_end = name_start + name.len();
-                let type_annotation_start = name_end + r_paren.len();
-                let type_annotation_end = code.len() - suffix.len();
-
-                Some(CodeLabel {
-                    spans: vec![
-                        CodeLabelSpan::code_range(name_start..name_end),
-                        CodeLabelSpan::code_range(type_annotation_start..type_annotation_end),
-                    ],
-                    filter_range: (0..name.len()).into(),
-                    code,
-                })
-            }
-
-            Some((CompletionKind::Method, detail)) => {
-                let method_decl = "class c : object method ";
-                let end = " end";
-                let code = format!("{method_decl}{name} : {detail}{end}");
-
-                Some(CodeLabel {
-                    spans: vec![CodeLabelSpan::code_range(
-                        method_decl.len()..code.len() - end.len(),
-                    )],
-                    code,
-                    filter_range: (0..name.len()).into(),
-                })
-            }
-
-            Some((kind, _)) => {
-                let highlight_name = match kind {
-                    CompletionKind::Module | CompletionKind::Interface => "title",
-                    CompletionKind::Keyword => "keyword",
-                    CompletionKind::TypeParameter => "type",
-                    _ => return None,
-                };
-
-                Some(CodeLabel {
-                    spans: vec![(CodeLabelSpan::literal(name, Some(highlight_name.to_string())))],
-                    filter_range: (0..name.len()).into(),
-                    code: String::new(),
-                })
-            }
-            _ => None,
-        }
-    }
-
-    fn label_for_symbol(
-        &self,
-        _language_server_id: &zed::LanguageServerId,
-        symbol: Symbol,
-    ) -> Option<CodeLabel> {
-        let name = &symbol.name;
-
-        let (code, filter_range, display_range) = match symbol.kind {
-            SymbolKind::Property => {
-                let code = format!("type t = {{ {}: (); }}", name);
-                let filter_range: Range<usize> = 0..name.len();
-                let display_range = 11..11 + name.len();
-                (code, filter_range, display_range)
-            }
-            SymbolKind::Function
-                if name.contains(OPERATOR_CHAR)
-                    || (name.starts_with("let") && name.contains(OPERATOR_CHAR)) =>
-            {
-                let code = format!("let ( {name} ) () = ()");
-
-                let filter_range = 6..6 + name.len();
-                let display_range = 0..filter_range.end + 1;
-                (code, filter_range, display_range)
-            }
-            SymbolKind::Function => {
-                let code = format!("let {name} () = ()");
-
-                let filter_range = 4..4 + name.len();
-                let display_range = 0..filter_range.end;
-                (code, filter_range, display_range)
-            }
-            SymbolKind::Constructor => {
-                let code = format!("type t = {name}");
-                let filter_range = 0..name.len();
-                let display_range = 9..9 + name.len();
-                (code, filter_range, display_range)
-            }
-            SymbolKind::Module => {
-                let code = format!("module {name} = struct end");
-                let filter_range = 7..7 + name.len();
-                let display_range = 0..filter_range.end;
-                (code, filter_range, display_range)
-            }
-            SymbolKind::Class => {
-                let code = format!("class {name} = object end");
-                let filter_range = 6..6 + name.len();
-                let display_range = 0..filter_range.end;
-                (code, filter_range, display_range)
-            }
-            SymbolKind::Method => {
-                let code = format!("class c = object method {name} = () end");
-                let filter_range = 0..name.len();
-                let display_range = 17..24 + name.len();
-                (code, filter_range, display_range)
-            }
-            SymbolKind::String => {
-                let code = format!("type {name} = T");
-                let filter_range = 5..5 + name.len();
-                let display_range = 0..filter_range.end;
-                (code, filter_range, display_range)
-            }
-            _ => return None,
-        };
-
-        Some(CodeLabel {
-            code,
-            spans: vec![CodeLabelSpan::code_range(display_range)],
-            filter_range: filter_range.into(),
-        })
-    }
-}
-
-zed::register_extension!(OcamlExtension);