diff options
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 141 |
1 files changed, 99 insertions, 42 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 7004836e69f..5eecc347f03 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))) |
| @@ -225,7 +225,7 @@ | |||
| 225 | ;;;###autoload | 225 | ;;;###autoload |
| 226 | (add-to-list 'auto-mode-alist (cons (purecopy "\\.py\\'") 'python-mode)) | 226 | (add-to-list 'auto-mode-alist (cons (purecopy "\\.py\\'") 'python-mode)) |
| 227 | ;;;###autoload | 227 | ;;;###autoload |
| 228 | (add-to-list 'interpreter-mode-alist (cons (purecopy "python") 'python-mode)) | 228 | (add-to-list 'interpreter-mode-alist (cons (purecopy "\\`python[0-9.]*\\'") 'python-mode)) |
| 229 | 229 | ||
| 230 | (defgroup python nil | 230 | (defgroup python nil |
| 231 | "Python Language's flying circus support for Emacs." | 231 | "Python Language's flying circus support for Emacs." |
| @@ -1327,9 +1327,7 @@ backward to previous statement." | |||
| 1327 | (defun python-nav-beginning-of-block () | 1327 | (defun python-nav-beginning-of-block () |
| 1328 | "Move to start of current block." | 1328 | "Move to start of current block." |
| 1329 | (interactive "^") | 1329 | (interactive "^") |
| 1330 | (let ((starting-pos (point)) | 1330 | (let ((starting-pos (point))) |
| 1331 | (block-regexp (python-rx | ||
| 1332 | line-start (* whitespace) block-start))) | ||
| 1333 | (if (progn | 1331 | (if (progn |
| 1334 | (python-nav-beginning-of-statement) | 1332 | (python-nav-beginning-of-statement) |
| 1335 | (looking-at (python-rx block-start))) | 1333 | (looking-at (python-rx block-start))) |
| @@ -1422,9 +1420,6 @@ backwards." | |||
| 1422 | (let* ((forward-p (if (> dir 0) | 1420 | (let* ((forward-p (if (> dir 0) |
| 1423 | (and (setq dir 1) t) | 1421 | (and (setq dir 1) t) |
| 1424 | (and (setq dir -1) nil))) | 1422 | (and (setq dir -1) nil))) |
| 1425 | (re-search-fn (if forward-p | ||
| 1426 | 're-search-forward | ||
| 1427 | 're-search-backward)) | ||
| 1428 | (context-type (python-syntax-context-type))) | 1423 | (context-type (python-syntax-context-type))) |
| 1429 | (cond | 1424 | (cond |
| 1430 | ((memq context-type '(string comment)) | 1425 | ((memq context-type '(string comment)) |
| @@ -1583,6 +1578,29 @@ This command assumes point is not in a string or comment." | |||
| 1583 | (or arg (setq arg 1)) | 1578 | (or arg (setq arg 1)) |
| 1584 | (python-nav-up-list (- arg))) | 1579 | (python-nav-up-list (- arg))) |
| 1585 | 1580 | ||
| 1581 | (defun python-nav-if-name-main () | ||
| 1582 | "Move point at the beginning the __main__ block. | ||
| 1583 | When \"if __name__ == '__main__':\" is found returns its | ||
| 1584 | position, else returns nil." | ||
| 1585 | (interactive) | ||
| 1586 | (let ((point (point)) | ||
| 1587 | (found (catch 'found | ||
| 1588 | (goto-char (point-min)) | ||
| 1589 | (while (re-search-forward | ||
| 1590 | (python-rx line-start | ||
| 1591 | "if" (+ space) | ||
| 1592 | "__name__" (+ space) | ||
| 1593 | "==" (+ space) | ||
| 1594 | (group-n 1 (or ?\" ?\')) | ||
| 1595 | "__main__" (backref 1) (* space) ":") | ||
| 1596 | nil t) | ||
| 1597 | (when (not (python-syntax-context-type)) | ||
| 1598 | (beginning-of-line) | ||
| 1599 | (throw 'found t)))))) | ||
| 1600 | (if found | ||
| 1601 | (point) | ||
| 1602 | (ignore (goto-char point))))) | ||
| 1603 | |||
| 1586 | 1604 | ||
| 1587 | ;;; Shell integration | 1605 | ;;; Shell integration |
| 1588 | 1606 | ||
| @@ -2114,17 +2132,58 @@ Returns the output. See `python-shell-send-string-no-output'." | |||
| 2114 | (define-obsolete-function-alias | 2132 | (define-obsolete-function-alias |
| 2115 | 'python-send-string 'python-shell-internal-send-string "24.3") | 2133 | 'python-send-string 'python-shell-internal-send-string "24.3") |
| 2116 | 2134 | ||
| 2135 | (defun python-shell-buffer-substring (start end &optional nomain) | ||
| 2136 | "Send buffer substring from START to END formatted for shell. | ||
| 2137 | This is a wrapper over `buffer-substring' that takes care of | ||
| 2138 | different transformations for the code sent to be evaluated in | ||
| 2139 | the python shell: | ||
| 2140 | 1. When Optional Argument NOMAIN is non-nil everything under an | ||
| 2141 | \"if __name__ == '__main__'\" block will be removed. | ||
| 2142 | 2. When a subregion of the buffer is sent, it takes care of | ||
| 2143 | appending extra empty lines so tracebacks are correct. | ||
| 2144 | 3. Wraps indented regions under an \"if True:\" block so the | ||
| 2145 | interpreter evaluates them correctly." | ||
| 2146 | (let ((substring (buffer-substring-no-properties start end)) | ||
| 2147 | (fillstr (make-string (1- (line-number-at-pos start)) ?\n)) | ||
| 2148 | (toplevel-block-p (save-excursion | ||
| 2149 | (goto-char start) | ||
| 2150 | (or (zerop (line-number-at-pos start)) | ||
| 2151 | (progn | ||
| 2152 | (python-util-forward-comment 1) | ||
| 2153 | (zerop (current-indentation))))))) | ||
| 2154 | (with-temp-buffer | ||
| 2155 | (python-mode) | ||
| 2156 | (insert fillstr) | ||
| 2157 | (insert substring) | ||
| 2158 | (goto-char (point-min)) | ||
| 2159 | (when (not toplevel-block-p) | ||
| 2160 | (insert "if True:") | ||
| 2161 | (delete-region (point) (line-end-position))) | ||
| 2162 | (when nomain | ||
| 2163 | (let* ((if-name-main-start-end | ||
| 2164 | (and nomain | ||
| 2165 | (save-excursion | ||
| 2166 | (when (python-nav-if-name-main) | ||
| 2167 | (cons (point) | ||
| 2168 | (progn (python-nav-forward-sexp) | ||
| 2169 | (point))))))) | ||
| 2170 | ;; Oh destructuring bind, how I miss you. | ||
| 2171 | (if-name-main-start (car if-name-main-start-end)) | ||
| 2172 | (if-name-main-end (cdr if-name-main-start-end))) | ||
| 2173 | (when if-name-main-start-end | ||
| 2174 | (goto-char if-name-main-start) | ||
| 2175 | (delete-region if-name-main-start if-name-main-end) | ||
| 2176 | (insert | ||
| 2177 | (make-string | ||
| 2178 | (- (line-number-at-pos if-name-main-end) | ||
| 2179 | (line-number-at-pos if-name-main-start)) ?\n))))) | ||
| 2180 | (buffer-substring-no-properties (point-min) (point-max))))) | ||
| 2181 | |||
| 2117 | (defun python-shell-send-region (start end) | 2182 | (defun python-shell-send-region (start end) |
| 2118 | "Send the region delimited by START and END to inferior Python process." | 2183 | "Send the region delimited by START and END to inferior Python process." |
| 2119 | (interactive "r") | 2184 | (interactive "r") |
| 2120 | (python-shell-send-string | 2185 | (python-shell-send-string |
| 2121 | (concat | 2186 | (python-shell-buffer-substring start end) nil t)) |
| 2122 | (let ((line-num (line-number-at-pos start))) | ||
| 2123 | ;; When sending a region, add blank lines for non sent code so | ||
| 2124 | ;; backtraces remain correct. | ||
| 2125 | (make-string (1- line-num) ?\n)) | ||
| 2126 | (buffer-substring start end)) | ||
| 2127 | nil t)) | ||
| 2128 | 2187 | ||
| 2129 | (defun python-shell-send-buffer (&optional arg) | 2188 | (defun python-shell-send-buffer (&optional arg) |
| 2130 | "Send the entire buffer to inferior Python process. | 2189 | "Send the entire buffer to inferior Python process. |
| @@ -2133,13 +2192,9 @@ by \"if __name__== '__main__':\"" | |||
| 2133 | (interactive "P") | 2192 | (interactive "P") |
| 2134 | (save-restriction | 2193 | (save-restriction |
| 2135 | (widen) | 2194 | (widen) |
| 2136 | (let ((str (buffer-substring (point-min) (point-max)))) | 2195 | (python-shell-send-string |
| 2137 | (and | 2196 | (python-shell-buffer-substring |
| 2138 | (not arg) | 2197 | (point-min) (point-max) (not arg))))) |
| 2139 | (setq str (replace-regexp-in-string | ||
| 2140 | (python-rx if-name-main) | ||
| 2141 | "if __name__ == '__main__ ':" str))) | ||
| 2142 | (python-shell-send-string str)))) | ||
| 2143 | 2198 | ||
| 2144 | (defun python-shell-send-defun (arg) | 2199 | (defun python-shell-send-defun (arg) |
| 2145 | "Send the current defun to inferior Python process. | 2200 | "Send the current defun to inferior Python process. |
| @@ -2266,13 +2321,17 @@ and use the following as the value of this variable: | |||
| 2266 | LINE is used to detect the context on how to complete given | 2321 | LINE is used to detect the context on how to complete given |
| 2267 | INPUT." | 2322 | INPUT." |
| 2268 | (let* ((prompt | 2323 | (let* ((prompt |
| 2269 | ;; Get the last prompt for the inferior process | 2324 | ;; Get last prompt of the inferior process buffer (this |
| 2270 | ;; buffer. This is used for the completion code selection | 2325 | ;; intentionally avoids using `comint-last-prompt' because |
| 2271 | ;; heuristic. | 2326 | ;; of incompatibilities with Emacs 24.x). |
| 2272 | (with-current-buffer (process-buffer process) | 2327 | (with-current-buffer (process-buffer process) |
| 2273 | (buffer-substring-no-properties | 2328 | (save-excursion |
| 2274 | (overlay-start comint-last-prompt-overlay) | 2329 | (buffer-substring-no-properties |
| 2275 | (overlay-end comint-last-prompt-overlay)))) | 2330 | (- (point) (length line)) |
| 2331 | (progn | ||
| 2332 | (re-search-backward "^") | ||
| 2333 | (python-util-forward-comment) | ||
| 2334 | (point)))))) | ||
| 2276 | (completion-context | 2335 | (completion-context |
| 2277 | ;; Check whether a prompt matches a pdb string, an import | 2336 | ;; Check whether a prompt matches a pdb string, an import |
| 2278 | ;; statement or just the standard prompt and use the | 2337 | ;; statement or just the standard prompt and use the |
| @@ -2602,8 +2661,7 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'." | |||
| 2602 | (defun python-fill-string (&optional justify) | 2661 | (defun python-fill-string (&optional justify) |
| 2603 | "String fill function for `python-fill-paragraph'. | 2662 | "String fill function for `python-fill-paragraph'. |
| 2604 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2663 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." |
| 2605 | (let* ((marker (point-marker)) | 2664 | (let* ((str-start-pos |
| 2606 | (str-start-pos | ||
| 2607 | (set-marker | 2665 | (set-marker |
| 2608 | (make-marker) | 2666 | (make-marker) |
| 2609 | (or (python-syntax-context 'string) | 2667 | (or (python-syntax-context 'string) |
| @@ -2669,7 +2727,7 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'." | |||
| 2669 | ;; Again indent only if a newline is added. | 2727 | ;; Again indent only if a newline is added. |
| 2670 | (indent-according-to-mode))))) t) | 2728 | (indent-according-to-mode))))) t) |
| 2671 | 2729 | ||
| 2672 | (defun python-fill-decorator (&optional justify) | 2730 | (defun python-fill-decorator (&optional _justify) |
| 2673 | "Decorator fill function for `python-fill-paragraph'. | 2731 | "Decorator fill function for `python-fill-paragraph'. |
| 2674 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2732 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." |
| 2675 | t) | 2733 | t) |
| @@ -2831,8 +2889,7 @@ The skeleton will be bound to python-skeleton-NAME." | |||
| 2831 | 2889 | ||
| 2832 | (defun python-skeleton-add-menu-items () | 2890 | (defun python-skeleton-add-menu-items () |
| 2833 | "Add menu items to Python->Skeletons menu." | 2891 | "Add menu items to Python->Skeletons menu." |
| 2834 | (let ((skeletons (sort python-skeleton-available 'string<)) | 2892 | (let ((skeletons (sort python-skeleton-available 'string<))) |
| 2835 | (items)) | ||
| 2836 | (dolist (skeleton skeletons) | 2893 | (dolist (skeleton skeletons) |
| 2837 | (easy-menu-add-item | 2894 | (easy-menu-add-item |
| 2838 | nil '("Python" "Skeletons") | 2895 | nil '("Python" "Skeletons") |
| @@ -2920,7 +2977,7 @@ Runs COMMAND, a shell command, as if by `compile'. See | |||
| 2920 | (let ((process-environment (python-shell-calculate-process-environment)) | 2977 | (let ((process-environment (python-shell-calculate-process-environment)) |
| 2921 | (exec-path (python-shell-calculate-exec-path))) | 2978 | (exec-path (python-shell-calculate-exec-path))) |
| 2922 | (compilation-start command nil | 2979 | (compilation-start command nil |
| 2923 | (lambda (mode-name) | 2980 | (lambda (_modename) |
| 2924 | (format python-check-buffer-name command))))) | 2981 | (format python-check-buffer-name command))))) |
| 2925 | 2982 | ||
| 2926 | 2983 | ||
| @@ -3031,7 +3088,7 @@ It must be a function with two arguments: TYPE and NAME.") | |||
| 3031 | "Return imenu label for parent node using TYPE and NAME." | 3088 | "Return imenu label for parent node using TYPE and NAME." |
| 3032 | (format "%s..." (python-imenu-format-item-label type name))) | 3089 | (format "%s..." (python-imenu-format-item-label type name))) |
| 3033 | 3090 | ||
| 3034 | (defun python-imenu-format-parent-item-jump-label (type name) | 3091 | (defun python-imenu-format-parent-item-jump-label (type _name) |
| 3035 | "Return imenu label for parent node jump using TYPE and NAME." | 3092 | "Return imenu label for parent node jump using TYPE and NAME." |
| 3036 | (if (string= type "class") | 3093 | (if (string= type "class") |
| 3037 | "*class definition*" | 3094 | "*class definition*" |
| @@ -3145,7 +3202,7 @@ To this: | |||
| 3145 | (cons name (cdar pos)) | 3202 | (cons name (cdar pos)) |
| 3146 | (python-imenu-create-flat-index (cddr item) name)))))) | 3203 | (python-imenu-create-flat-index (cddr item) name)))))) |
| 3147 | (or alist | 3204 | (or alist |
| 3148 | (let* ((fn (lambda (type name) name)) | 3205 | (let* ((fn (lambda (_type name) name)) |
| 3149 | (python-imenu-format-item-label-function fn) | 3206 | (python-imenu-format-item-label-function fn) |
| 3150 | (python-imenu-format-parent-item-label-function fn) | 3207 | (python-imenu-format-parent-item-label-function fn) |
| 3151 | (python-imenu-format-parent-item-jump-label-function fn)) | 3208 | (python-imenu-format-parent-item-jump-label-function fn)) |
| @@ -3550,7 +3607,7 @@ if that value is non-nil." | |||
| 3550 | 3607 | ||
| 3551 | (add-to-list 'hs-special-modes-alist | 3608 | (add-to-list 'hs-special-modes-alist |
| 3552 | `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#" | 3609 | `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#" |
| 3553 | ,(lambda (arg) | 3610 | ,(lambda (_arg) |
| 3554 | (python-nav-end-of-defun)) nil)) | 3611 | (python-nav-end-of-defun)) nil)) |
| 3555 | 3612 | ||
| 3556 | (set (make-local-variable 'mode-require-final-newline) t) | 3613 | (set (make-local-variable 'mode-require-final-newline) t) |