diff options
| author | Evgeni Kolev | 2022-12-29 17:49:40 +0200 |
|---|---|---|
| committer | Yuan Fu | 2023-01-08 20:32:51 -0800 |
| commit | dc911e4ba5ccfc99d66504b6e99c9abcf3e617f3 (patch) | |
| tree | af48bc543809c14bfb657a39161c1a519c5e145a | |
| parent | 20f36c8f6f98478dd86ddfe93da2803de2518ea2 (diff) | |
| download | emacs-dc911e4ba5ccfc99d66504b6e99c9abcf3e617f3.tar.gz emacs-dc911e4ba5ccfc99d66504b6e99c9abcf3e617f3.zip | |
Improve go-ts-mode Imenu, navigation and electric pair (bug#60407)
The Imenu items are extended to support "Method", "Struct",
"Interface", "Alias" and "Type".
go-ts-mode is updated to use the Imenu facility added in commit
b39dc7ab27a696a8607ab859aeff3c71509231f5.
Variable electric-indent-chars is set in order to improve integration
with Electric Pair mode.
* lisp/progmodes/go-ts-mode.el (go-ts-mode--imenu-1) (go-ts-mode--imenu):
Remove functions.
(go-ts-mode--defun-name, go-ts-mode--interface-node-p)
(go-ts-mode--struct-node-p, go-ts-mode--other-type-node-p)
(go-ts-mode--alias-node-p): New functions.
(go-ts-mode): Improve Imenu settings, navigation, add Electric Pair
mode settings.
| -rw-r--r-- | lisp/progmodes/go-ts-mode.el | 107 |
1 files changed, 67 insertions, 40 deletions
diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el index 1d6a8a30db5..64e761d2f72 100644 --- a/lisp/progmodes/go-ts-mode.el +++ b/lisp/progmodes/go-ts-mode.el | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | (declare-function treesit-node-child-by-field-name "treesit.c") | 36 | (declare-function treesit-node-child-by-field-name "treesit.c") |
| 37 | (declare-function treesit-node-start "treesit.c") | 37 | (declare-function treesit-node-start "treesit.c") |
| 38 | (declare-function treesit-node-type "treesit.c") | 38 | (declare-function treesit-node-type "treesit.c") |
| 39 | (declare-function treesit-search-subtree "treesit.c") | ||
| 39 | 40 | ||
| 40 | (defcustom go-ts-mode-indent-offset 4 | 41 | (defcustom go-ts-mode-indent-offset 4 |
| 41 | "Number of spaces for each indentation step in `go-ts-mode'." | 42 | "Number of spaces for each indentation step in `go-ts-mode'." |
| @@ -173,44 +174,6 @@ | |||
| 173 | '((ERROR) @font-lock-warning-face)) | 174 | '((ERROR) @font-lock-warning-face)) |
| 174 | "Tree-sitter font-lock settings for `go-ts-mode'.") | 175 | "Tree-sitter font-lock settings for `go-ts-mode'.") |
| 175 | 176 | ||
| 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 | 177 | ;;;###autoload |
| 215 | (add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode)) | 178 | (add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode)) |
| 216 | 179 | ||
| @@ -228,14 +191,30 @@ the subtrees." | |||
| 228 | (setq-local comment-end "") | 191 | (setq-local comment-end "") |
| 229 | (setq-local comment-start-skip (rx "//" (* (syntax whitespace)))) | 192 | (setq-local comment-start-skip (rx "//" (* (syntax whitespace)))) |
| 230 | 193 | ||
| 194 | ;; Navigation. | ||
| 195 | (setq-local treesit-defun-type-regexp | ||
| 196 | (regexp-opt '("method_declaration" | ||
| 197 | "function_declaration" | ||
| 198 | "type_declaration"))) | ||
| 199 | (setq-local treesit-defun-name-function #'go-ts-mode--defun-name) | ||
| 200 | |||
| 231 | ;; Imenu. | 201 | ;; Imenu. |
| 232 | (setq-local imenu-create-index-function #'go-ts-mode--imenu) | 202 | (setq-local treesit-simple-imenu-settings |
| 233 | (setq-local which-func-functions nil) | 203 | `(("Function" "\\`function_declaration\\'" nil nil) |
| 204 | ("Method" "\\`method_declaration\\'" nil nil) | ||
| 205 | ("Struct" "\\`type_declaration\\'" go-ts-mode--struct-node-p nil) | ||
| 206 | ("Interface" "\\`type_declaration\\'" go-ts-mode--interface-node-p nil) | ||
| 207 | ("Type" "\\`type_declaration\\'" go-ts-mode--other-type-node-p nil) | ||
| 208 | ("Alias" "\\`type_declaration\\'" go-ts-mode--alias-node-p nil))) | ||
| 234 | 209 | ||
| 235 | ;; Indent. | 210 | ;; Indent. |
| 236 | (setq-local indent-tabs-mode t | 211 | (setq-local indent-tabs-mode t |
| 237 | treesit-simple-indent-rules go-ts-mode--indent-rules) | 212 | treesit-simple-indent-rules go-ts-mode--indent-rules) |
| 238 | 213 | ||
| 214 | ;; Electric | ||
| 215 | (setq-local electric-indent-chars | ||
| 216 | (append "{}()" electric-indent-chars)) | ||
| 217 | |||
| 239 | ;; Font-lock. | 218 | ;; Font-lock. |
| 240 | (setq-local treesit-font-lock-settings go-ts-mode--font-lock-settings) | 219 | (setq-local treesit-font-lock-settings go-ts-mode--font-lock-settings) |
| 241 | (setq-local treesit-font-lock-feature-list | 220 | (setq-local treesit-font-lock-feature-list |
| @@ -247,6 +226,54 @@ the subtrees." | |||
| 247 | 226 | ||
| 248 | (treesit-major-mode-setup))) | 227 | (treesit-major-mode-setup))) |
| 249 | 228 | ||
| 229 | (defun go-ts-mode--defun-name (node) | ||
| 230 | "Return the defun name of NODE. | ||
| 231 | Return nil if there is no name or if NODE is not a defun node." | ||
| 232 | (pcase (treesit-node-type node) | ||
| 233 | ("function_declaration" | ||
| 234 | (treesit-node-text | ||
| 235 | (treesit-node-child-by-field-name | ||
| 236 | node "name") | ||
| 237 | t)) | ||
| 238 | ("method_declaration" | ||
| 239 | (let* ((receiver-node (treesit-node-child-by-field-name node "receiver")) | ||
| 240 | (type-node (treesit-search-subtree receiver-node "type_identifier")) | ||
| 241 | (name-node (treesit-node-child-by-field-name node "name"))) | ||
| 242 | (concat | ||
| 243 | "(" (treesit-node-text type-node) ")." | ||
| 244 | (treesit-node-text name-node)))) | ||
| 245 | ("type_declaration" | ||
| 246 | (treesit-node-text | ||
| 247 | (treesit-node-child-by-field-name | ||
| 248 | (treesit-node-child node 0 t) "name") | ||
| 249 | t)))) | ||
| 250 | |||
| 251 | (defun go-ts-mode--interface-node-p (node) | ||
| 252 | "Return t if NODE is an interface." | ||
| 253 | (and | ||
| 254 | (string-equal "type_declaration" (treesit-node-type node)) | ||
| 255 | (treesit-search-subtree node "interface_type" nil nil 2))) | ||
| 256 | |||
| 257 | (defun go-ts-mode--struct-node-p (node) | ||
| 258 | "Return t if NODE is a struct." | ||
| 259 | (and | ||
| 260 | (string-equal "type_declaration" (treesit-node-type node)) | ||
| 261 | (treesit-search-subtree node "struct_type" nil nil 2))) | ||
| 262 | |||
| 263 | (defun go-ts-mode--alias-node-p (node) | ||
| 264 | "Return t if NODE is a type alias." | ||
| 265 | (and | ||
| 266 | (string-equal "type_declaration" (treesit-node-type node)) | ||
| 267 | (treesit-search-subtree node "type_alias" nil nil 1))) | ||
| 268 | |||
| 269 | (defun go-ts-mode--other-type-node-p (node) | ||
| 270 | "Return t if NODE is a type, other than interface, struct or alias." | ||
| 271 | (and | ||
| 272 | (string-equal "type_declaration" (treesit-node-type node)) | ||
| 273 | (not (go-ts-mode--interface-node-p node)) | ||
| 274 | (not (go-ts-mode--struct-node-p node)) | ||
| 275 | (not (go-ts-mode--alias-node-p node)))) | ||
| 276 | |||
| 250 | ;; go.mod support. | 277 | ;; go.mod support. |
| 251 | 278 | ||
| 252 | (defvar go-mod-ts-mode--syntax-table | 279 | (defvar go-mod-ts-mode--syntax-table |