diff options
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 163 |
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. | ||
| 345 | This variant of `rx' supports common python named REGEXPS." | 357 | This 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'. | ||
| 1417 | DIR 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). | ||
| 1455 | With ARG, do this that many times. | ||
| 1456 | A negative argument means move backward but still to a less deep spot. | ||
| 1457 | This 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). | ||
| 1469 | With ARG, do this that many times. | ||
| 1470 | A negative argument means move backward but still to a less deep spot. | ||
| 1471 | This 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. | ||
| 1688 | It 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. |
| 1614 | Runs a Python interpreter as a subprocess of Emacs, with Python | 1692 | Runs 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. |
| 2249 | This is the function used by `python-fill-paragraph-function' to | 2339 | This is the function used by `python-fill-paragraph' to |
| 2250 | fill comments." | 2340 | fill 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. |
| 2256 | This is the function used by `python-fill-paragraph-function' to | 2346 | This is the function used by `python-fill-paragraph' to |
| 2257 | fill strings." | 2347 | fill 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. |
| 2263 | This is the function used by `python-fill-paragraph-function' to | 2353 | This is the function used by `python-fill-paragraph' to |
| 2264 | fill decorators." | 2354 | fill 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. |
| 2270 | This is the function used by `python-fill-paragraph-function' to | 2360 | This is the function used by `python-fill-paragraph' to |
| 2271 | fill parens." | 2361 | fill 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. |
| 2349 | If any of the current line is in or at the end of a multi-line string, | 2439 | If any of the current line is in or at the end of a multi-line string, |
| 2350 | fill the string or the paragraph of it that point is in, preserving | 2440 | fill 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'. |
| 2380 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2469 | JUSTIFY 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'. |
| 2385 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2474 | JUSTIFY 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'. |
| 2455 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2544 | JUSTIFY 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'. |
| 2460 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2549 | JUSTIFY 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) |