Add go-work-ts-mode for Go workspace files
* lisp/progmodes/eglot.el (eglot-server-programs): Add go-work-ts-mode. * lisp/progmodes/go-ts-mode.el (Commentary): Add the repositories for the grammars. (go-work-ts-mode--indent-rules, go-work-ts-mode--keywords) (go-work-ts-mode--font-lock-settings): New variables. (go-work-ts-mode--directive-matcher, go-work-ts-mode): New functions. (go-mod-ts-mode--directive-matcher): Rename from go-mod-ts-mode--in-directive-p. Be more specific on the directive location (modules). Replace mention of nil with function. Use member instead of pcase to check node types. * admin/notes/tree-sitter/build-module/batch.sh * admin/notes/tree-sitter/build-module/build.sh: Add go-work support. * test/lisp/progmodes/go-ts-mode-resources/font-lock-package.go: * test/lisp/progmodes/go-ts-mode-resources/indent-mod.erts: * test/lisp/progmodes/go-ts-mode-resources/indent-work.erts: New files for testing indentation and font-locking for Go module and workspace files. * test/lisp/progmodes/go-ts-mode-tests.el: Add tests for Go module and workspace files. (Bug#74461) * etc/NEWS: Announce go-work-ts-mode.
This commit is contained in:
parent
7aa4291728
commit
aade1b707c
9 changed files with 176 additions and 11 deletions
|
@ -11,6 +11,7 @@ languages=(
|
|||
'elixir'
|
||||
'go'
|
||||
'go-mod'
|
||||
'go-work'
|
||||
'heex'
|
||||
'html'
|
||||
'java'
|
||||
|
|
|
@ -39,6 +39,11 @@ case "${lang}" in
|
|||
lang="gomod"
|
||||
org="camdencheek"
|
||||
;;
|
||||
"go-work")
|
||||
# The parser is called "gowork".
|
||||
lang="gowork"
|
||||
org="omertuc"
|
||||
;;
|
||||
"heex")
|
||||
org="phoenixframework"
|
||||
;;
|
||||
|
|
6
etc/NEWS
6
etc/NEWS
|
@ -1474,6 +1474,12 @@ means of the GDI+ library.
|
|||
In addition to ':file FILE' for playing a sound from a file, ':data
|
||||
DATA' can now be used to play a sound from memory.
|
||||
|
||||
---
|
||||
** New major mode 'go-work-ts-mode'.
|
||||
A major mode based on the tree-sitter library for editing "go.work"
|
||||
files. If tree-sitter is properly set-up by the user, it can be
|
||||
enabled for files named "go.work".
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
This file is part of GNU Emacs.
|
||||
|
|
|
@ -279,7 +279,7 @@ automatically)."
|
|||
(elm-mode . ("elm-language-server"))
|
||||
(mint-mode . ("mint" "ls"))
|
||||
((kotlin-mode kotlin-ts-mode) . ("kotlin-language-server"))
|
||||
((go-mode go-dot-mod-mode go-dot-work-mode go-ts-mode go-mod-ts-mode)
|
||||
((go-mode go-dot-mod-mode go-dot-work-mode go-ts-mode go-mod-ts-mode go-work-ts-mode)
|
||||
. ("gopls"))
|
||||
((R-mode ess-r-mode) . ("R" "--slave" "-e"
|
||||
"languageserver::run()"))
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
;;
|
||||
;; go-ts-mode is known to work with the following languages and version:
|
||||
;; - tree-sitter-go: v0.23.4-1-g12fe553
|
||||
;; - tree-sitter-go-mod: v1.1.0-3b01edce
|
||||
;; - tree-sitter-go-work: 949a8a47
|
||||
;;
|
||||
;; We try our best to make builtin modes work with latest grammar
|
||||
;; versions, so a more recent grammar version has a good chance to work.
|
||||
|
@ -33,6 +35,9 @@
|
|||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; Go uses tabs as a convention for indentation:
|
||||
;; https://go.dev/doc/effective_go#formatting
|
||||
;; so `indent-tabs-mode' is enabled for the modes.
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
@ -478,7 +483,7 @@ be run."
|
|||
default-directory
|
||||
(go-ts-mode--get-test-flags))))
|
||||
|
||||
;; go.mod support.
|
||||
;;;; go.mod support.
|
||||
|
||||
(defvar go-mod-ts-mode--syntax-table
|
||||
(let ((table (make-syntax-table)))
|
||||
|
@ -495,12 +500,12 @@ be run."
|
|||
((parent-is "replace_directive") parent-bol go-ts-mode-indent-offset)
|
||||
((parent-is "require_directive") parent-bol go-ts-mode-indent-offset)
|
||||
((parent-is "retract_directive") parent-bol go-ts-mode-indent-offset)
|
||||
((go-mod-ts-mode--in-directive-p) no-indent go-ts-mode-indent-offset)
|
||||
((go-mod-ts-mode--directive-matcher) no-indent go-ts-mode-indent-offset)
|
||||
(no-node no-indent 0)))
|
||||
"Tree-sitter indent rules for `go-mod-ts-mode'.")
|
||||
|
||||
(defun go-mod-ts-mode--in-directive-p ()
|
||||
"Return non-nil if point is inside a directive.
|
||||
(defun go-mod-ts-mode--directive-matcher ()
|
||||
"Return a function for determining if point is inside a Go module directive.
|
||||
When entering an empty directive or adding a new entry to one, no node
|
||||
will be present meaning none of the indentation rules will match,
|
||||
because there is no parent to match against. This function determines
|
||||
|
@ -510,12 +515,12 @@ what the parent of the node would be if it were a node."
|
|||
(save-excursion
|
||||
(backward-up-list)
|
||||
(back-to-indentation)
|
||||
(pcase (treesit-node-type (treesit-node-at (point)))
|
||||
("exclude" t)
|
||||
("module" t)
|
||||
("replace" t)
|
||||
("require" t)
|
||||
("retract" t))))))
|
||||
(member (treesit-node-type (treesit-node-at (point)))
|
||||
'("exclude"
|
||||
"module"
|
||||
"replace"
|
||||
"require"
|
||||
"retract"))))))
|
||||
|
||||
(defvar go-mod-ts-mode--keywords
|
||||
'("exclude" "go" "module" "replace" "require" "retract")
|
||||
|
@ -582,6 +587,94 @@ what the parent of the node would be if it were a node."
|
|||
(if (treesit-ready-p 'gomod)
|
||||
(add-to-list 'auto-mode-alist '("/go\\.mod\\'" . go-mod-ts-mode)))
|
||||
|
||||
;;;; go.work support.
|
||||
|
||||
(defvar go-work-ts-mode--indent-rules
|
||||
`((gowork
|
||||
((node-is ")") parent-bol 0)
|
||||
((parent-is "replace_directive") parent-bol go-ts-mode-indent-offset)
|
||||
((parent-is "use_directive") parent-bol go-ts-mode-indent-offset)
|
||||
((go-work-ts-mode--directive-matcher) no-indent go-ts-mode-indent-offset)
|
||||
(no-node no-indent 0)))
|
||||
"Tree-sitter indent rules for `go-work-ts-mode'.")
|
||||
|
||||
(defun go-work-ts-mode--directive-matcher ()
|
||||
"Return a function for determining if point is inside a Go workspace directive.
|
||||
When entering an empty directive or adding a new entry to one, no node
|
||||
will be present meaning none of the indentation rules will match,
|
||||
because there is no parent to match against. This function determines
|
||||
what the parent of the node would be if it were a node."
|
||||
(lambda (node _ _ &rest _)
|
||||
(unless (treesit-node-type node)
|
||||
(save-excursion
|
||||
(backward-up-list)
|
||||
(back-to-indentation)
|
||||
(member (treesit-node-type (treesit-node-at (point)))
|
||||
'("replace"
|
||||
"use"))))))
|
||||
|
||||
(defvar go-work-ts-mode--keywords
|
||||
'("go" "replace" "use")
|
||||
"go.work keywords for tree-sitter font-locking.")
|
||||
|
||||
(defvar go-work-ts-mode--font-lock-settings
|
||||
(treesit-font-lock-rules
|
||||
:language 'gowork
|
||||
:feature 'bracket
|
||||
'((["(" ")"]) @font-lock-bracket-face)
|
||||
|
||||
:language 'gowork
|
||||
:feature 'comment
|
||||
'((comment) @font-lock-comment-face)
|
||||
|
||||
:language 'gowork
|
||||
:feature 'keyword
|
||||
`([,@go-work-ts-mode--keywords] @font-lock-keyword-face)
|
||||
|
||||
:language 'gowork
|
||||
:feature 'number
|
||||
'([(go_version) (version)] @font-lock-number-face)
|
||||
|
||||
:language 'gowork
|
||||
:feature 'operator
|
||||
'((["=>"]) @font-lock-operator-face)
|
||||
|
||||
:language 'gowork
|
||||
:feature 'error
|
||||
:override t
|
||||
'((ERROR) @font-lock-warning-face))
|
||||
"Tree-sitter font-lock settings for `go-work-ts-mode'.")
|
||||
|
||||
;;;###autoload
|
||||
(define-derived-mode go-work-ts-mode prog-mode "Go Work"
|
||||
"Major mode for editing go.work files, powered by tree-sitter."
|
||||
:group 'go
|
||||
|
||||
(when (treesit-ready-p 'gowork)
|
||||
(setq treesit-primary-parser (treesit-parser-create 'gowork))
|
||||
|
||||
;; Comments.
|
||||
(setq-local comment-start "// ")
|
||||
(setq-local comment-end "")
|
||||
(setq-local comment-start-skip (rx "//" (* (syntax whitespace))))
|
||||
|
||||
;; Indent.
|
||||
(setq-local indent-tabs-mode t
|
||||
treesit-simple-indent-rules go-work-ts-mode--indent-rules)
|
||||
|
||||
;; Font-lock.
|
||||
(setq-local treesit-font-lock-settings go-work-ts-mode--font-lock-settings)
|
||||
(setq-local treesit-font-lock-feature-list
|
||||
'((comment)
|
||||
(keyword)
|
||||
(number)
|
||||
(bracket error operator)))
|
||||
|
||||
(treesit-major-mode-setup)))
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'auto-mode-alist '("/go\\.work\\'" . go-work-ts-mode))
|
||||
|
||||
(provide 'go-ts-mode)
|
||||
|
||||
;;; go-ts-mode.el ends here
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
replace gnu.org/go/package1 v1.0.0 => gnu.org/go/package2 v1.0.0
|
||||
// ^ font-lock-keyword-face
|
||||
// ^ font-lock-number-face
|
||||
// ^ font-lock-operator-face
|
16
test/lisp/progmodes/go-ts-mode-resources/indent-mod.erts
Normal file
16
test/lisp/progmodes/go-ts-mode-resources/indent-mod.erts
Normal file
|
@ -0,0 +1,16 @@
|
|||
Code:
|
||||
(lambda ()
|
||||
(go-mod-ts-mode)
|
||||
(indent-region (point-min) (point-max)))
|
||||
|
||||
Point-Char: |
|
||||
|
||||
Name: Basic
|
||||
|
||||
=-=
|
||||
require (
|
||||
gnu.org/go/package1 v1.0.0
|
||||
gnu.org/go/package2 v1.0.0
|
||||
)
|
||||
|
||||
=-=-=
|
16
test/lisp/progmodes/go-ts-mode-resources/indent-work.erts
Normal file
16
test/lisp/progmodes/go-ts-mode-resources/indent-work.erts
Normal file
|
@ -0,0 +1,16 @@
|
|||
Code:
|
||||
(lambda ()
|
||||
(go-work-ts-mode)
|
||||
(indent-region (point-min) (point-max)))
|
||||
|
||||
Point-Char: |
|
||||
|
||||
Name: Basic
|
||||
|
||||
=-=
|
||||
use (
|
||||
./package1
|
||||
./package2
|
||||
)
|
||||
|
||||
=-=-=
|
|
@ -23,6 +23,8 @@
|
|||
(require 'ert-x)
|
||||
(require 'treesit)
|
||||
|
||||
;; go-ts-mode
|
||||
|
||||
(ert-deftest go-ts-mode-test-indentation ()
|
||||
(skip-unless (treesit-ready-p 'go))
|
||||
(ert-test-erts-file (ert-resource-file "indent.erts")))
|
||||
|
@ -32,5 +34,27 @@
|
|||
(let ((treesit-font-lock-level 4))
|
||||
(ert-font-lock-test-file (ert-resource-file "font-lock.go") 'go-ts-mode)))
|
||||
|
||||
;; go-mod-ts-mode
|
||||
|
||||
(ert-deftest go-work-ts-mode-test-indentation ()
|
||||
(skip-unless (treesit-ready-p 'gomod))
|
||||
(ert-test-erts-file (ert-resource-file "indent-mod.erts")))
|
||||
|
||||
(ert-deftest go-mod-ts-test-font-lock ()
|
||||
(skip-unless (treesit-ready-p 'gomod))
|
||||
(let ((treesit-font-lock-level 4))
|
||||
(ert-font-lock-test-file (ert-resource-file "font-lock-package.go") 'go-mod-ts-mode)))
|
||||
|
||||
;; go-work-ts-mode
|
||||
|
||||
(ert-deftest go-work-ts-mode-test-indentation ()
|
||||
(skip-unless (treesit-ready-p 'gowork))
|
||||
(ert-test-erts-file (ert-resource-file "indent-work.erts")))
|
||||
|
||||
(ert-deftest go-work-ts-test-font-lock ()
|
||||
(skip-unless (treesit-ready-p 'gowork))
|
||||
(let ((treesit-font-lock-level 4))
|
||||
(ert-font-lock-test-file (ert-resource-file "font-lock-package.go") 'go-work-ts-mode)))
|
||||
|
||||
(provide 'go-ts-mode-tests)
|
||||
;;; go-ts-mode-tests.el ends here
|
||||
|
|
Loading…
Add table
Reference in a new issue