aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorYuan Fu2022-09-24 19:41:17 -0700
committerYuan Fu2022-09-24 21:11:30 -0700
commit795e01ac248d389a581589b13a02465a2f99202f (patch)
tree8ba12d103784a17b37df98bd41f7d71483f5d008 /lisp/progmodes/python.el
parentf071e61d106e6f3c17b660e3aa1a5b7890ea5d41 (diff)
downloademacs-795e01ac248d389a581589b13a02465a2f99202f.tar.gz
emacs-795e01ac248d389a581589b13a02465a2f99202f.zip
Update and enable treesit-imenu function in python.el
* lisp/progmodes/python.el (python--treesit-settings): Add docstring. (python--imenu-treesit-create-index-1): Rewrite with treesit-induce-sparse-tree. (python-imenu-treesit-create-index): Move main body to python--imenu-treesit-create-index-1. (python-imenu-treesit-create-flat-index): Fix typo. (python-mode): Enable treesit-imenu. Also fix indentation for which-func code.
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el114
1 files changed, 69 insertions, 45 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 8368f4da513..fb91d00053a 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -1035,7 +1035,9 @@ Do not fontify the initial f for f-strings."
1035 `(seq bol (or ,@python--treesit-exceptions) 1035 `(seq bol (or ,@python--treesit-exceptions)
1036 eol)) 1036 eol))
1037 @font-lock-type-face)) 1037 @font-lock-type-face))
1038 (type (identifier) @font-lock-type-face)))) 1038 (type (identifier) @font-lock-type-face)))
1039 "Tree-sitter font-lock settings.")
1040
1039 1041
1040;;; Indentation 1042;;; Indentation
1041 1043
@@ -5244,61 +5246,79 @@ To this:
5244 (python-imenu-create-index)))))) 5246 (python-imenu-create-index))))))
5245 5247
5246;;; Tree-sitter imenu 5248;;; Tree-sitter imenu
5247;;
5248;; This works, but is slower than the native functions, presumably
5249;; because traversing the parser tree is slower than scanning the
5250;; text. Also I'm sure this consumes more memory as we allocate
5251;; memory for every node in the tree.
5252 5249
5253(defun python--imenu-treesit-create-index (&optional node) 5250(defun python--imenu-treesit-create-index-1 (node)
5254 "Return tree Imenu alist for the current Python buffer. 5251 "Given a sparse tree, create an imenu alist.
5255 5252
5256Change `python-imenu-format-item-label-function', 5253NODE is the root node of the tree returned by
5257`python-imenu-format-parent-item-label-function', 5254`treesit-induce-sparse-tree' (not a tree-sitter node, its car is
5258`python-imenu-format-parent-item-jump-label-function' to 5255a tree-sitter node). Walk that tree and return an imenu alist.
5259customize how labels are formatted.
5260 5256
5261NODE is the root node of the subtree you want to build an index 5257Return a list of ENTRY where
5262of. If nil, use the root node of the whole parse tree.
5263 5258
5264Similar to `python-imenu-create-index' but use tree-sitter." 5259ENTRY := (NAME . MARKER)
5265 (let* ((node (or node (treesit-buffer-root-node 'python))) 5260 | (NAME . ((JUMP-LABEL . MARKER)
5266 (children (treesit-node-children node t)) 5261 ENTRY
5267 (subtrees (mapcan #'python--imenu-treesit-create-index 5262 ...)
5263
5264NAME is the function/class's name, JUMP-LABEL is like \"*function
5265definition*\"."
5266 (let* ((ts-node (car node))
5267 (children (cdr node))
5268 (subtrees (mapcan #'python--imenu-treesit-create-index-1
5268 children)) 5269 children))
5269 (type (pcase (treesit-node-type node) 5270 (type (pcase (treesit-node-type ts-node)
5270 ("function_definition" 'def) 5271 ("function_definition" 'def)
5271 ("class_definition" 'class) 5272 ("class_definition" 'class)))
5272 (_ nil))) 5273 ;; The root of the tree could have a nil ts-node.
5273 (name (when type 5274 (name (when ts-node
5274 (treesit-node-text 5275 (treesit-node-text
5275 (treesit-node-child-by-field-name 5276 (treesit-node-child-by-field-name
5276 node "name") t)))) 5277 ts-node "name") t)))
5278 (marker (when ts-node
5279 (set-marker (make-marker)
5280 (treesit-node-start ts-node)))))
5277 (cond 5281 (cond
5278 ;; 1. This node is a function/class and doesn't have children. 5282 ((null ts-node)
5279 ((and type (not subtrees)) 5283 subtrees)
5280 (let ((label 5284 (subtrees
5281 (funcall python-imenu-format-item-label-function
5282 type name)))
5283 (list (cons label
5284 (set-marker (make-marker)
5285 (treesit-node-start node))))))
5286 ;; 2. This node is a function/class and has children.
5287 ((and type subtrees)
5288 (let ((parent-label 5285 (let ((parent-label
5289 (funcall python-imenu-format-parent-item-label-function 5286 (funcall python-imenu-format-parent-item-label-function
5290 type name)) 5287 type name))
5291 (jump-label 5288 (jump-label
5292 (funcall python-imenu-format-parent-item-jump-label-function 5289 (funcall
5293 type name))) 5290 python-imenu-format-parent-item-jump-label-function
5291 type name)))
5294 `((,parent-label 5292 `((,parent-label
5295 ,(cons jump-label (set-marker (make-marker) 5293 ,(cons jump-label marker)
5296 (treesit-node-start node)))
5297 ,@subtrees)))) 5294 ,@subtrees))))
5298 ;; 3. This node is not a function/class. 5295 (t (let ((label
5299 ((not type) subtrees)))) 5296 (funcall python-imenu-format-item-label-function
5297 type name)))
5298 (list (cons label marker)))))))
5299
5300(defun python-imenu-treesit-create-index (&optional node)
5301 "Return tree Imenu alist for the current Python buffer.
5300 5302
5301(defun python--imenu-treesit-create-flat-index () 5303Change `python-imenu-format-item-label-function',
5304`python-imenu-format-parent-item-label-function',
5305`python-imenu-format-parent-item-jump-label-function' to
5306customize how labels are formatted.
5307
5308NODE is the root node of the subtree you want to build an index
5309of. If nil, use the root node of the whole parse tree.
5310
5311Similar to `python-imenu-create-index' but use tree-sitter."
5312 (let* ((node (or node (treesit-buffer-root-node 'python)))
5313 (tree (treesit-induce-sparse-tree
5314 node
5315 (rx (seq bol
5316 (or "function" "class")
5317 "_definition"
5318 eol)))))
5319 (python--imenu-treesit-create-index-1 tree)))
5320
5321(defun python-imenu-treesit-create-flat-index ()
5302 "Return flat outline of the current Python buffer for Imenu. 5322 "Return flat outline of the current Python buffer for Imenu.
5303 5323
5304Change `python-imenu-format-item-label-function', 5324Change `python-imenu-format-item-label-function',
@@ -5309,7 +5329,7 @@ customize how labels are formatted.
5309Similar to `python-imenu-create-flat-index' but use 5329Similar to `python-imenu-create-flat-index' but use
5310tree-sitter." 5330tree-sitter."
5311 (python-imenu-create-flat-index 5331 (python-imenu-create-flat-index
5312 (python--imenu-treesit-create-index))) 5332 (python-imenu-treesit-create-index)))
5313 5333
5314;;; Misc helpers 5334;;; Misc helpers
5315 5335
@@ -6120,14 +6140,18 @@ REPORT-FN is Flymake's callback function."
6120 (add-hook 'post-self-insert-hook 6140 (add-hook 'post-self-insert-hook
6121 #'python-indent-post-self-insert-function 'append 'local) 6141 #'python-indent-post-self-insert-function 'append 'local)
6122 6142
6123 (setq-local imenu-create-index-function 6143 (if (and python-use-tree-sitter
6124 #'python-imenu-create-index) 6144 (treesit-can-enable-p))
6145 (setq-local imenu-create-index-function
6146 #'python-treesit-imenu-create-index)
6147 (setq-local imenu-create-index-function
6148 #'python-imenu-create-index))
6125 6149
6126 (setq-local add-log-current-defun-function 6150 (setq-local add-log-current-defun-function
6127 #'python-info-current-defun) 6151 #'python-info-current-defun)
6128 6152
6129 (if (and python-use-tree-sitter 6153 (if (and python-use-tree-sitter
6130 (treesit-can-enable-p)) 6154 (treesit-can-enable-p))
6131 (add-hook 'which-func-functions 6155 (add-hook 'which-func-functions
6132 #'python-info-treesit-current-defun nil t) 6156 #'python-info-treesit-current-defun nil t)
6133 (add-hook 'which-func-functions #'python-info-current-defun nil t)) 6157 (add-hook 'which-func-functions #'python-info-current-defun nil t))