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.el163
1 files changed, 126 insertions, 37 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 6b0dc954ca7..5bf64c18f99 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -235,6 +235,9 @@
235 (substitute-key-definition 'forward-sentence 235 (substitute-key-definition 'forward-sentence
236 'python-nav-forward-block 236 'python-nav-forward-block
237 map global-map) 237 map global-map)
238 (substitute-key-definition 'backward-up-list
239 'python-nav-backward-up-list
240 map global-map)
238 (define-key map "\C-c\C-j" 'imenu) 241 (define-key map "\C-c\C-j" 'imenu)
239 ;; Indent specific 242 ;; Indent specific
240 (define-key map "\177" 'python-indent-dedent-line-backspace) 243 (define-key map "\177" 'python-indent-dedent-line-backspace)
@@ -337,19 +340,28 @@
337 "==" ">=" "is" "not"))) 340 "==" ">=" "is" "not")))
338 ;; FIXME: Use regexp-opt. 341 ;; FIXME: Use regexp-opt.
339 (assignment-operator . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**=" 342 (assignment-operator . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**="
340 ">>=" "<<=" "&=" "^=" "|=")))) 343 ">>=" "<<=" "&=" "^=" "|=")))
341 "Additional Python specific sexps for `python-rx'")) 344 (string-delimiter . ,(rx (and
342 345 ;; Match even number of backslashes.
343(defmacro python-rx (&rest regexps) 346 (or (not (any ?\\ ?\' ?\")) point
344 "Python mode specialized rx macro. 347 ;; Quotes might be preceded by a escaped quote.
348 (and (or (not (any ?\\)) point) ?\\
349 (* ?\\ ?\\) (any ?\' ?\")))
350 (* ?\\ ?\\)
351 ;; Match single or triple quotes of any kind.
352 (group (or "\"" "\"\"\"" "'" "'''"))))))
353 "Additional Python specific sexps for `python-rx'")
354
355 (defmacro python-rx (&rest regexps)
356 "Python mode specialized rx macro.
345This variant of `rx' supports common python named REGEXPS." 357This variant of `rx' supports common python named REGEXPS."
346 (let ((rx-constituents (append python-rx-constituents rx-constituents))) 358 (let ((rx-constituents (append python-rx-constituents rx-constituents)))
347 (cond ((null regexps) 359 (cond ((null regexps)
348 (error "No regexp")) 360 (error "No regexp"))
349 ((cdr regexps) 361 ((cdr regexps)
350 (rx-to-string `(and ,@regexps) t)) 362 (rx-to-string `(and ,@regexps) t))
351 (t 363 (t
352 (rx-to-string (car regexps) t))))) 364 (rx-to-string (car regexps) t))))))
353 365
354 366
355;;; Font-lock and syntax 367;;; Font-lock and syntax
@@ -498,16 +510,7 @@ The type returned can be `comment', `string' or `paren'."
498 510
499(defconst python-syntax-propertize-function 511(defconst python-syntax-propertize-function
500 (syntax-propertize-rules 512 (syntax-propertize-rules
501 ((rx 513 ((python-rx string-delimiter)
502 (and
503 ;; Match even number of backslashes.
504 (or (not (any ?\\ ?\' ?\")) point
505 ;; Quotes might be preceded by a escaped quote.
506 (and (or (not (any ?\\)) point) ?\\
507 (* ?\\ ?\\) (any ?\' ?\")))
508 (* ?\\ ?\\)
509 ;; Match single or triple quotes of any kind.
510 (group (or "\"" "\"\"\"" "'" "'''"))))
511 (0 (ignore (python-syntax-stringify)))))) 514 (0 (ignore (python-syntax-stringify))))))
512 515
513(defsubst python-syntax-count-quotes (quote-char &optional point limit) 516(defsubst python-syntax-count-quotes (quote-char &optional point limit)
@@ -1409,6 +1412,67 @@ move backward N times."
1409 (python-nav--backward-sexp) 1412 (python-nav--backward-sexp)
1410 (setq arg (1+ arg)))) 1413 (setq arg (1+ arg))))
1411 1414
1415(defun python-nav--up-list (&optional dir)
1416 "Internal implementation of `python-nav-up-list'.
1417DIR is always 1 or -1 and comes sanitized from
1418`python-nav-up-list' calls."
1419 (let ((context (python-syntax-context-type))
1420 (forward-p (> dir 0)))
1421 (cond
1422 ((memq context '(string comment)))
1423 ((eq context 'paren)
1424 (let ((forward-sexp-function))
1425 (up-list dir)))
1426 ((and forward-p (python-info-end-of-block-p))
1427 (let ((parent-end-pos
1428 (save-excursion
1429 (let ((indentation (and
1430 (python-nav-beginning-of-block)
1431 (current-indentation))))
1432 (while (and indentation
1433 (> indentation 0)
1434 (>= (current-indentation) indentation)
1435 (python-nav-backward-block)))
1436 (python-nav-end-of-block)))))
1437 (and (> (or parent-end-pos (point)) (point))
1438 (goto-char parent-end-pos))))
1439 (forward-p (python-nav-end-of-block))
1440 ((and (not forward-p)
1441 (> (current-indentation) 0)
1442 (python-info-beginning-of-block-p))
1443 (let ((prev-block-pos
1444 (save-excursion
1445 (let ((indentation (current-indentation)))
1446 (while (and (python-nav-backward-block)
1447 (> (current-indentation) indentation))))
1448 (point))))
1449 (and (> (point) prev-block-pos)
1450 (goto-char prev-block-pos))))
1451 ((not forward-p) (python-nav-beginning-of-block)))))
1452
1453(defun python-nav-up-list (&optional arg)
1454 "Move forward out of one level of parentheses (or blocks).
1455With ARG, do this that many times.
1456A negative argument means move backward but still to a less deep spot.
1457This command assumes point is not in a string or comment."
1458 (interactive "^p")
1459 (or arg (setq arg 1))
1460 (while (> arg 0)
1461 (python-nav--up-list 1)
1462 (setq arg (1- arg)))
1463 (while (< arg 0)
1464 (python-nav--up-list -1)
1465 (setq arg (1+ arg))))
1466
1467(defun python-nav-backward-up-list (&optional arg)
1468 "Move backward out of one level of parentheses (or blocks).
1469With ARG, do this that many times.
1470A negative argument means move backward but still to a less deep spot.
1471This command assumes point is not in a string or comment."
1472 (interactive "^p")
1473 (or arg (setq arg 1))
1474 (python-nav-up-list (- arg)))
1475
1412 1476
1413;;; Shell integration 1477;;; Shell integration
1414 1478
@@ -1609,6 +1673,20 @@ OUTPUT is a string with the contents of the buffer."
1609 1673
1610(defvar python-shell--parent-buffer nil) 1674(defvar python-shell--parent-buffer nil)
1611 1675
1676(defvar python-shell-output-syntax-table
1677 (let ((table (make-syntax-table python-dotty-syntax-table)))
1678 (modify-syntax-entry ?\' "." table)
1679 (modify-syntax-entry ?\" "." table)
1680 (modify-syntax-entry ?\( "." table)
1681 (modify-syntax-entry ?\[ "." table)
1682 (modify-syntax-entry ?\{ "." table)
1683 (modify-syntax-entry ?\) "." table)
1684 (modify-syntax-entry ?\] "." table)
1685 (modify-syntax-entry ?\} "." table)
1686 table)
1687 "Syntax table for shell output.
1688It makes parens and quotes be treated as punctuation chars.")
1689
1612(define-derived-mode inferior-python-mode comint-mode "Inferior Python" 1690(define-derived-mode inferior-python-mode comint-mode "Inferior Python"
1613 "Major mode for Python inferior process. 1691 "Major mode for Python inferior process.
1614Runs a Python interpreter as a subprocess of Emacs, with Python 1692Runs a Python interpreter as a subprocess of Emacs, with Python
@@ -1637,7 +1715,6 @@ variable.
1637 python-shell-prompt-regexp 1715 python-shell-prompt-regexp
1638 python-shell-prompt-block-regexp 1716 python-shell-prompt-block-regexp
1639 python-shell-prompt-pdb-regexp)) 1717 python-shell-prompt-pdb-regexp))
1640 (set-syntax-table python-mode-syntax-table)
1641 (setq mode-line-process '(":%s")) 1718 (setq mode-line-process '(":%s"))
1642 (make-local-variable 'comint-output-filter-functions) 1719 (make-local-variable 'comint-output-filter-functions)
1643 (add-hook 'comint-output-filter-functions 1720 (add-hook 'comint-output-filter-functions
@@ -1658,10 +1735,21 @@ variable.
1658 (make-local-variable 'python-pdbtrack-tracked-buffer) 1735 (make-local-variable 'python-pdbtrack-tracked-buffer)
1659 (make-local-variable 'python-shell-internal-last-output) 1736 (make-local-variable 'python-shell-internal-last-output)
1660 (when python-shell-enable-font-lock 1737 (when python-shell-enable-font-lock
1738 (set-syntax-table python-mode-syntax-table)
1661 (set (make-local-variable 'font-lock-defaults) 1739 (set (make-local-variable 'font-lock-defaults)
1662 '(python-font-lock-keywords nil nil nil nil)) 1740 '(python-font-lock-keywords nil nil nil nil))
1663 (set (make-local-variable 'syntax-propertize-function) 1741 (set (make-local-variable 'syntax-propertize-function)
1664 python-syntax-propertize-function)) 1742 (syntax-propertize-rules
1743 (comint-prompt-regexp
1744 (0 (ignore
1745 (put-text-property
1746 comint-last-input-start end 'syntax-table
1747 python-shell-output-syntax-table)
1748 (font-lock-unfontify-region comint-last-input-start end))))
1749 ((python-rx string-delimiter)
1750 (0 (ignore
1751 (and (not (eq (get-text-property start 'field) 'output))
1752 (python-syntax-stringify))))))))
1665 (compilation-shell-minor-mode 1)) 1753 (compilation-shell-minor-mode 1))
1666 1754
1667(defun python-shell-make-comint (cmd proc-name &optional pop internal) 1755(defun python-shell-make-comint (cmd proc-name &optional pop internal)
@@ -1842,7 +1930,9 @@ detecting a prompt at the end of the buffer."
1842 python-shell-output-filter-buffer 1930 python-shell-output-filter-buffer
1843 (concat python-shell-output-filter-buffer string)) 1931 (concat python-shell-output-filter-buffer string))
1844 (when (string-match 1932 (when (string-match
1845 (format "\n\\(?:%s\\|%s\\|%s\\)$" 1933 ;; XXX: It seems on OSX an extra carriage return is attached
1934 ;; at the end of output, this handles that too.
1935 (format "\r?\n\\(?:%s\\|%s\\|%s\\)$"
1846 python-shell-prompt-regexp 1936 python-shell-prompt-regexp
1847 python-shell-prompt-block-regexp 1937 python-shell-prompt-block-regexp
1848 python-shell-prompt-pdb-regexp) 1938 python-shell-prompt-pdb-regexp)
@@ -2246,28 +2336,28 @@ inferior python process is updated properly."
2246 2336
2247(defcustom python-fill-comment-function 'python-fill-comment 2337(defcustom python-fill-comment-function 'python-fill-comment
2248 "Function to fill comments. 2338 "Function to fill comments.
2249This is the function used by `python-fill-paragraph-function' to 2339This is the function used by `python-fill-paragraph' to
2250fill comments." 2340fill comments."
2251 :type 'symbol 2341 :type 'symbol
2252 :group 'python) 2342 :group 'python)
2253 2343
2254(defcustom python-fill-string-function 'python-fill-string 2344(defcustom python-fill-string-function 'python-fill-string
2255 "Function to fill strings. 2345 "Function to fill strings.
2256This is the function used by `python-fill-paragraph-function' to 2346This is the function used by `python-fill-paragraph' to
2257fill strings." 2347fill strings."
2258 :type 'symbol 2348 :type 'symbol
2259 :group 'python) 2349 :group 'python)
2260 2350
2261(defcustom python-fill-decorator-function 'python-fill-decorator 2351(defcustom python-fill-decorator-function 'python-fill-decorator
2262 "Function to fill decorators. 2352 "Function to fill decorators.
2263This is the function used by `python-fill-paragraph-function' to 2353This is the function used by `python-fill-paragraph' to
2264fill decorators." 2354fill decorators."
2265 :type 'symbol 2355 :type 'symbol
2266 :group 'python) 2356 :group 'python)
2267 2357
2268(defcustom python-fill-paren-function 'python-fill-paren 2358(defcustom python-fill-paren-function 'python-fill-paren
2269 "Function to fill parens. 2359 "Function to fill parens.
2270This is the function used by `python-fill-paragraph-function' to 2360This is the function used by `python-fill-paragraph' to
2271fill parens." 2361fill parens."
2272 :type 'symbol 2362 :type 'symbol
2273 :group 'python) 2363 :group 'python)
@@ -2344,7 +2434,7 @@ SYMMETRIC:
2344 :safe (lambda (val) 2434 :safe (lambda (val)
2345 (memq val '(django onetwo pep-257 pep-257-nn symmetric nil)))) 2435 (memq val '(django onetwo pep-257 pep-257-nn symmetric nil))))
2346 2436
2347(defun python-fill-paragraph-function (&optional justify) 2437(defun python-fill-paragraph (&optional justify)
2348 "`fill-paragraph-function' handling multi-line strings and possibly comments. 2438 "`fill-paragraph-function' handling multi-line strings and possibly comments.
2349If any of the current line is in or at the end of a multi-line string, 2439If any of the current line is in or at the end of a multi-line string,
2350fill the string or the paragraph of it that point is in, preserving 2440fill the string or the paragraph of it that point is in, preserving
@@ -2363,8 +2453,7 @@ Optional argument JUSTIFY defines if the paragraph should be justified."
2363 (funcall python-fill-string-function justify)) 2453 (funcall python-fill-string-function justify))
2364 ;; Decorators 2454 ;; Decorators
2365 ((equal (char-after (save-excursion 2455 ((equal (char-after (save-excursion
2366 (back-to-indentation) 2456 (python-nav-beginning-of-statement))) ?@)
2367 (point))) ?@)
2368 (funcall python-fill-decorator-function justify)) 2457 (funcall python-fill-decorator-function justify))
2369 ;; Parens 2458 ;; Parens
2370 ((or (python-syntax-context 'paren) 2459 ((or (python-syntax-context 'paren)
@@ -2376,12 +2465,12 @@ Optional argument JUSTIFY defines if the paragraph should be justified."
2376 (t t)))) 2465 (t t))))
2377 2466
2378(defun python-fill-comment (&optional justify) 2467(defun python-fill-comment (&optional justify)
2379 "Comment fill function for `python-fill-paragraph-function'. 2468 "Comment fill function for `python-fill-paragraph'.
2380JUSTIFY should be used (if applicable) as in `fill-paragraph'." 2469JUSTIFY should be used (if applicable) as in `fill-paragraph'."
2381 (fill-comment-paragraph justify)) 2470 (fill-comment-paragraph justify))
2382 2471
2383(defun python-fill-string (&optional justify) 2472(defun python-fill-string (&optional justify)
2384 "String fill function for `python-fill-paragraph-function'. 2473 "String fill function for `python-fill-paragraph'.
2385JUSTIFY should be used (if applicable) as in `fill-paragraph'." 2474JUSTIFY should be used (if applicable) as in `fill-paragraph'."
2386 (let* ((marker (point-marker)) 2475 (let* ((marker (point-marker))
2387 (str-start-pos 2476 (str-start-pos
@@ -2451,12 +2540,12 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'."
2451 (indent-according-to-mode))))) t) 2540 (indent-according-to-mode))))) t)
2452 2541
2453(defun python-fill-decorator (&optional justify) 2542(defun python-fill-decorator (&optional justify)
2454 "Decorator fill function for `python-fill-paragraph-function'. 2543 "Decorator fill function for `python-fill-paragraph'.
2455JUSTIFY should be used (if applicable) as in `fill-paragraph'." 2544JUSTIFY should be used (if applicable) as in `fill-paragraph'."
2456 t) 2545 t)
2457 2546
2458(defun python-fill-paren (&optional justify) 2547(defun python-fill-paren (&optional justify)
2459 "Paren fill function for `python-fill-paragraph-function'. 2548 "Paren fill function for `python-fill-paragraph'.
2460JUSTIFY should be used (if applicable) as in `fill-paragraph'." 2549JUSTIFY should be used (if applicable) as in `fill-paragraph'."
2461 (save-restriction 2550 (save-restriction
2462 (narrow-to-region (progn 2551 (narrow-to-region (progn
@@ -3107,7 +3196,7 @@ if that value is non-nil."
3107 3196
3108 (set (make-local-variable 'paragraph-start) "\\s-*$") 3197 (set (make-local-variable 'paragraph-start) "\\s-*$")
3109 (set (make-local-variable 'fill-paragraph-function) 3198 (set (make-local-variable 'fill-paragraph-function)
3110 'python-fill-paragraph-function) 3199 'python-fill-paragraph)
3111 3200
3112 (set (make-local-variable 'beginning-of-defun-function) 3201 (set (make-local-variable 'beginning-of-defun-function)
3113 #'python-beginning-of-defun-function) 3202 #'python-beginning-of-defun-function)