aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el141
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.
1583When \"if __name__ == '__main__':\" is found returns its
1584position, 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.
2137This is a wrapper over `buffer-substring' that takes care of
2138different transformations for the code sent to be evaluated in
2139the 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:
2266LINE is used to detect the context on how to complete given 2321LINE is used to detect the context on how to complete given
2267INPUT." 2322INPUT."
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'.
2604JUSTIFY should be used (if applicable) as in `fill-paragraph'." 2663JUSTIFY 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'.
2674JUSTIFY should be used (if applicable) as in `fill-paragraph'." 2732JUSTIFY 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)