diff options
| author | Randy Taylor | 2022-12-11 18:41:16 -0500 |
|---|---|---|
| committer | Yuan Fu | 2022-12-15 17:20:50 -0800 |
| commit | fee2efe1b035d601ac53a32801227402e9be8bca (patch) | |
| tree | da0956063942da9764fea942547d18e100af5cfd | |
| parent | e8f7ab67ad18063155f6a7ba14a29e3679dc1e76 (diff) | |
| download | emacs-fee2efe1b035d601ac53a32801227402e9be8bca.tar.gz emacs-fee2efe1b035d601ac53a32801227402e9be8bca.zip | |
Add go-ts-mode and go-mod-ts-mode (Bug#60025)
* admin/notes/tree-sitter/build-module/batch.sh:
* admin/notes/tree-sitter/build-module/build.sh: Add go-mod support.
* etc/NEWS: Mention them.
* lisp/progmodes/eglot.el (eglot-server-programs): Add them.
* lisp/progmodes/go-ts-mode.el: New major modes with
tree-sitter support.
| -rwxr-xr-x | admin/notes/tree-sitter/build-module/batch.sh | 1 | ||||
| -rwxr-xr-x | admin/notes/tree-sitter/build-module/build.sh | 5 | ||||
| -rw-r--r-- | etc/NEWS | 8 | ||||
| -rw-r--r-- | lisp/progmodes/eglot.el | 3 | ||||
| -rw-r--r-- | lisp/progmodes/go-ts-mode.el | 354 |
5 files changed, 370 insertions, 1 deletions
diff --git a/admin/notes/tree-sitter/build-module/batch.sh b/admin/notes/tree-sitter/build-module/batch.sh index e7ef45cf57d..c50b9df37ed 100755 --- a/admin/notes/tree-sitter/build-module/batch.sh +++ b/admin/notes/tree-sitter/build-module/batch.sh | |||
| @@ -9,6 +9,7 @@ languages=( | |||
| 9 | 'c-sharp' | 9 | 'c-sharp' |
| 10 | 'dockerfile' | 10 | 'dockerfile' |
| 11 | 'go' | 11 | 'go' |
| 12 | 'go-mod' | ||
| 12 | 'html' | 13 | 'html' |
| 13 | 'javascript' | 14 | 'javascript' |
| 14 | 'json' | 15 | 'json' |
diff --git a/admin/notes/tree-sitter/build-module/build.sh b/admin/notes/tree-sitter/build-module/build.sh index 4195ea58c3c..b6c83ea9b99 100755 --- a/admin/notes/tree-sitter/build-module/build.sh +++ b/admin/notes/tree-sitter/build-module/build.sh | |||
| @@ -26,6 +26,11 @@ case "${lang}" in | |||
| 26 | "cmake") | 26 | "cmake") |
| 27 | org="uyha" | 27 | org="uyha" |
| 28 | ;; | 28 | ;; |
| 29 | "go-mod") | ||
| 30 | # The parser is called "gomod". | ||
| 31 | lang="gomod" | ||
| 32 | org="camdencheek" | ||
| 33 | ;; | ||
| 29 | "typescript") | 34 | "typescript") |
| 30 | sourcedir="tree-sitter-typescript/typescript/src" | 35 | sourcedir="tree-sitter-typescript/typescript/src" |
| 31 | grammardir="tree-sitter-typescript/typescript" | 36 | grammardir="tree-sitter-typescript/typescript" |
| @@ -3081,6 +3081,14 @@ A major mode based on the tree-sitter library for editing files | |||
| 3081 | written in TOML, a format for writing configuration files. It is | 3081 | written in TOML, a format for writing configuration files. It is |
| 3082 | auto-enabled for files with the ".toml" extension. | 3082 | auto-enabled for files with the ".toml" extension. |
| 3083 | 3083 | ||
| 3084 | *** New major mode 'go-ts-mode'. | ||
| 3085 | A major mode based on the tree-sitter library for editing programs in | ||
| 3086 | the Go language. It is auto-enabled for files with the ".go" extension. | ||
| 3087 | |||
| 3088 | *** New major mode 'go-mod-ts-mode'. | ||
| 3089 | A major mode based on the tree-sitter library for editing "go.mod" | ||
| 3090 | files. It is auto-enabled for files which are named "go.mod". | ||
| 3091 | |||
| 3084 | 3092 | ||
| 3085 | * Incompatible Lisp Changes in Emacs 29.1 | 3093 | * Incompatible Lisp Changes in Emacs 29.1 |
| 3086 | 3094 | ||
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 9c5a361df7b..02bb6bb665d 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el | |||
| @@ -211,7 +211,8 @@ chosen (interactively or automatically)." | |||
| 211 | (elm-mode . ("elm-language-server")) | 211 | (elm-mode . ("elm-language-server")) |
| 212 | (mint-mode . ("mint" "ls")) | 212 | (mint-mode . ("mint" "ls")) |
| 213 | (kotlin-mode . ("kotlin-language-server")) | 213 | (kotlin-mode . ("kotlin-language-server")) |
| 214 | ((go-mode go-dot-mod-mode go-dot-work-mode) . ("gopls")) | 214 | ((go-mode go-dot-mod-mode go-dot-work-mode go-ts-mode go-mod-ts-mode) |
| 215 | . ("gopls")) | ||
| 215 | ((R-mode ess-r-mode) . ("R" "--slave" "-e" | 216 | ((R-mode ess-r-mode) . ("R" "--slave" "-e" |
| 216 | "languageserver::run()")) | 217 | "languageserver::run()")) |
| 217 | ((java-mode java-ts-mode) . ("jdtls")) | 218 | ((java-mode java-ts-mode) . ("jdtls")) |
diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el new file mode 100644 index 00000000000..124d9b044a2 --- /dev/null +++ b/lisp/progmodes/go-ts-mode.el | |||
| @@ -0,0 +1,354 @@ | |||
| 1 | ;;; go-ts-mode.el --- tree-sitter support for Go -*- lexical-binding: t; -*- | ||
| 2 | |||
| 3 | ;; Copyright (C) 2022 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author : Randy Taylor <dev@rjt.dev> | ||
| 6 | ;; Maintainer : Randy Taylor <dev@rjt.dev> | ||
| 7 | ;; Created : December 2022 | ||
| 8 | ;; Keywords : go languages tree-sitter | ||
| 9 | |||
| 10 | ;; This file is part of GNU Emacs. | ||
| 11 | |||
| 12 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 13 | ;; it under the terms of the GNU General Public License as published by | ||
| 14 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 15 | ;; (at your option) any later version. | ||
| 16 | |||
| 17 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | ;; GNU General Public License for more details. | ||
| 21 | |||
| 22 | ;; You should have received a copy of the GNU General Public License | ||
| 23 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 24 | |||
| 25 | ;;; Commentary: | ||
| 26 | ;; | ||
| 27 | |||
| 28 | ;;; Code: | ||
| 29 | |||
| 30 | (require 'treesit) | ||
| 31 | (eval-when-compile (require 'rx)) | ||
| 32 | |||
| 33 | (declare-function treesit-parser-create "treesit.c") | ||
| 34 | (declare-function treesit-induce-sparse-tree "treesit.c") | ||
| 35 | (declare-function treesit-node-child "treesit.c") | ||
| 36 | (declare-function treesit-node-child-by-field-name "treesit.c") | ||
| 37 | (declare-function treesit-node-start "treesit.c") | ||
| 38 | (declare-function treesit-node-type "treesit.c") | ||
| 39 | |||
| 40 | (defcustom go-ts-mode-indent-offset 4 | ||
| 41 | "Number of spaces for each indentation step in `go-ts-mode'." | ||
| 42 | :version "29.1" | ||
| 43 | :type 'integer | ||
| 44 | :safe 'integerp | ||
| 45 | :group 'go) | ||
| 46 | |||
| 47 | (defvar go-ts-mode--syntax-table | ||
| 48 | (let ((table (make-syntax-table))) | ||
| 49 | (modify-syntax-entry ?+ "." table) | ||
| 50 | (modify-syntax-entry ?- "." table) | ||
| 51 | (modify-syntax-entry ?= "." table) | ||
| 52 | (modify-syntax-entry ?% "." table) | ||
| 53 | (modify-syntax-entry ?& "." table) | ||
| 54 | (modify-syntax-entry ?| "." table) | ||
| 55 | (modify-syntax-entry ?^ "." table) | ||
| 56 | (modify-syntax-entry ?! "." table) | ||
| 57 | (modify-syntax-entry ?< "." table) | ||
| 58 | (modify-syntax-entry ?> "." table) | ||
| 59 | (modify-syntax-entry ?\\ "\\" table) | ||
| 60 | (modify-syntax-entry ?/ ". 124b" table) | ||
| 61 | (modify-syntax-entry ?* ". 23" table) | ||
| 62 | (modify-syntax-entry ?\n "> b" table) | ||
| 63 | table) | ||
| 64 | "Syntax table for `go-ts-mode'.") | ||
| 65 | |||
| 66 | (defvar go-ts-mode--indent-rules | ||
| 67 | `((go | ||
| 68 | ((node-is ")") parent-bol 0) | ||
| 69 | ((node-is "]") parent-bol 0) | ||
| 70 | ((node-is "}") parent-bol 0) | ||
| 71 | ((node-is "labeled_statement") no-indent) | ||
| 72 | ((parent-is "argument_list") parent-bol go-ts-mode-indent-offset) | ||
| 73 | ((parent-is "block") parent-bol go-ts-mode-indent-offset) | ||
| 74 | ((parent-is "const_declaration") parent-bol go-ts-mode-indent-offset) | ||
| 75 | ((parent-is "default_case") parent-bol go-ts-mode-indent-offset) | ||
| 76 | ((parent-is "expression_case") parent-bol go-ts-mode-indent-offset) | ||
| 77 | ((parent-is "expression_switch_statement") parent-bol 0) | ||
| 78 | ((parent-is "field_declaration_list") parent-bol go-ts-mode-indent-offset) | ||
| 79 | ((parent-is "import_spec_list") parent-bol go-ts-mode-indent-offset) | ||
| 80 | ((parent-is "labeled_statement") parent-bol go-ts-mode-indent-offset) | ||
| 81 | ((parent-is "literal_value") parent-bol go-ts-mode-indent-offset) | ||
| 82 | ((parent-is "type_spec") parent-bol go-ts-mode-indent-offset) | ||
| 83 | ((parent-is "var_declaration") parent-bol go-ts-mode-indent-offset) | ||
| 84 | (no-node parent-bol 0))) | ||
| 85 | "Tree-sitter indent rules for `go-ts-mode'.") | ||
| 86 | |||
| 87 | (defvar go-ts-mode--keywords | ||
| 88 | '("break" "case" "chan" "const" "continue" "default" "defer" "else" | ||
| 89 | "fallthrough" "for" "func" "go" "goto" "if" "import" "interface" "map" | ||
| 90 | "package" "range" "return" "select" "struct" "switch" "type" "var") | ||
| 91 | "Go keywords for tree-sitter font-locking.") | ||
| 92 | |||
| 93 | (defvar go-ts-mode--operators | ||
| 94 | '("+" "&" "+=" "&=" "&&" "==" "!=" "-" "|" "-=" "|=" "||" "<" "<=" | ||
| 95 | "*" "^" "*=" "^=" "<-" ">" ">=" "/" "<<" "/=" "<<=" "++" "=" ":=" "%" | ||
| 96 | ">>" "%=" ">>=" "--" "!" "..." "&^" "&^=" "~") | ||
| 97 | "Go operators for tree-sitter font-locking.") | ||
| 98 | |||
| 99 | (defvar go-ts-mode--font-lock-settings | ||
| 100 | (treesit-font-lock-rules | ||
| 101 | :language 'go | ||
| 102 | :feature 'bracket | ||
| 103 | '((["(" ")" "[" "]" "{" "}"]) @font-lock-bracket-face) | ||
| 104 | |||
| 105 | :language 'go | ||
| 106 | :feature 'comment | ||
| 107 | '((comment) @font-lock-comment-face) | ||
| 108 | |||
| 109 | :language 'go | ||
| 110 | :feature 'constant | ||
| 111 | '([(false) (iota) (nil) (true)] @font-lock-constant-face | ||
| 112 | (const_declaration | ||
| 113 | (const_spec name: (identifier) @font-lock-constant-face))) | ||
| 114 | |||
| 115 | :language 'go | ||
| 116 | :feature 'delimiter | ||
| 117 | '((["," "." ";" ":"]) @font-lock-delimiter-face) | ||
| 118 | |||
| 119 | :language 'go | ||
| 120 | :feature 'function | ||
| 121 | '((call_expression | ||
| 122 | function: (identifier) @font-lock-function-name-face) | ||
| 123 | (call_expression | ||
| 124 | function: (selector_expression | ||
| 125 | field: (field_identifier) @font-lock-function-name-face)) | ||
| 126 | (function_declaration | ||
| 127 | name: (identifier) @font-lock-function-name-face) | ||
| 128 | (method_declaration | ||
| 129 | name: (field_identifier) @font-lock-function-name-face)) | ||
| 130 | |||
| 131 | :language 'go | ||
| 132 | :feature 'keyword | ||
| 133 | `([,@go-ts-mode--keywords] @font-lock-keyword-face) | ||
| 134 | |||
| 135 | :language 'go | ||
| 136 | :feature 'label | ||
| 137 | '((label_name) @font-lock-constant-face) | ||
| 138 | |||
| 139 | :language 'go | ||
| 140 | :feature 'number | ||
| 141 | '([(float_literal) | ||
| 142 | (imaginary_literal) | ||
| 143 | (int_literal)] @font-lock-number-face) | ||
| 144 | |||
| 145 | :language 'go | ||
| 146 | :feature 'string | ||
| 147 | '([(interpreted_string_literal) | ||
| 148 | (raw_string_literal) | ||
| 149 | (rune_literal)] @font-lock-string-face) | ||
| 150 | |||
| 151 | :language 'go | ||
| 152 | :feature 'type | ||
| 153 | '([(package_identifier) (type_identifier)] @font-lock-type-face) | ||
| 154 | |||
| 155 | :language 'go | ||
| 156 | :feature 'variable | ||
| 157 | '((identifier) @font-lock-variable-name-face) | ||
| 158 | |||
| 159 | :language 'go | ||
| 160 | :feature 'escape-sequence | ||
| 161 | :override t | ||
| 162 | '((escape_sequence) @font-lock-escape-face) | ||
| 163 | |||
| 164 | :language 'go | ||
| 165 | :feature 'property | ||
| 166 | :override t | ||
| 167 | '((field_identifier) @font-lock-property-face | ||
| 168 | (keyed_element (_ (identifier) @font-lock-property-face))) | ||
| 169 | |||
| 170 | :language 'go | ||
| 171 | :feature 'error | ||
| 172 | :override t | ||
| 173 | '((ERROR) @font-lock-warning-face)) | ||
| 174 | "Tree-sitter font-lock settings for `go-ts-mode'.") | ||
| 175 | |||
| 176 | (defun go-ts-mode--imenu () | ||
| 177 | "Return Imenu alist for the current buffer." | ||
| 178 | (let* ((node (treesit-buffer-root-node)) | ||
| 179 | (func-tree (treesit-induce-sparse-tree | ||
| 180 | node "function_declaration" nil 1000)) | ||
| 181 | (type-tree (treesit-induce-sparse-tree | ||
| 182 | node "type_spec" nil 1000)) | ||
| 183 | (func-index (go-ts-mode--imenu-1 func-tree)) | ||
| 184 | (type-index (go-ts-mode--imenu-1 type-tree))) | ||
| 185 | (append | ||
| 186 | (when func-index `(("Function" . ,func-index))) | ||
| 187 | (when type-index `(("Type" . ,type-index)))))) | ||
| 188 | |||
| 189 | (defun go-ts-mode--imenu-1 (node) | ||
| 190 | "Helper for `go-ts-mode--imenu'. | ||
| 191 | Find string representation for NODE and set marker, then recurse | ||
| 192 | the subtrees." | ||
| 193 | (let* ((ts-node (car node)) | ||
| 194 | (children (cdr node)) | ||
| 195 | (subtrees (mapcan #'go-ts-mode--imenu-1 | ||
| 196 | children)) | ||
| 197 | (name (when ts-node | ||
| 198 | (treesit-node-text | ||
| 199 | (pcase (treesit-node-type ts-node) | ||
| 200 | ("function_declaration" | ||
| 201 | (treesit-node-child-by-field-name ts-node "name")) | ||
| 202 | ("type_spec" | ||
| 203 | (treesit-node-child-by-field-name ts-node "name")))))) | ||
| 204 | (marker (when ts-node | ||
| 205 | (set-marker (make-marker) | ||
| 206 | (treesit-node-start ts-node))))) | ||
| 207 | (cond | ||
| 208 | ((or (null ts-node) (null name)) subtrees) | ||
| 209 | (subtrees | ||
| 210 | `((,name ,(cons name marker) ,@subtrees))) | ||
| 211 | (t | ||
| 212 | `((,name . ,marker)))))) | ||
| 213 | |||
| 214 | ;;;###autoload | ||
| 215 | (add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode)) | ||
| 216 | |||
| 217 | ;;;###autoload | ||
| 218 | (define-derived-mode go-ts-mode prog-mode "Go" | ||
| 219 | "Major mode for editing Go, powered by tree-sitter." | ||
| 220 | :group 'go | ||
| 221 | :syntax-table go-ts-mode--syntax-table | ||
| 222 | |||
| 223 | (when (treesit-ready-p 'go) | ||
| 224 | (treesit-parser-create 'go) | ||
| 225 | |||
| 226 | ;; Comments. | ||
| 227 | (setq-local comment-start "// ") | ||
| 228 | (setq-local comment-end "") | ||
| 229 | (setq-local comment-start-skip (rx "//" (* (syntax whitespace)))) | ||
| 230 | |||
| 231 | ;; Imenu. | ||
| 232 | (setq-local imenu-create-index-function #'go-ts-mode--imenu) | ||
| 233 | (setq-local which-func-functions nil) | ||
| 234 | |||
| 235 | ;; Indent. | ||
| 236 | (setq-local indent-tabs-mode t | ||
| 237 | treesit-simple-indent-rules go-ts-mode--indent-rules) | ||
| 238 | |||
| 239 | ;; Font-lock. | ||
| 240 | (setq-local treesit-font-lock-settings go-ts-mode--font-lock-settings) | ||
| 241 | (setq-local treesit-font-lock-feature-list | ||
| 242 | '(( comment) | ||
| 243 | ( keyword string type) | ||
| 244 | ( constant escape-sequence function label number | ||
| 245 | property variable) | ||
| 246 | ( bracket delimiter error operator))) | ||
| 247 | |||
| 248 | (treesit-major-mode-setup))) | ||
| 249 | |||
| 250 | ;; go.mod support. | ||
| 251 | |||
| 252 | (defvar go-mod-ts-mode--syntax-table | ||
| 253 | (let ((table (make-syntax-table))) | ||
| 254 | (modify-syntax-entry ?/ ". 124b" table) | ||
| 255 | (modify-syntax-entry ?\n "> b" table) | ||
| 256 | table) | ||
| 257 | "Syntax table for `go-mod-ts-mode'.") | ||
| 258 | |||
| 259 | (defvar go-mod-ts-mode--indent-rules | ||
| 260 | `((gomod | ||
| 261 | ((node-is ")") parent-bol 0) | ||
| 262 | ((parent-is "exclude_directive") parent-bol go-ts-mode-indent-offset) | ||
| 263 | ((parent-is "module_directive") parent-bol go-ts-mode-indent-offset) | ||
| 264 | ((parent-is "replace_directive") parent-bol go-ts-mode-indent-offset) | ||
| 265 | ((parent-is "require_directive") parent-bol go-ts-mode-indent-offset) | ||
| 266 | ((parent-is "retract_directive") parent-bol go-ts-mode-indent-offset) | ||
| 267 | ((go-mod-ts-mode--in-directive-p) no-indent go-ts-mode-indent-offset) | ||
| 268 | (no-node no-indent 0))) | ||
| 269 | "Tree-sitter indent rules for `go-mod-ts-mode'.") | ||
| 270 | |||
| 271 | (defun go-mod-ts-mode--in-directive-p () | ||
| 272 | "Return non-nil if inside a directive. | ||
| 273 | When entering an empty directive or adding a new entry to one, no node | ||
| 274 | will be present meaning none of the indentation rules will match, | ||
| 275 | because there is no parent to match against. This function determines | ||
| 276 | what the parent of the node would be if it were a node." | ||
| 277 | (lambda (node _ _ &rest _) | ||
| 278 | (unless (treesit-node-type node) | ||
| 279 | (save-excursion | ||
| 280 | (backward-up-list) | ||
| 281 | (back-to-indentation) | ||
| 282 | (pcase (treesit-node-type (treesit-node-at (point))) | ||
| 283 | ("exclude" t) | ||
| 284 | ("module" t) | ||
| 285 | ("replace" t) | ||
| 286 | ("require" t) | ||
| 287 | ("retract" t)))))) | ||
| 288 | |||
| 289 | (defvar go-mod-ts-mode--keywords | ||
| 290 | '("exclude" "go" "module" "replace" "require" "retract") | ||
| 291 | "go.mod keywords for tree-sitter font-locking.") | ||
| 292 | |||
| 293 | (defvar go-mod-ts-mode--font-lock-settings | ||
| 294 | (treesit-font-lock-rules | ||
| 295 | :language 'gomod | ||
| 296 | :feature 'bracket | ||
| 297 | '((["(" ")"]) @font-lock-bracket-face) | ||
| 298 | |||
| 299 | :language 'gomod | ||
| 300 | :feature 'comment | ||
| 301 | '((comment) @font-lock-comment-face) | ||
| 302 | |||
| 303 | :language 'gomod | ||
| 304 | :feature 'keyword | ||
| 305 | `([,@go-mod-ts-mode--keywords] @font-lock-keyword-face) | ||
| 306 | |||
| 307 | :language 'gomod | ||
| 308 | :feature 'number | ||
| 309 | '([(go_version) (version)] @font-lock-number-face) | ||
| 310 | |||
| 311 | :language 'gomod | ||
| 312 | :feature 'operator | ||
| 313 | '((["=>"]) @font-lock-operator-face) | ||
| 314 | |||
| 315 | :language 'gomod | ||
| 316 | :feature 'error | ||
| 317 | :override t | ||
| 318 | '((ERROR) @font-lock-warning-face)) | ||
| 319 | "Tree-sitter font-lock settings for `go-mod-ts-mode'.") | ||
| 320 | |||
| 321 | ;;;###autoload | ||
| 322 | (add-to-list 'auto-mode-alist '("/go\\.mod\\'" . go-mod-ts-mode)) | ||
| 323 | |||
| 324 | ;;;###autoload | ||
| 325 | (define-derived-mode go-mod-ts-mode prog-mode "Go Mod" | ||
| 326 | "Major mode for editing go.mod files, powered by tree-sitter." | ||
| 327 | :group 'go | ||
| 328 | :syntax-table go-mod-ts-mode--syntax-table | ||
| 329 | |||
| 330 | (when (treesit-ready-p 'gomod) | ||
| 331 | (treesit-parser-create 'gomod) | ||
| 332 | |||
| 333 | ;; Comments. | ||
| 334 | (setq-local comment-start "// ") | ||
| 335 | (setq-local comment-end "") | ||
| 336 | (setq-local comment-start-skip (rx "//" (* (syntax whitespace)))) | ||
| 337 | |||
| 338 | ;; Indent. | ||
| 339 | (setq-local indent-tabs-mode t | ||
| 340 | treesit-simple-indent-rules go-mod-ts-mode--indent-rules) | ||
| 341 | |||
| 342 | ;; Font-lock. | ||
| 343 | (setq-local treesit-font-lock-settings go-mod-ts-mode--font-lock-settings) | ||
| 344 | (setq-local treesit-font-lock-feature-list | ||
| 345 | '((comment) | ||
| 346 | (keyword) | ||
| 347 | (number) | ||
| 348 | (bracket error operator))) | ||
| 349 | |||
| 350 | (treesit-major-mode-setup))) | ||
| 351 | |||
| 352 | (provide 'go-ts-mode) | ||
| 353 | |||
| 354 | ;;; go-ts-mode.el ends here | ||