diff options
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 259 |
1 files changed, 134 insertions, 125 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 62870f9085b..fb2dc01c9be 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -52,12 +52,12 @@ | |||
| 52 | ;; Extra functions `python-nav-forward-statement', | 52 | ;; Extra functions `python-nav-forward-statement', |
| 53 | ;; `python-nav-backward-statement', | 53 | ;; `python-nav-backward-statement', |
| 54 | ;; `python-nav-beginning-of-statement', `python-nav-end-of-statement', | 54 | ;; `python-nav-beginning-of-statement', `python-nav-end-of-statement', |
| 55 | ;; `python-nav-beginning-of-block' and `python-nav-end-of-block' are | 55 | ;; `python-nav-beginning-of-block', `python-nav-end-of-block' and |
| 56 | ;; included but no bound to any key. At last but not least the | 56 | ;; `python-nav-if-name-main' are included but no bound to any key. At |
| 57 | ;; specialized `python-nav-forward-sexp' allows easy navigation | 57 | ;; last but not least the specialized `python-nav-forward-sexp' allows |
| 58 | ;; between code blocks. If you prefer `cc-mode'-like `forward-sexp' | 58 | ;; easy navigation between code blocks. If you prefer `cc-mode'-like |
| 59 | ;; movement, setting `forward-sexp-function' to nil is enough, You can | 59 | ;; `forward-sexp' movement, setting `forward-sexp-function' to nil is |
| 60 | ;; do that using the `python-mode-hook': | 60 | ;; enough, You can do that using the `python-mode-hook': |
| 61 | 61 | ||
| 62 | ;; (add-hook 'python-mode-hook | 62 | ;; (add-hook 'python-mode-hook |
| 63 | ;; (lambda () (setq forward-sexp-function nil))) | 63 | ;; (lambda () (setq forward-sexp-function nil))) |
| @@ -501,29 +501,24 @@ The type returned can be `comment', `string' or `paren'." | |||
| 501 | (,(lambda (limit) | 501 | (,(lambda (limit) |
| 502 | (let ((re (python-rx (group (+ (any word ?. ?_))) | 502 | (let ((re (python-rx (group (+ (any word ?. ?_))) |
| 503 | (? ?\[ (+ (not (any ?\]))) ?\]) (* space) | 503 | (? ?\[ (+ (not (any ?\]))) ?\]) (* space) |
| 504 | assignment-operator))) | 504 | assignment-operator)) |
| 505 | (when (re-search-forward re limit t) | 505 | (res nil)) |
| 506 | (while (and (python-syntax-context 'paren) | 506 | (while (and (setq res (re-search-forward re limit t)) |
| 507 | (re-search-forward re limit t))) | 507 | (or (python-syntax-context 'paren) |
| 508 | (if (not (or (python-syntax-context 'paren) | 508 | (equal (char-after (point-marker)) ?=)))) |
| 509 | (equal (char-after (point-marker)) ?=))) | 509 | res)) |
| 510 | t | ||
| 511 | (set-match-data nil))))) | ||
| 512 | (1 font-lock-variable-name-face nil nil)) | 510 | (1 font-lock-variable-name-face nil nil)) |
| 513 | ;; support for a, b, c = (1, 2, 3) | 511 | ;; support for a, b, c = (1, 2, 3) |
| 514 | (,(lambda (limit) | 512 | (,(lambda (limit) |
| 515 | (let ((re (python-rx (group (+ (any word ?. ?_))) (* space) | 513 | (let ((re (python-rx (group (+ (any word ?. ?_))) (* space) |
| 516 | (* ?, (* space) (+ (any word ?. ?_)) (* space)) | 514 | (* ?, (* space) (+ (any word ?. ?_)) (* space)) |
| 517 | ?, (* space) (+ (any word ?. ?_)) (* space) | 515 | ?, (* space) (+ (any word ?. ?_)) (* space) |
| 518 | assignment-operator))) | 516 | assignment-operator)) |
| 519 | (when (and (re-search-forward re limit t) | 517 | (res nil)) |
| 520 | (goto-char (nth 3 (match-data)))) | 518 | (while (and (setq res (re-search-forward re limit t)) |
| 521 | (while (and (python-syntax-context 'paren) | 519 | (goto-char (match-end 1)) |
| 522 | (re-search-forward re limit t)) | 520 | (python-syntax-context 'paren))) |
| 523 | (goto-char (nth 3 (match-data)))) | 521 | res)) |
| 524 | (if (not (python-syntax-context 'paren)) | ||
| 525 | t | ||
| 526 | (set-match-data nil))))) | ||
| 527 | (1 font-lock-variable-name-face nil nil)))) | 522 | (1 font-lock-variable-name-face nil nil)))) |
| 528 | 523 | ||
| 529 | (defconst python-syntax-propertize-function | 524 | (defconst python-syntax-propertize-function |
| @@ -1588,6 +1583,29 @@ This command assumes point is not in a string or comment." | |||
| 1588 | (or arg (setq arg 1)) | 1583 | (or arg (setq arg 1)) |
| 1589 | (python-nav-up-list (- arg))) | 1584 | (python-nav-up-list (- arg))) |
| 1590 | 1585 | ||
| 1586 | (defun python-nav-if-name-main () | ||
| 1587 | "Move point at the beginning the __main__ block. | ||
| 1588 | When \"if __name__ == '__main__':\" is found returns its | ||
| 1589 | position, else returns nil." | ||
| 1590 | (interactive) | ||
| 1591 | (let ((point (point)) | ||
| 1592 | (found (catch 'found | ||
| 1593 | (goto-char (point-min)) | ||
| 1594 | (while (re-search-forward | ||
| 1595 | (python-rx line-start | ||
| 1596 | "if" (+ space) | ||
| 1597 | "__name__" (+ space) | ||
| 1598 | "==" (+ space) | ||
| 1599 | (group-n 1 (or ?\" ?\')) | ||
| 1600 | "__main__" (backref 1) (* space) ":") | ||
| 1601 | nil t) | ||
| 1602 | (when (not (python-syntax-context-type)) | ||
| 1603 | (beginning-of-line) | ||
| 1604 | (throw 'found t)))))) | ||
| 1605 | (if found | ||
| 1606 | (point) | ||
| 1607 | (ignore (goto-char point))))) | ||
| 1608 | |||
| 1591 | 1609 | ||
| 1592 | ;;; Shell integration | 1610 | ;;; Shell integration |
| 1593 | 1611 | ||
| @@ -2119,17 +2137,58 @@ Returns the output. See `python-shell-send-string-no-output'." | |||
| 2119 | (define-obsolete-function-alias | 2137 | (define-obsolete-function-alias |
| 2120 | 'python-send-string 'python-shell-internal-send-string "24.3") | 2138 | 'python-send-string 'python-shell-internal-send-string "24.3") |
| 2121 | 2139 | ||
| 2140 | (defun python-shell-buffer-substring (start end &optional nomain) | ||
| 2141 | "Send buffer substring from START to END formatted for shell. | ||
| 2142 | This is a wrapper over `buffer-substring' that takes care of | ||
| 2143 | different transformations for the code sent to be evaluated in | ||
| 2144 | the python shell: | ||
| 2145 | 1. When Optional Argument NOMAIN is non-nil everything under an | ||
| 2146 | \"if __name__ == '__main__'\" block will be removed. | ||
| 2147 | 2. When a subregion of the buffer is sent, it takes care of | ||
| 2148 | appending extra whitelines so tracebacks are correct. | ||
| 2149 | 3. Wraps indented regions under an \"if True:\" block so the | ||
| 2150 | interpreter evaluates them correctly." | ||
| 2151 | (let ((substring (buffer-substring-no-properties start end)) | ||
| 2152 | (fillstr (make-string (1- (line-number-at-pos start)) ?\n)) | ||
| 2153 | (toplevel-block-p (save-excursion | ||
| 2154 | (goto-char start) | ||
| 2155 | (or (zerop (line-number-at-pos start)) | ||
| 2156 | (progn | ||
| 2157 | (python-util-forward-comment 1) | ||
| 2158 | (zerop (current-indentation))))))) | ||
| 2159 | (with-temp-buffer | ||
| 2160 | (python-mode) | ||
| 2161 | (insert fillstr) | ||
| 2162 | (insert substring) | ||
| 2163 | (goto-char (point-min)) | ||
| 2164 | (when (not toplevel-block-p) | ||
| 2165 | (insert "if True:") | ||
| 2166 | (delete-region (point) (line-end-position))) | ||
| 2167 | (when nomain | ||
| 2168 | (let* ((if-name-main-start-end | ||
| 2169 | (and nomain | ||
| 2170 | (save-excursion | ||
| 2171 | (when (python-nav-if-name-main) | ||
| 2172 | (cons (point) | ||
| 2173 | (progn (python-nav-forward-sexp) | ||
| 2174 | (point))))))) | ||
| 2175 | ;; Oh destructuring bind, how I miss you. | ||
| 2176 | (if-name-main-start (car if-name-main-start-end)) | ||
| 2177 | (if-name-main-end (cdr if-name-main-start-end))) | ||
| 2178 | (when if-name-main-start-end | ||
| 2179 | (goto-char if-name-main-start) | ||
| 2180 | (delete-region if-name-main-start if-name-main-end) | ||
| 2181 | (insert | ||
| 2182 | (make-string | ||
| 2183 | (- (line-number-at-pos if-name-main-end) | ||
| 2184 | (line-number-at-pos if-name-main-start)) ?\n))))) | ||
| 2185 | (buffer-substring-no-properties (point-min) (point-max))))) | ||
| 2186 | |||
| 2122 | (defun python-shell-send-region (start end) | 2187 | (defun python-shell-send-region (start end) |
| 2123 | "Send the region delimited by START and END to inferior Python process." | 2188 | "Send the region delimited by START and END to inferior Python process." |
| 2124 | (interactive "r") | 2189 | (interactive "r") |
| 2125 | (python-shell-send-string | 2190 | (python-shell-send-string |
| 2126 | (concat | 2191 | (python-shell-buffer-substring start end) nil t)) |
| 2127 | (let ((line-num (line-number-at-pos start))) | ||
| 2128 | ;; When sending a region, add blank lines for non sent code so | ||
| 2129 | ;; backtraces remain correct. | ||
| 2130 | (make-string (1- line-num) ?\n)) | ||
| 2131 | (buffer-substring start end)) | ||
| 2132 | nil t)) | ||
| 2133 | 2192 | ||
| 2134 | (defun python-shell-send-buffer (&optional arg) | 2193 | (defun python-shell-send-buffer (&optional arg) |
| 2135 | "Send the entire buffer to inferior Python process. | 2194 | "Send the entire buffer to inferior Python process. |
| @@ -2138,13 +2197,9 @@ by \"if __name__== '__main__':\"" | |||
| 2138 | (interactive "P") | 2197 | (interactive "P") |
| 2139 | (save-restriction | 2198 | (save-restriction |
| 2140 | (widen) | 2199 | (widen) |
| 2141 | (let ((str (buffer-substring (point-min) (point-max)))) | 2200 | (python-shell-send-string |
| 2142 | (and | 2201 | (python-shell-buffer-substring |
| 2143 | (not arg) | 2202 | (point-min) (point-max) (not arg))))) |
| 2144 | (setq str (replace-regexp-in-string | ||
| 2145 | (python-rx if-name-main) | ||
| 2146 | "if __name__ == '__main__ ':" str))) | ||
| 2147 | (python-shell-send-string str)))) | ||
| 2148 | 2203 | ||
| 2149 | (defun python-shell-send-defun (arg) | 2204 | (defun python-shell-send-defun (arg) |
| 2150 | "Send the current defun to inferior Python process. | 2205 | "Send the current defun to inferior Python process. |
| @@ -2271,13 +2326,17 @@ and use the following as the value of this variable: | |||
| 2271 | LINE is used to detect the context on how to complete given | 2326 | LINE is used to detect the context on how to complete given |
| 2272 | INPUT." | 2327 | INPUT." |
| 2273 | (let* ((prompt | 2328 | (let* ((prompt |
| 2274 | ;; Get the last prompt for the inferior process | 2329 | ;; Get last prompt of the inferior process buffer (this |
| 2275 | ;; buffer. This is used for the completion code selection | 2330 | ;; intentionally avoids using `comint-last-prompt' because |
| 2276 | ;; heuristic. | 2331 | ;; of incompatibilities with Emacs 24.x). |
| 2277 | (with-current-buffer (process-buffer process) | 2332 | (with-current-buffer (process-buffer process) |
| 2278 | (buffer-substring-no-properties | 2333 | (save-excursion |
| 2279 | (overlay-start comint-last-prompt-overlay) | 2334 | (buffer-substring-no-properties |
| 2280 | (overlay-end comint-last-prompt-overlay)))) | 2335 | (- (point) (length line)) |
| 2336 | (progn | ||
| 2337 | (re-search-backward "^") | ||
| 2338 | (python-util-forward-comment) | ||
| 2339 | (point)))))) | ||
| 2281 | (completion-context | 2340 | (completion-context |
| 2282 | ;; Check whether a prompt matches a pdb string, an import | 2341 | ;; Check whether a prompt matches a pdb string, an import |
| 2283 | ;; statement or just the standard prompt and use the | 2342 | ;; statement or just the standard prompt and use the |
| @@ -3042,32 +3101,22 @@ It must be a function with two arguments: TYPE and NAME.") | |||
| 3042 | "*class definition*" | 3101 | "*class definition*" |
| 3043 | "*function definition*")) | 3102 | "*function definition*")) |
| 3044 | 3103 | ||
| 3045 | (defun python-imenu--put-parent (type name pos num-children tree &optional root) | 3104 | (defun python-imenu--put-parent (type name pos tree) |
| 3046 | "Add the parent with TYPE, NAME, POS and NUM-CHILDREN to TREE. | 3105 | "Add the parent with TYPE, NAME and POS to TREE." |
| 3047 | Optional Argument ROOT must be non-nil when the node being | ||
| 3048 | processed is the root of the TREE." | ||
| 3049 | (let ((label | 3106 | (let ((label |
| 3050 | (funcall python-imenu-format-item-label-function type name)) | 3107 | (funcall python-imenu-format-item-label-function type name)) |
| 3051 | (jump-label | 3108 | (jump-label |
| 3052 | (funcall python-imenu-format-parent-item-jump-label-function type name))) | 3109 | (funcall python-imenu-format-parent-item-jump-label-function type name))) |
| 3053 | (if root | 3110 | (if (not tree) |
| 3054 | ;; This is the root, everything is a children. | 3111 | (cons label pos) |
| 3055 | (cons label (cons (cons jump-label pos) tree)) | 3112 | (cons label (cons (cons jump-label pos) tree))))) |
| 3056 | ;; This is node a which may contain some children. | ||
| 3057 | (cons | ||
| 3058 | (cons label (cons (cons jump-label pos) | ||
| 3059 | ;; Append all the children | ||
| 3060 | (python-util-popn tree num-children))) | ||
| 3061 | ;; All previous non-children nodes. | ||
| 3062 | (nthcdr num-children tree))))) | ||
| 3063 | 3113 | ||
| 3064 | (defun python-imenu--build-tree (&optional min-indent prev-indent num-children tree) | 3114 | (defun python-imenu--build-tree (&optional min-indent prev-indent tree) |
| 3065 | "Recursively build the tree of nested definitions of a node. | 3115 | "Recursively build the tree of nested definitions of a node. |
| 3066 | Arguments MIN-INDENT PREV-INDENT NUM-CHILDREN and TREE are | 3116 | Arguments MIN-INDENT PREV-INDENT and TREE are internal and should |
| 3067 | internal and should not be passed explicitly unless you know what | 3117 | not be passed explicitly unless you know what you are doing." |
| 3068 | you are doing." | 3118 | (setq min-indent (or min-indent 0) |
| 3069 | (setq num-children (or num-children 0) | 3119 | prev-indent (or prev-indent python-indent-offset)) |
| 3070 | min-indent (or min-indent 0)) | ||
| 3071 | (let* ((pos (python-nav-backward-defun)) | 3120 | (let* ((pos (python-nav-backward-defun)) |
| 3072 | (type) | 3121 | (type) |
| 3073 | (name (when (and pos (looking-at python-nav-beginning-of-defun-regexp)) | 3122 | (name (when (and pos (looking-at python-nav-beginning-of-defun-regexp)) |
| @@ -3076,73 +3125,33 @@ you are doing." | |||
| 3076 | (cadr split)))) | 3125 | (cadr split)))) |
| 3077 | (label (when name | 3126 | (label (when name |
| 3078 | (funcall python-imenu-format-item-label-function type name))) | 3127 | (funcall python-imenu-format-item-label-function type name))) |
| 3079 | (indent (current-indentation))) | 3128 | (indent (current-indentation)) |
| 3129 | (children-indent-limit (+ python-indent-offset min-indent))) | ||
| 3080 | (cond ((not pos) | 3130 | (cond ((not pos) |
| 3081 | ;; No defun found, nothing to add. | 3131 | ;; Nothing found, probably near to bobp. |
| 3082 | tree) | 3132 | nil) |
| 3083 | ((equal indent 0) | 3133 | ((<= indent min-indent) |
| 3084 | (if (> num-children 0) | 3134 | ;; The current indentation points that this is a parent |
| 3085 | ;; Append it as the parent of everything collected to | 3135 | ;; node, add it to the tree and stop recursing. |
| 3086 | ;; this point. | 3136 | (python-imenu--put-parent type name pos tree)) |
| 3087 | (python-imenu--put-parent type name pos num-children tree t) | ||
| 3088 | ;; There are no children, this is a lonely defun. | ||
| 3089 | (cons label pos))) | ||
| 3090 | ((equal min-indent indent) | ||
| 3091 | ;; Stop collecting nodes after moving to a position with | ||
| 3092 | ;; indentation equaling min-indent. This is specially | ||
| 3093 | ;; useful for navigating nested definitions recursively. | ||
| 3094 | (if (> num-children 0) | ||
| 3095 | tree | ||
| 3096 | ;; When there are no children, the collected tree is a | ||
| 3097 | ;; single node intended to be added in the list of defuns | ||
| 3098 | ;; of its parent. | ||
| 3099 | (car tree))) | ||
| 3100 | (t | 3137 | (t |
| 3101 | (python-imenu--build-tree | 3138 | (python-imenu--build-tree |
| 3102 | min-indent | 3139 | min-indent |
| 3103 | indent | 3140 | indent |
| 3104 | ;; Add another children, either when this is the | 3141 | (if (<= indent children-indent-limit) |
| 3105 | ;; first call or when indentation is | 3142 | ;; This lies within the children indent offset range, |
| 3106 | ;; less-or-equal than previous. And do not | 3143 | ;; so it's a normal child of its parent (i.e., not |
| 3107 | ;; discard the number of children, because the | 3144 | ;; a child of a child). |
| 3108 | ;; way code is scanned, all children are | 3145 | (cons (cons label pos) tree) |
| 3109 | ;; collected until a root node yet to be found | 3146 | ;; Oh no, a child of a child?! Fear not, we |
| 3110 | ;; appears. | 3147 | ;; know how to roll. We recursively parse these by |
| 3111 | (if (or (not prev-indent) | 3148 | ;; swapping prev-indent and min-indent plus adding this |
| 3112 | (and | 3149 | ;; newly found item to a fresh subtree. This works, I |
| 3113 | (> indent min-indent) | 3150 | ;; promise. |
| 3114 | (<= indent prev-indent))) | 3151 | (cons |
| 3115 | (1+ num-children) | 3152 | (python-imenu--build-tree |
| 3116 | num-children) | 3153 | prev-indent indent (list (cons label pos))) |
| 3117 | (cond ((not prev-indent) | 3154 | tree))))))) |
| 3118 | ;; First call to the function: append this | ||
| 3119 | ;; defun to the index. | ||
| 3120 | (list (cons label pos))) | ||
| 3121 | ((= indent prev-indent) | ||
| 3122 | ;; Add another defun with the same depth | ||
| 3123 | ;; as the previous. | ||
| 3124 | (cons (cons label pos) tree)) | ||
| 3125 | ((and (< indent prev-indent) | ||
| 3126 | (< 0 num-children)) | ||
| 3127 | ;; There are children to be appended and | ||
| 3128 | ;; the previous defun had more | ||
| 3129 | ;; indentation, the current one must be a | ||
| 3130 | ;; parent. | ||
| 3131 | (python-imenu--put-parent type name pos num-children tree)) | ||
| 3132 | ((> indent prev-indent) | ||
| 3133 | ;; There are children defuns deeper than | ||
| 3134 | ;; current depth. Fear not, we already | ||
| 3135 | ;; know how to treat them. | ||
| 3136 | (cons | ||
| 3137 | (prog1 | ||
| 3138 | (python-imenu--build-tree | ||
| 3139 | prev-indent indent 0 (list (cons label pos))) | ||
| 3140 | ;; Adjustment: after scanning backwards | ||
| 3141 | ;; for all deeper children, we need to | ||
| 3142 | ;; continue our scan for a parent from | ||
| 3143 | ;; the current defun we are looking at. | ||
| 3144 | (python-nav-forward-defun)) | ||
| 3145 | tree)))))))) | ||
| 3146 | 3155 | ||
| 3147 | (defun python-imenu-create-index () | 3156 | (defun python-imenu-create-index () |
| 3148 | "Return tree Imenu alist for the current python buffer. | 3157 | "Return tree Imenu alist for the current python buffer. |