(subtrees (mapcan #'c-ts-mode--imenu-1 (cdr node)))
(name (when ts-node
(or (treesit-node-text
- (or (treesit-node-child-by-field-name
- ts-node "declarator")
+ (pcase (treesit-node-type ts-node)
+ ("function_definition"
+ (treesit-node-child-by-field-name
(treesit-node-child-by-field-name
- ts-node "name"))
+ ts-node "declarator")
+ "declarator"))
+ ("declaration"
+ (let ((child (treesit-node-child ts-node -1 t)))
+ (pcase (treesit-node-type child)
+ ("identifier" child)
+ (_ (treesit-node-child-by-field-name
+ child "declarator")))))
+ ("struct_specifier"
+ (treesit-node-child-by-field-name
+ ts-node "name")))
t)
"Unnamed node")))
(marker (when ts-node
(set-marker (make-marker)
(treesit-node-start ts-node)))))
- ;; A struct_specifier could be inside a parameter list or another
- ;; struct definition. In those cases we don't include it.
+ ;; A struct_specifier could be inside a parameter list, another
+ ;; struct definition, a variable declaration, a function
+ ;; declaration. In those cases we don't include it.
(cond
((string-match-p
- (rx (or "parameter" "field") "_declaration")
+ (rx (or "parameter_declaration" "field_declaration"
+ "declaration" "function_definition"))
(or (treesit-node-type (treesit-node-parent ts-node))
""))
nil)
+ ((and (equal (treesit-node-type ts-node) "declaration")
+ (not (equal (treesit-node-type (treesit-node-parent ts-node))
+ "translation_unit")))
+ nil)
((null ts-node) subtrees)
(subtrees
`((,name ,(cons name marker) ,@subtrees)))
(defun c-ts-mode--imenu ()
"Return Imenu alist for the current buffer."
(let* ((node (treesit-buffer-root-node))
- (tree (treesit-induce-sparse-tree
- node (rx (or "function_definition"
- "struct_specifier")))))
- (c-ts-mode--imenu-1 tree)))
+ (func-tree (treesit-induce-sparse-tree
+ node "^function_definition$"))
+ (var-tree (treesit-induce-sparse-tree
+ node "^declaration$"))
+ (struct-tree (treesit-induce-sparse-tree
+ node "^struct_specifier$")))
+ `(("Struct" . ,(c-ts-mode--imenu-1 struct-tree))
+ ("Variable" . ,(c-ts-mode--imenu-1 var-tree))
+ ("Function" . ,(c-ts-mode--imenu-1 func-tree)))))
;;;###autoload
(define-derived-mode c-ts-mode--base-mode prog-mode "C"
do (setq node (treesit-node-parent node))
finally return (string-join name-list "."))))
-;; Keep this private since we might later change it or generalize it.
-(defvar js--treesit-imenu-type-alist
- '((variable . "V ")
- (function . "F ")
- (class . "C ")
- (method . "M "))
- "Maps imenu label types to their \"symbol\".
-Symbols are prefixed to each label in imenu (see
-`js--treesit-imenu-label').")
-
-(defun js--treesit-imenu-label (type name)
- "Format label for imenu.
-TYPE can be `variable', `function', `class', `method'.
-NAME is a string."
- (format "%s%s" (alist-get type js--treesit-imenu-type-alist)
- name))
-
(defun js--treesit-imenu-1 (node)
"Given a sparse tree, create an imenu alist.
(treesit-node-top-level ts-node))
nil)
(subtrees
- (let ((parent-label (js--treesit-imenu-label type name))
- (jump-label ""))
- `((,parent-label
- ,(cons jump-label marker)
- ,@subtrees))))
- (t (let ((label (js--treesit-imenu-label type name)))
- (list (cons label marker)))))))
+ `((,name
+ ,(cons "" marker)
+ ,@subtrees)))
+ (t (list (cons name marker))))))
(defun js--treesit-imenu ()
"Return Imenu alist for the current buffer."
(let* ((node (treesit-buffer-root-node))
- (tree (treesit-induce-sparse-tree
- node (rx (or "class_declaration"
- "method_definition"
- "function_declaration"
- "lexical_declaration")))))
- (js--treesit-imenu-1 tree)))
+ (class-tree (treesit-induce-sparse-tree
+ node (rx (or "class_declaration"
+ "method_definition"))))
+ (func-tree (treesit-induce-sparse-tree
+ node "function_declaration"))
+ (var-tree (treesit-induce-sparse-tree
+ node "lexical_declaration")))
+ `(("Class" . ,(js--treesit-imenu-1 class-tree))
+ ("Varieable" . ,(js--treesit-imenu-1 var-tree))
+ ("Function" . ,(js--treesit-imenu-1 func-tree)))))
;;; Main Function