diff options
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 1126 |
1 files changed, 701 insertions, 425 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 601850ed0fb..67388c0339b 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -33,7 +33,7 @@ | |||
| 33 | ;; Implements Syntax highlighting, Indentation, Movement, Shell | 33 | ;; Implements Syntax highlighting, Indentation, Movement, Shell |
| 34 | ;; interaction, Shell completion, Shell virtualenv support, Pdb | 34 | ;; interaction, Shell completion, Shell virtualenv support, Pdb |
| 35 | ;; tracking, Symbol completion, Skeletons, FFAP, Code Check, Eldoc, | 35 | ;; tracking, Symbol completion, Skeletons, FFAP, Code Check, Eldoc, |
| 36 | ;; imenu. | 36 | ;; Imenu. |
| 37 | 37 | ||
| 38 | ;; Syntax highlighting: Fontification of code is provided and supports | 38 | ;; Syntax highlighting: Fontification of code is provided and supports |
| 39 | ;; python's triple quoted strings properly. | 39 | ;; python's triple quoted strings properly. |
| @@ -169,10 +169,12 @@ | |||
| 169 | ;; might guessed you should run `python-shell-send-buffer' from time | 169 | ;; might guessed you should run `python-shell-send-buffer' from time |
| 170 | ;; to time to get better results too. | 170 | ;; to time to get better results too. |
| 171 | 171 | ||
| 172 | ;; imenu: This mode supports imenu in its most basic form, letting it | 172 | ;; Imenu: This mode supports Imenu in its most basic form, letting it |
| 173 | ;; build the necessary alist via `imenu-default-create-index-function' | 173 | ;; build the necessary alist via `imenu-default-create-index-function' |
| 174 | ;; by having set `imenu-extract-index-name-function' to | 174 | ;; by having set `imenu-extract-index-name-function' to |
| 175 | ;; `python-info-current-defun'. | 175 | ;; `python-info-current-defun' and |
| 176 | ;; `imenu-prev-index-position-function' to | ||
| 177 | ;; `python-imenu-prev-index-position'. | ||
| 176 | 178 | ||
| 177 | ;; If you used python-mode.el you probably will miss auto-indentation | 179 | ;; If you used python-mode.el you probably will miss auto-indentation |
| 178 | ;; when inserting newlines. To achieve the same behavior you have | 180 | ;; when inserting newlines. To achieve the same behavior you have |
| @@ -202,13 +204,12 @@ | |||
| 202 | 204 | ||
| 203 | (require 'ansi-color) | 205 | (require 'ansi-color) |
| 204 | (require 'comint) | 206 | (require 'comint) |
| 207 | (eval-when-compile (require 'cl-lib)) | ||
| 205 | 208 | ||
| 206 | (eval-when-compile | 209 | ;; Avoid compiler warnings |
| 207 | (require 'cl) | 210 | (defvar view-return-to-alist) |
| 208 | ;; Avoid compiler warnings | 211 | (defvar compilation-error-regexp-alist) |
| 209 | (defvar view-return-to-alist) | 212 | (defvar outline-heading-end-regexp) |
| 210 | (defvar compilation-error-regexp-alist) | ||
| 211 | (defvar outline-heading-end-regexp)) | ||
| 212 | 213 | ||
| 213 | (autoload 'comint-mode "comint") | 214 | (autoload 'comint-mode "comint") |
| 214 | 215 | ||
| @@ -229,12 +230,9 @@ | |||
| 229 | (defvar python-mode-map | 230 | (defvar python-mode-map |
| 230 | (let ((map (make-sparse-keymap))) | 231 | (let ((map (make-sparse-keymap))) |
| 231 | ;; Movement | 232 | ;; Movement |
| 232 | (substitute-key-definition 'backward-sentence | 233 | (define-key map [remap backward-sentence] 'python-nav-backward-block) |
| 233 | 'python-nav-backward-block | 234 | (define-key map [remap forward-sentence] 'python-nav-forward-block) |
| 234 | map global-map) | 235 | (define-key map [remap backward-up-list] 'python-nav-backward-up-list) |
| 235 | (substitute-key-definition 'forward-sentence | ||
| 236 | 'python-nav-forward-block | ||
| 237 | map global-map) | ||
| 238 | (define-key map "\C-c\C-j" 'imenu) | 236 | (define-key map "\C-c\C-j" 'imenu) |
| 239 | ;; Indent specific | 237 | ;; Indent specific |
| 240 | (define-key map "\177" 'python-indent-dedent-line-backspace) | 238 | (define-key map "\177" 'python-indent-dedent-line-backspace) |
| @@ -337,19 +335,28 @@ | |||
| 337 | "==" ">=" "is" "not"))) | 335 | "==" ">=" "is" "not"))) |
| 338 | ;; FIXME: Use regexp-opt. | 336 | ;; FIXME: Use regexp-opt. |
| 339 | (assignment-operator . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**=" | 337 | (assignment-operator . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**=" |
| 340 | ">>=" "<<=" "&=" "^=" "|=")))) | 338 | ">>=" "<<=" "&=" "^=" "|="))) |
| 341 | "Additional Python specific sexps for `python-rx'")) | 339 | (string-delimiter . ,(rx (and |
| 342 | 340 | ;; Match even number of backslashes. | |
| 343 | (defmacro python-rx (&rest regexps) | 341 | (or (not (any ?\\ ?\' ?\")) point |
| 344 | "Python mode specialized rx macro. | 342 | ;; Quotes might be preceded by a escaped quote. |
| 343 | (and (or (not (any ?\\)) point) ?\\ | ||
| 344 | (* ?\\ ?\\) (any ?\' ?\"))) | ||
| 345 | (* ?\\ ?\\) | ||
| 346 | ;; Match single or triple quotes of any kind. | ||
| 347 | (group (or "\"" "\"\"\"" "'" "'''")))))) | ||
| 348 | "Additional Python specific sexps for `python-rx'") | ||
| 349 | |||
| 350 | (defmacro python-rx (&rest regexps) | ||
| 351 | "Python mode specialized rx macro. | ||
| 345 | This variant of `rx' supports common python named REGEXPS." | 352 | This variant of `rx' supports common python named REGEXPS." |
| 346 | (let ((rx-constituents (append python-rx-constituents rx-constituents))) | 353 | (let ((rx-constituents (append python-rx-constituents rx-constituents))) |
| 347 | (cond ((null regexps) | 354 | (cond ((null regexps) |
| 348 | (error "No regexp")) | 355 | (error "No regexp")) |
| 349 | ((cdr regexps) | 356 | ((cdr regexps) |
| 350 | (rx-to-string `(and ,@regexps) t)) | 357 | (rx-to-string `(and ,@regexps) t)) |
| 351 | (t | 358 | (t |
| 352 | (rx-to-string (car regexps) t))))) | 359 | (rx-to-string (car regexps) t)))))) |
| 353 | 360 | ||
| 354 | 361 | ||
| 355 | ;;; Font-lock and syntax | 362 | ;;; Font-lock and syntax |
| @@ -358,12 +365,24 @@ This variant of `rx' supports common python named REGEXPS." | |||
| 358 | "Return non-nil if point is on TYPE using SYNTAX-PPSS. | 365 | "Return non-nil if point is on TYPE using SYNTAX-PPSS. |
| 359 | TYPE can be `comment', `string' or `paren'. It returns the start | 366 | TYPE can be `comment', `string' or `paren'. It returns the start |
| 360 | character address of the specified TYPE." | 367 | character address of the specified TYPE." |
| 368 | (declare (compiler-macro | ||
| 369 | (lambda (form) | ||
| 370 | (pcase type | ||
| 371 | (`'comment | ||
| 372 | `(let ((ppss (or ,syntax-ppss (syntax-ppss)))) | ||
| 373 | (and (nth 4 ppss) (nth 8 ppss)))) | ||
| 374 | (`'string | ||
| 375 | `(let ((ppss (or ,syntax-ppss (syntax-ppss)))) | ||
| 376 | (and (nth 3 ppss) (nth 8 ppss)))) | ||
| 377 | (`'paren | ||
| 378 | `(nth 1 (or ,syntax-ppss (syntax-ppss)))) | ||
| 379 | (_ form))))) | ||
| 361 | (let ((ppss (or syntax-ppss (syntax-ppss)))) | 380 | (let ((ppss (or syntax-ppss (syntax-ppss)))) |
| 362 | (case type | 381 | (pcase type |
| 363 | (comment (and (nth 4 ppss) (nth 8 ppss))) | 382 | (`comment (and (nth 4 ppss) (nth 8 ppss))) |
| 364 | (string (and (not (nth 4 ppss)) (nth 8 ppss))) | 383 | (`string (and (nth 3 ppss) (nth 8 ppss))) |
| 365 | (paren (nth 1 ppss)) | 384 | (`paren (nth 1 ppss)) |
| 366 | (t nil)))) | 385 | (_ nil)))) |
| 367 | 386 | ||
| 368 | (defun python-syntax-context-type (&optional syntax-ppss) | 387 | (defun python-syntax-context-type (&optional syntax-ppss) |
| 369 | "Return the context type using SYNTAX-PPSS. | 388 | "Return the context type using SYNTAX-PPSS. |
| @@ -475,8 +494,8 @@ The type returned can be `comment', `string' or `paren'." | |||
| 475 | (when (re-search-forward re limit t) | 494 | (when (re-search-forward re limit t) |
| 476 | (while (and (python-syntax-context 'paren) | 495 | (while (and (python-syntax-context 'paren) |
| 477 | (re-search-forward re limit t))) | 496 | (re-search-forward re limit t))) |
| 478 | (if (and (not (python-syntax-context 'paren)) | 497 | (if (not (or (python-syntax-context 'paren) |
| 479 | (not (equal (char-after (point-marker)) ?=))) | 498 | (equal (char-after (point-marker)) ?=))) |
| 480 | t | 499 | t |
| 481 | (set-match-data nil))))) | 500 | (set-match-data nil))))) |
| 482 | (1 font-lock-variable-name-face nil nil)) | 501 | (1 font-lock-variable-name-face nil nil)) |
| @@ -497,52 +516,54 @@ The type returned can be `comment', `string' or `paren'." | |||
| 497 | (1 font-lock-variable-name-face nil nil)))) | 516 | (1 font-lock-variable-name-face nil nil)))) |
| 498 | 517 | ||
| 499 | (defconst python-syntax-propertize-function | 518 | (defconst python-syntax-propertize-function |
| 500 | ;; Make outer chars of matching triple-quote sequences into generic | ||
| 501 | ;; string delimiters. Fixme: Is there a better way? | ||
| 502 | ;; First avoid a sequence preceded by an odd number of backslashes. | ||
| 503 | (syntax-propertize-rules | 519 | (syntax-propertize-rules |
| 504 | (;; ¡Backrefs don't work in syntax-propertize-rules! | 520 | ((python-rx string-delimiter) |
| 505 | (concat "\\(?:\\([RUru]\\)[Rr]?\\|^\\|[^\\]\\(?:\\\\.\\)*\\)" ;Prefix. | 521 | (0 (ignore (python-syntax-stringify)))))) |
| 506 | "\\(?:\\('\\)'\\('\\)\\|\\(?2:\"\\)\"\\(?3:\"\\)\\)") | 522 | |
| 507 | (3 (ignore (python-quote-syntax)))))) | 523 | (defsubst python-syntax-count-quotes (quote-char &optional point limit) |
| 508 | 524 | "Count number of quotes around point (max is 3). | |
| 509 | (defun python-quote-syntax () | 525 | QUOTE-CHAR is the quote char to count. Optional argument POINT is |
| 510 | "Put `syntax-table' property correctly on triple quote. | 526 | the point where scan starts (defaults to current point) and LIMIT |
| 511 | Used for syntactic keywords. N is the match number (1, 2 or 3)." | 527 | is used to limit the scan." |
| 512 | ;; Given a triple quote, we have to check the context to know | 528 | (let ((i 0)) |
| 513 | ;; whether this is an opening or closing triple or whether it's | 529 | (while (and (< i 3) |
| 514 | ;; quoted anyhow, and should be ignored. (For that we need to do | 530 | (or (not limit) (< (+ point i) limit)) |
| 515 | ;; the same job as `syntax-ppss' to be correct and it seems to be OK | 531 | (eq (char-after (+ point i)) quote-char)) |
| 516 | ;; to use it here despite initial worries.) We also have to sort | 532 | (cl-incf i)) |
| 517 | ;; out a possible prefix -- well, we don't _have_ to, but I think it | 533 | i)) |
| 518 | ;; should be treated as part of the string. | 534 | |
| 519 | 535 | (defun python-syntax-stringify () | |
| 520 | ;; Test cases: | 536 | "Put `syntax-table' property correctly on single/triple quotes." |
| 521 | ;; ur"""ar""" x='"' # """ | 537 | (let* ((num-quotes (length (match-string-no-properties 1))) |
| 522 | ;; x = ''' """ ' a | 538 | (ppss (prog2 |
| 523 | ;; ''' | 539 | (backward-char num-quotes) |
| 524 | ;; x '"""' x """ \"""" x | 540 | (syntax-ppss) |
| 525 | (save-excursion | 541 | (forward-char num-quotes))) |
| 526 | (goto-char (match-beginning 0)) | 542 | (string-start (and (not (nth 4 ppss)) (nth 8 ppss))) |
| 527 | (let ((syntax (save-match-data (syntax-ppss)))) | 543 | (quote-starting-pos (- (point) num-quotes)) |
| 528 | (cond | 544 | (quote-ending-pos (point)) |
| 529 | ((eq t (nth 3 syntax)) ; after unclosed fence | 545 | (num-closing-quotes |
| 530 | ;; Consider property for the last char if in a fenced string. | 546 | (and string-start |
| 531 | (goto-char (nth 8 syntax)) ; fence position | 547 | (python-syntax-count-quotes |
| 532 | (skip-chars-forward "uUrR") ; skip any prefix | 548 | (char-before) string-start quote-starting-pos)))) |
| 533 | ;; Is it a matching sequence? | 549 | (cond ((and string-start (= num-closing-quotes 0)) |
| 534 | (if (eq (char-after) (char-after (match-beginning 2))) | 550 | ;; This set of quotes doesn't match the string starting |
| 535 | (put-text-property (match-beginning 3) (match-end 3) | 551 | ;; kind. Do nothing. |
| 536 | 'syntax-table (string-to-syntax "|")))) | 552 | nil) |
| 537 | ((match-end 1) | 553 | ((not string-start) |
| 538 | ;; Consider property for initial char, accounting for prefixes. | 554 | ;; This set of quotes delimit the start of a string. |
| 539 | (put-text-property (match-beginning 1) (match-end 1) | 555 | (put-text-property quote-starting-pos (1+ quote-starting-pos) |
| 540 | 'syntax-table (string-to-syntax "|"))) | 556 | 'syntax-table (string-to-syntax "|"))) |
| 541 | (t | 557 | ((= num-quotes num-closing-quotes) |
| 542 | ;; Consider property for initial char, accounting for prefixes. | 558 | ;; This set of quotes delimit the end of a string. |
| 543 | (put-text-property (match-beginning 2) (match-end 2) | 559 | (put-text-property (1- quote-ending-pos) quote-ending-pos |
| 544 | 'syntax-table (string-to-syntax "|")))) | 560 | 'syntax-table (string-to-syntax "|"))) |
| 545 | ))) | 561 | ((> num-quotes num-closing-quotes) |
| 562 | ;; This may only happen whenever a triple quote is closing | ||
| 563 | ;; a single quoted string. Add string delimiter syntax to | ||
| 564 | ;; all three quotes. | ||
| 565 | (put-text-property quote-starting-pos quote-ending-pos | ||
| 566 | 'syntax-table (string-to-syntax "|")))))) | ||
| 546 | 567 | ||
| 547 | (defvar python-mode-syntax-table | 568 | (defvar python-mode-syntax-table |
| 548 | (let ((table (make-syntax-table))) | 569 | (let ((table (make-syntax-table))) |
| @@ -637,7 +658,7 @@ These make `python-indent-calculate-indentation' subtract the value of | |||
| 637 | (python-util-forward-comment) | 658 | (python-util-forward-comment) |
| 638 | (current-indentation)))) | 659 | (current-indentation)))) |
| 639 | (if indentation | 660 | (if indentation |
| 640 | (setq python-indent-offset indentation) | 661 | (set (make-local-variable 'python-indent-offset) indentation) |
| 641 | (message "Can't guess python-indent-offset, using defaults: %s" | 662 | (message "Can't guess python-indent-offset, using defaults: %s" |
| 642 | python-indent-offset))))))) | 663 | python-indent-offset))))))) |
| 643 | 664 | ||
| @@ -665,12 +686,12 @@ START is the buffer position where the sexp starts." | |||
| 665 | (goto-char (line-beginning-position)) | 686 | (goto-char (line-beginning-position)) |
| 666 | (bobp)) | 687 | (bobp)) |
| 667 | 'no-indent) | 688 | 'no-indent) |
| 668 | ;; Inside a paren | ||
| 669 | ((setq start (python-syntax-context 'paren ppss)) | ||
| 670 | 'inside-paren) | ||
| 671 | ;; Inside string | 689 | ;; Inside string |
| 672 | ((setq start (python-syntax-context 'string ppss)) | 690 | ((setq start (python-syntax-context 'string ppss)) |
| 673 | 'inside-string) | 691 | 'inside-string) |
| 692 | ;; Inside a paren | ||
| 693 | ((setq start (python-syntax-context 'paren ppss)) | ||
| 694 | 'inside-paren) | ||
| 674 | ;; After backslash | 695 | ;; After backslash |
| 675 | ((setq start (when (not (or (python-syntax-context 'string ppss) | 696 | ((setq start (when (not (or (python-syntax-context 'string ppss) |
| 676 | (python-syntax-context 'comment ppss))) | 697 | (python-syntax-context 'comment ppss))) |
| @@ -699,7 +720,7 @@ START is the buffer position where the sexp starts." | |||
| 699 | ;; After normal line | 720 | ;; After normal line |
| 700 | ((setq start (save-excursion | 721 | ((setq start (save-excursion |
| 701 | (back-to-indentation) | 722 | (back-to-indentation) |
| 702 | (python-util-forward-comment -1) | 723 | (skip-chars-backward (rx (or whitespace ?\n))) |
| 703 | (python-nav-beginning-of-statement) | 724 | (python-nav-beginning-of-statement) |
| 704 | (point-marker))) | 725 | (point-marker))) |
| 705 | 'after-line) | 726 | 'after-line) |
| @@ -715,17 +736,17 @@ START is the buffer position where the sexp starts." | |||
| 715 | (save-restriction | 736 | (save-restriction |
| 716 | (widen) | 737 | (widen) |
| 717 | (save-excursion | 738 | (save-excursion |
| 718 | (case context-status | 739 | (pcase context-status |
| 719 | ('no-indent 0) | 740 | (`no-indent 0) |
| 720 | ;; When point is after beginning of block just add one level | 741 | ;; When point is after beginning of block just add one level |
| 721 | ;; of indentation relative to the context-start | 742 | ;; of indentation relative to the context-start |
| 722 | ('after-beginning-of-block | 743 | (`after-beginning-of-block |
| 723 | (goto-char context-start) | 744 | (goto-char context-start) |
| 724 | (+ (current-indentation) python-indent-offset)) | 745 | (+ (current-indentation) python-indent-offset)) |
| 725 | ;; When after a simple line just use previous line | 746 | ;; When after a simple line just use previous line |
| 726 | ;; indentation, in the case current line starts with a | 747 | ;; indentation, in the case current line starts with a |
| 727 | ;; `python-indent-dedenters' de-indent one level. | 748 | ;; `python-indent-dedenters' de-indent one level. |
| 728 | ('after-line | 749 | (`after-line |
| 729 | (- | 750 | (- |
| 730 | (save-excursion | 751 | (save-excursion |
| 731 | (goto-char context-start) | 752 | (goto-char context-start) |
| @@ -738,11 +759,11 @@ START is the buffer position where the sexp starts." | |||
| 738 | ;; When inside of a string, do nothing. just use the current | 759 | ;; When inside of a string, do nothing. just use the current |
| 739 | ;; indentation. XXX: perhaps it would be a good idea to | 760 | ;; indentation. XXX: perhaps it would be a good idea to |
| 740 | ;; invoke standard text indentation here | 761 | ;; invoke standard text indentation here |
| 741 | ('inside-string | 762 | (`inside-string |
| 742 | (goto-char context-start) | 763 | (goto-char context-start) |
| 743 | (current-indentation)) | 764 | (current-indentation)) |
| 744 | ;; After backslash we have several possibilities. | 765 | ;; After backslash we have several possibilities. |
| 745 | ('after-backslash | 766 | (`after-backslash |
| 746 | (cond | 767 | (cond |
| 747 | ;; Check if current line is a dot continuation. For this | 768 | ;; Check if current line is a dot continuation. For this |
| 748 | ;; the current line must start with a dot and previous | 769 | ;; the current line must start with a dot and previous |
| @@ -808,7 +829,7 @@ START is the buffer position where the sexp starts." | |||
| 808 | (+ (current-indentation) python-indent-offset))))) | 829 | (+ (current-indentation) python-indent-offset))))) |
| 809 | ;; When inside a paren there's a need to handle nesting | 830 | ;; When inside a paren there's a need to handle nesting |
| 810 | ;; correctly | 831 | ;; correctly |
| 811 | ('inside-paren | 832 | (`inside-paren |
| 812 | (cond | 833 | (cond |
| 813 | ;; If current line closes the outermost open paren use the | 834 | ;; If current line closes the outermost open paren use the |
| 814 | ;; current indentation of the context-start line. | 835 | ;; current indentation of the context-start line. |
| @@ -897,16 +918,27 @@ possible indentation levels and saves it in the variable | |||
| 897 | `python-indent-levels'. Afterwards it sets the variable | 918 | `python-indent-levels'. Afterwards it sets the variable |
| 898 | `python-indent-current-level' correctly so offset is equal | 919 | `python-indent-current-level' correctly so offset is equal |
| 899 | to (`nth' `python-indent-current-level' `python-indent-levels')" | 920 | to (`nth' `python-indent-current-level' `python-indent-levels')" |
| 900 | (if (or (and (eq this-command 'indent-for-tab-command) | 921 | (or |
| 901 | (eq last-command this-command)) | 922 | (and (or (and (eq this-command 'indent-for-tab-command) |
| 902 | force-toggle) | 923 | (eq last-command this-command)) |
| 903 | (if (not (equal python-indent-levels '(0))) | 924 | force-toggle) |
| 904 | (python-indent-toggle-levels) | 925 | (not (equal python-indent-levels '(0))) |
| 905 | (python-indent-calculate-levels)) | 926 | (or (python-indent-toggle-levels) t)) |
| 906 | (python-indent-calculate-levels)) | 927 | (python-indent-calculate-levels)) |
| 907 | (beginning-of-line) | 928 | (let* ((starting-pos (point-marker)) |
| 908 | (delete-horizontal-space) | 929 | (indent-ending-position |
| 909 | (indent-to (nth python-indent-current-level python-indent-levels)) | 930 | (+ (line-beginning-position) (current-indentation))) |
| 931 | (follow-indentation-p | ||
| 932 | (or (bolp) | ||
| 933 | (and (<= (line-beginning-position) starting-pos) | ||
| 934 | (>= indent-ending-position starting-pos)))) | ||
| 935 | (next-indent (nth python-indent-current-level python-indent-levels))) | ||
| 936 | (unless (= next-indent (current-indentation)) | ||
| 937 | (beginning-of-line) | ||
| 938 | (delete-horizontal-space) | ||
| 939 | (indent-to next-indent) | ||
| 940 | (goto-char starting-pos)) | ||
| 941 | (and follow-indentation-p (back-to-indentation))) | ||
| 910 | (python-info-closing-block-message)) | 942 | (python-info-closing-block-message)) |
| 911 | 943 | ||
| 912 | (defun python-indent-line-function () | 944 | (defun python-indent-line-function () |
| @@ -951,7 +983,16 @@ Called from a program, START and END specify the region to indent." | |||
| 951 | (back-to-indentation) | 983 | (back-to-indentation) |
| 952 | (setq word (current-word)) | 984 | (setq word (current-word)) |
| 953 | (forward-line 1) | 985 | (forward-line 1) |
| 954 | (when word | 986 | (when (and word |
| 987 | ;; Don't mess with strings, unless it's the | ||
| 988 | ;; enclosing set of quotes. | ||
| 989 | (or (not (python-syntax-context 'string)) | ||
| 990 | (eq | ||
| 991 | (syntax-after | ||
| 992 | (+ (1- (point)) | ||
| 993 | (current-indentation) | ||
| 994 | (python-syntax-count-quotes (char-after) (point)))) | ||
| 995 | (string-to-syntax "|")))) | ||
| 955 | (beginning-of-line) | 996 | (beginning-of-line) |
| 956 | (delete-horizontal-space) | 997 | (delete-horizontal-space) |
| 957 | (indent-to (python-indent-calculate-indentation))))) | 998 | (indent-to (python-indent-calculate-indentation))))) |
| @@ -1046,12 +1087,9 @@ automatically if needed." | |||
| 1046 | The name of the defun should be grouped so it can be retrieved | 1087 | The name of the defun should be grouped so it can be retrieved |
| 1047 | via `match-string'.") | 1088 | via `match-string'.") |
| 1048 | 1089 | ||
| 1049 | (defun python-nav-beginning-of-defun (&optional arg) | 1090 | (defun python-nav--beginning-of-defun (&optional arg) |
| 1050 | "Move point to `beginning-of-defun'. | 1091 | "Internal implementation of `python-nav-beginning-of-defun'. |
| 1051 | With positive ARG move search backwards. With negative do the | 1092 | With positive ARG search backwards, else search forwards." |
| 1052 | same but forward. When ARG is nil or 0 defaults to 1. This is | ||
| 1053 | the main part of `python-beginning-of-defun-function'. Return | ||
| 1054 | non-nil if point is moved to `beginning-of-defun'." | ||
| 1055 | (when (or (null arg) (= arg 0)) (setq arg 1)) | 1093 | (when (or (null arg) (= arg 0)) (setq arg 1)) |
| 1056 | (let* ((re-search-fn (if (> arg 0) | 1094 | (let* ((re-search-fn (if (> arg 0) |
| 1057 | #'re-search-backward | 1095 | #'re-search-backward |
| @@ -1059,6 +1097,15 @@ non-nil if point is moved to `beginning-of-defun'." | |||
| 1059 | (line-beg-pos (line-beginning-position)) | 1097 | (line-beg-pos (line-beginning-position)) |
| 1060 | (line-content-start (+ line-beg-pos (current-indentation))) | 1098 | (line-content-start (+ line-beg-pos (current-indentation))) |
| 1061 | (pos (point-marker)) | 1099 | (pos (point-marker)) |
| 1100 | (beg-indentation | ||
| 1101 | (and (> arg 0) | ||
| 1102 | (save-excursion | ||
| 1103 | (while (and | ||
| 1104 | (not (python-info-looking-at-beginning-of-defun)) | ||
| 1105 | (python-nav-backward-block))) | ||
| 1106 | (or (and (python-info-looking-at-beginning-of-defun) | ||
| 1107 | (+ (current-indentation) python-indent-offset)) | ||
| 1108 | 0)))) | ||
| 1062 | (found | 1109 | (found |
| 1063 | (progn | 1110 | (progn |
| 1064 | (when (and (< arg 0) | 1111 | (when (and (< arg 0) |
| @@ -1066,7 +1113,12 @@ non-nil if point is moved to `beginning-of-defun'." | |||
| 1066 | (end-of-line 1)) | 1113 | (end-of-line 1)) |
| 1067 | (while (and (funcall re-search-fn | 1114 | (while (and (funcall re-search-fn |
| 1068 | python-nav-beginning-of-defun-regexp nil t) | 1115 | python-nav-beginning-of-defun-regexp nil t) |
| 1069 | (python-syntax-context-type))) | 1116 | (or (python-syntax-context-type) |
| 1117 | ;; Handle nested defuns when moving | ||
| 1118 | ;; backwards by checking indentation. | ||
| 1119 | (and (> arg 0) | ||
| 1120 | (not (= (current-indentation) 0)) | ||
| 1121 | (>= (current-indentation) beg-indentation))))) | ||
| 1070 | (and (python-info-looking-at-beginning-of-defun) | 1122 | (and (python-info-looking-at-beginning-of-defun) |
| 1071 | (or (not (= (line-number-at-pos pos) | 1123 | (or (not (= (line-number-at-pos pos) |
| 1072 | (line-number-at-pos))) | 1124 | (line-number-at-pos))) |
| @@ -1077,55 +1129,43 @@ non-nil if point is moved to `beginning-of-defun'." | |||
| 1077 | (or (beginning-of-line 1) t) | 1129 | (or (beginning-of-line 1) t) |
| 1078 | (and (goto-char pos) nil)))) | 1130 | (and (goto-char pos) nil)))) |
| 1079 | 1131 | ||
| 1080 | (defun python-beginning-of-defun-function (&optional arg) | 1132 | (defun python-nav-beginning-of-defun (&optional arg) |
| 1081 | "Move point to the beginning of def or class. | 1133 | "Move point to `beginning-of-defun'. |
| 1082 | With positive ARG move that number of functions backwards. With | 1134 | With positive ARG search backwards else search forward. When ARG |
| 1083 | negative do the same but forward. When ARG is nil or 0 defaults | 1135 | is nil or 0 defaults to 1. When searching backwards nested |
| 1084 | to 1. Return non-nil if point is moved to `beginning-of-defun'." | 1136 | defuns are handled with care depending on current point |
| 1137 | position. Return non-nil if point is moved to | ||
| 1138 | `beginning-of-defun'." | ||
| 1085 | (when (or (null arg) (= arg 0)) (setq arg 1)) | 1139 | (when (or (null arg) (= arg 0)) (setq arg 1)) |
| 1086 | (let ((found)) | 1140 | (let ((found)) |
| 1087 | (cond ((and (eq this-command 'mark-defun) | 1141 | (cond ((and (eq this-command 'mark-defun) |
| 1088 | (python-info-looking-at-beginning-of-defun))) | 1142 | (python-info-looking-at-beginning-of-defun))) |
| 1089 | (t | 1143 | (t |
| 1090 | (dotimes (i (if (> arg 0) arg (- arg))) | 1144 | (dotimes (i (if (> arg 0) arg (- arg))) |
| 1091 | (when (and (python-nav-beginning-of-defun arg) | 1145 | (when (and (python-nav--beginning-of-defun arg) |
| 1092 | (not found)) | 1146 | (not found)) |
| 1093 | (setq found t))))) | 1147 | (setq found t))))) |
| 1094 | found)) | 1148 | found)) |
| 1095 | 1149 | ||
| 1096 | (defun python-end-of-defun-function () | 1150 | (defun python-nav-end-of-defun () |
| 1097 | "Move point to the end of def or class. | 1151 | "Move point to the end of def or class. |
| 1098 | Returns nil if point is not in a def or class." | 1152 | Returns nil if point is not in a def or class." |
| 1099 | (interactive) | 1153 | (interactive) |
| 1100 | (let ((beg-defun-indent)) | 1154 | (let ((beg-defun-indent) |
| 1155 | (beg-pos (point))) | ||
| 1101 | (when (or (python-info-looking-at-beginning-of-defun) | 1156 | (when (or (python-info-looking-at-beginning-of-defun) |
| 1102 | (python-beginning-of-defun-function 1) | 1157 | (python-nav-beginning-of-defun 1) |
| 1103 | (python-beginning-of-defun-function -1)) | 1158 | (python-nav-beginning-of-defun -1)) |
| 1104 | (setq beg-defun-indent (current-indentation)) | 1159 | (setq beg-defun-indent (current-indentation)) |
| 1160 | (while (progn | ||
| 1161 | (python-nav-end-of-statement) | ||
| 1162 | (python-util-forward-comment 1) | ||
| 1163 | (and (> (current-indentation) beg-defun-indent) | ||
| 1164 | (not (eobp))))) | ||
| 1165 | (python-util-forward-comment -1) | ||
| 1105 | (forward-line 1) | 1166 | (forward-line 1) |
| 1106 | ;; Go as forward as possible | 1167 | ;; Ensure point moves forward. |
| 1107 | (while (and (or | 1168 | (and (> beg-pos (point)) (goto-char beg-pos))))) |
| 1108 | (python-nav-beginning-of-defun -1) | ||
| 1109 | (and (goto-char (point-max)) nil)) | ||
| 1110 | (> (current-indentation) beg-defun-indent))) | ||
| 1111 | (beginning-of-line 1) | ||
| 1112 | ;; Go as backwards as possible | ||
| 1113 | (while (and (forward-line -1) | ||
| 1114 | (not (bobp)) | ||
| 1115 | (or (not (current-word)) | ||
| 1116 | (equal (char-after (+ (point) (current-indentation))) ?#) | ||
| 1117 | (<= (current-indentation) beg-defun-indent) | ||
| 1118 | (looking-at (python-rx decorator)) | ||
| 1119 | (python-syntax-context-type)))) | ||
| 1120 | (forward-line 1) | ||
| 1121 | ;; If point falls inside a paren or string context the point is | ||
| 1122 | ;; forwarded at the end of it (or end of buffer if its not closed) | ||
| 1123 | (let ((context-type (python-syntax-context-type))) | ||
| 1124 | (when (memq context-type '(paren string)) | ||
| 1125 | ;; Slow but safe. | ||
| 1126 | (while (and (not (eobp)) | ||
| 1127 | (python-syntax-context-type)) | ||
| 1128 | (forward-line 1))))))) | ||
| 1129 | 1169 | ||
| 1130 | (defun python-nav-beginning-of-statement () | 1170 | (defun python-nav-beginning-of-statement () |
| 1131 | "Move to start of current statement." | 1171 | "Move to start of current statement." |
| @@ -1138,7 +1178,8 @@ Returns nil if point is not in a def or class." | |||
| 1138 | (python-info-line-ends-backslash-p)) | 1178 | (python-info-line-ends-backslash-p)) |
| 1139 | (python-syntax-context 'string) | 1179 | (python-syntax-context 'string) |
| 1140 | (python-syntax-context 'paren)) | 1180 | (python-syntax-context 'paren)) |
| 1141 | (forward-line -1))))) | 1181 | (forward-line -1)))) |
| 1182 | (point-marker)) | ||
| 1142 | 1183 | ||
| 1143 | (defun python-nav-end-of-statement () | 1184 | (defun python-nav-end-of-statement () |
| 1144 | "Move to end of current statement." | 1185 | "Move to end of current statement." |
| @@ -1149,7 +1190,8 @@ Returns nil if point is not in a def or class." | |||
| 1149 | (python-info-line-ends-backslash-p) | 1190 | (python-info-line-ends-backslash-p) |
| 1150 | (python-syntax-context 'string) | 1191 | (python-syntax-context 'string) |
| 1151 | (python-syntax-context 'paren)) | 1192 | (python-syntax-context 'paren)) |
| 1152 | (forward-line 1))))) | 1193 | (forward-line 1)))) |
| 1194 | (point-marker)) | ||
| 1153 | 1195 | ||
| 1154 | (defun python-nav-backward-statement (&optional arg) | 1196 | (defun python-nav-backward-statement (&optional arg) |
| 1155 | "Move backward to previous statement. | 1197 | "Move backward to previous statement. |
| @@ -1264,151 +1306,104 @@ When ARG > 0 move forward, else if ARG is < 0." | |||
| 1264 | (while (and (funcall search-fn paren-regexp nil t) | 1306 | (while (and (funcall search-fn paren-regexp nil t) |
| 1265 | (python-syntax-context 'paren))))))) | 1307 | (python-syntax-context 'paren))))))) |
| 1266 | 1308 | ||
| 1267 | (defun python-nav--forward-sexp () | 1309 | (defun python-nav--forward-sexp (&optional dir) |
| 1268 | "Move to forward sexp." | 1310 | "Move to forward sexp. |
| 1269 | (case (python-syntax-context-type) | 1311 | With positive Optional argument DIR direction move forward, else |
| 1270 | (string | 1312 | backwards." |
| 1271 | ;; Inside of a string, get out of it. | 1313 | (setq dir (or dir 1)) |
| 1272 | (while (and (re-search-forward "[\"']" nil t) | 1314 | (unless (= dir 0) |
| 1273 | (python-syntax-context 'string)))) | 1315 | (let* ((forward-p (if (> dir 0) |
| 1274 | (comment | 1316 | (and (setq dir 1) t) |
| 1275 | ;; Inside of a comment, just move forward. | 1317 | (and (setq dir -1) nil))) |
| 1276 | (python-util-forward-comment)) | 1318 | (re-search-fn (if forward-p |
| 1277 | (paren | 1319 | 're-search-forward |
| 1278 | (python-nav-lisp-forward-sexp-safe 1)) | 1320 | 're-search-backward)) |
| 1279 | (t | 1321 | (context-type (python-syntax-context-type))) |
| 1280 | (if (and (not (eobp)) | 1322 | (cond |
| 1281 | (= (syntax-class (syntax-after (point))) 4)) | 1323 | ((eq context-type 'string) |
| 1282 | ;; Looking an open-paren | 1324 | ;; Inside of a string, get out of it. |
| 1283 | (python-nav-lisp-forward-sexp-safe 1) | 1325 | (while (and (funcall re-search-fn "[\"']" nil t) |
| 1284 | (let ((block-starting-pos | 1326 | (python-syntax-context 'string)))) |
| 1285 | (save-excursion (python-nav-beginning-of-block))) | 1327 | ((eq context-type 'comment) |
| 1286 | (block-ending-pos | 1328 | ;; Inside of a comment, just move forward. |
| 1287 | (save-excursion (python-nav-end-of-block))) | 1329 | (python-util-forward-comment dir)) |
| 1288 | (next-block-starting-pos | 1330 | ((or (eq context-type 'paren) |
| 1289 | (save-excursion (python-nav-forward-block)))) | 1331 | (and forward-p (looking-at (python-rx open-paren))) |
| 1290 | (cond | 1332 | (and (not forward-p) |
| 1291 | ((not block-starting-pos) | 1333 | (eq (syntax-class (syntax-after (1- (point)))) |
| 1292 | ;; Not inside a block, move to closest one. | 1334 | (car (string-to-syntax ")"))))) |
| 1293 | (and next-block-starting-pos | 1335 | ;; Inside a paren or looking at it, lisp knows what to do. |
| 1294 | (goto-char next-block-starting-pos))) | 1336 | (python-nav-lisp-forward-sexp-safe dir)) |
| 1295 | ((= (point) block-starting-pos) | 1337 | (t |
| 1296 | ;; Point is at beginning of block | 1338 | ;; This part handles the lispy feel of |
| 1297 | (if (and next-block-starting-pos | 1339 | ;; `python-nav-forward-sexp'. Knowing everything about the |
| 1298 | (< next-block-starting-pos block-ending-pos)) | 1340 | ;; current context and the context of the next sexp tries to |
| 1299 | ;; Beginning of next block is closer than current's | 1341 | ;; follow the lisp sexp motion commands in a symmetric manner. |
| 1300 | ;; end, move to it. | 1342 | (let* ((context |
| 1301 | (goto-char next-block-starting-pos) | 1343 | (cond |
| 1302 | (goto-char block-ending-pos))) | 1344 | ((python-info-beginning-of-block-p) 'block-start) |
| 1303 | ((= block-ending-pos (point)) | 1345 | ((python-info-end-of-block-p) 'block-end) |
| 1304 | ;; Point is at end of current block | 1346 | ((python-info-beginning-of-statement-p) 'statement-start) |
| 1305 | (let ((parent-block-end-pos | 1347 | ((python-info-end-of-statement-p) 'statement-end))) |
| 1306 | (save-excursion | 1348 | (next-sexp-pos |
| 1307 | (python-util-forward-comment) | 1349 | (save-excursion |
| 1308 | (python-nav-beginning-of-block) | 1350 | (python-nav-lisp-forward-sexp-safe dir) |
| 1309 | (python-nav-end-of-block)))) | 1351 | (point))) |
| 1310 | (if (and parent-block-end-pos | 1352 | (next-sexp-context |
| 1311 | (or (not next-block-starting-pos) | 1353 | (save-excursion |
| 1312 | (> next-block-starting-pos parent-block-end-pos))) | 1354 | (goto-char next-sexp-pos) |
| 1313 | ;; If the parent block ends before next block | 1355 | (cond |
| 1314 | ;; starts move to it. | 1356 | ((python-info-beginning-of-block-p) 'block-start) |
| 1315 | (goto-char parent-block-end-pos) | 1357 | ((python-info-end-of-block-p) 'block-end) |
| 1316 | (and next-block-starting-pos | 1358 | ((python-info-beginning-of-statement-p) 'statement-start) |
| 1317 | (goto-char next-block-starting-pos))))) | 1359 | ((python-info-end-of-statement-p) 'statement-end) |
| 1318 | (t (python-nav-end-of-block)))))))) | 1360 | ((python-info-statement-starts-block-p) 'starts-block) |
| 1361 | ((python-info-statement-ends-block-p) 'ends-block))))) | ||
| 1362 | (if forward-p | ||
| 1363 | (cond ((and (not (eobp)) | ||
| 1364 | (python-info-current-line-empty-p)) | ||
| 1365 | (python-util-forward-comment dir) | ||
| 1366 | (python-nav--forward-sexp dir)) | ||
| 1367 | ((eq context 'block-start) | ||
| 1368 | (python-nav-end-of-block)) | ||
| 1369 | ((eq context 'statement-start) | ||
| 1370 | (python-nav-end-of-statement)) | ||
| 1371 | ((and (memq context '(statement-end block-end)) | ||
| 1372 | (eq next-sexp-context 'ends-block)) | ||
| 1373 | (goto-char next-sexp-pos) | ||
| 1374 | (python-nav-end-of-block)) | ||
| 1375 | ((and (memq context '(statement-end block-end)) | ||
| 1376 | (eq next-sexp-context 'starts-block)) | ||
| 1377 | (goto-char next-sexp-pos) | ||
| 1378 | (python-nav-end-of-block)) | ||
| 1379 | ((memq context '(statement-end block-end)) | ||
| 1380 | (goto-char next-sexp-pos) | ||
| 1381 | (python-nav-end-of-statement)) | ||
| 1382 | (t (goto-char next-sexp-pos))) | ||
| 1383 | (cond ((and (not (bobp)) | ||
| 1384 | (python-info-current-line-empty-p)) | ||
| 1385 | (python-util-forward-comment dir) | ||
| 1386 | (python-nav--forward-sexp dir)) | ||
| 1387 | ((eq context 'block-end) | ||
| 1388 | (python-nav-beginning-of-block)) | ||
| 1389 | ((eq context 'statement-end) | ||
| 1390 | (python-nav-beginning-of-statement)) | ||
| 1391 | ((and (memq context '(statement-start block-start)) | ||
| 1392 | (eq next-sexp-context 'starts-block)) | ||
| 1393 | (goto-char next-sexp-pos) | ||
| 1394 | (python-nav-beginning-of-block)) | ||
| 1395 | ((and (memq context '(statement-start block-start)) | ||
| 1396 | (eq next-sexp-context 'ends-block)) | ||
| 1397 | (goto-char next-sexp-pos) | ||
| 1398 | (python-nav-beginning-of-block)) | ||
| 1399 | ((memq context '(statement-start block-start)) | ||
| 1400 | (goto-char next-sexp-pos) | ||
| 1401 | (python-nav-beginning-of-statement)) | ||
| 1402 | (t (goto-char next-sexp-pos)))))))))) | ||
| 1319 | 1403 | ||
| 1320 | (defun python-nav--backward-sexp () | 1404 | (defun python-nav--backward-sexp () |
| 1321 | "Move to backward sexp." | 1405 | "Move to backward sexp." |
| 1322 | (case (python-syntax-context-type) | 1406 | (python-nav--forward-sexp -1)) |
| 1323 | (string | ||
| 1324 | ;; Inside of a string, get out of it. | ||
| 1325 | (while (and (re-search-backward "[\"']" nil t) | ||
| 1326 | (python-syntax-context 'string)))) | ||
| 1327 | (comment | ||
| 1328 | ;; Inside of a comment, just move backward. | ||
| 1329 | (python-util-forward-comment -1)) | ||
| 1330 | (paren | ||
| 1331 | ;; Handle parens like we are lisp. | ||
| 1332 | (python-nav-lisp-forward-sexp-safe -1)) | ||
| 1333 | (t | ||
| 1334 | (let* ((block-starting-pos | ||
| 1335 | (save-excursion (python-nav-beginning-of-block))) | ||
| 1336 | (block-ending-pos | ||
| 1337 | (save-excursion (python-nav-end-of-block))) | ||
| 1338 | (prev-block-ending-pos | ||
| 1339 | (save-excursion (when (python-nav-backward-block) | ||
| 1340 | (python-nav-end-of-block)))) | ||
| 1341 | (prev-block-parent-ending-pos | ||
| 1342 | (save-excursion | ||
| 1343 | (when prev-block-ending-pos | ||
| 1344 | (goto-char prev-block-ending-pos) | ||
| 1345 | (python-util-forward-comment) | ||
| 1346 | (python-nav-beginning-of-block) | ||
| 1347 | (python-nav-end-of-block))))) | ||
| 1348 | (if (and (not (bobp)) | ||
| 1349 | (= (syntax-class (syntax-after (1- (point)))) 5)) | ||
| 1350 | ;; Char before point is a paren closing char, handle it | ||
| 1351 | ;; like we are lisp. | ||
| 1352 | (python-nav-lisp-forward-sexp-safe -1) | ||
| 1353 | (cond | ||
| 1354 | ((not block-ending-pos) | ||
| 1355 | ;; Not in and ending pos, move to end of previous block. | ||
| 1356 | (and (python-nav-backward-block) | ||
| 1357 | (python-nav-end-of-block))) | ||
| 1358 | ((= (point) block-ending-pos) | ||
| 1359 | ;; In ending pos, we need to search backwards for the | ||
| 1360 | ;; closest point looking the list of candidates from here. | ||
| 1361 | (let ((candidates)) | ||
| 1362 | (dolist (name | ||
| 1363 | '(prev-block-parent-ending-pos | ||
| 1364 | prev-block-ending-pos | ||
| 1365 | block-ending-pos | ||
| 1366 | block-starting-pos)) | ||
| 1367 | (when (and (symbol-value name) | ||
| 1368 | (< (symbol-value name) (point))) | ||
| 1369 | (add-to-list 'candidates (symbol-value name)))) | ||
| 1370 | (goto-char (apply 'max candidates)))) | ||
| 1371 | ((> (point) block-ending-pos) | ||
| 1372 | ;; After an ending position, move to it. | ||
| 1373 | (goto-char block-ending-pos)) | ||
| 1374 | ((= (point) block-starting-pos) | ||
| 1375 | ;; On a block starting position. | ||
| 1376 | (if (not (> (point) (or prev-block-ending-pos (point)))) | ||
| 1377 | ;; Point is after the end position of the block that | ||
| 1378 | ;; wraps the current one, just move a block backward. | ||
| 1379 | (python-nav-backward-block) | ||
| 1380 | ;; If we got here we are facing a case like this one: | ||
| 1381 | ;; | ||
| 1382 | ;; try: | ||
| 1383 | ;; return here() | ||
| 1384 | ;; except Exception as e: | ||
| 1385 | ;; | ||
| 1386 | ;; Where point is on the "except" and must move to the | ||
| 1387 | ;; end of "here()". | ||
| 1388 | (goto-char prev-block-ending-pos) | ||
| 1389 | (let ((parent-block-ending-pos | ||
| 1390 | (save-excursion | ||
| 1391 | (python-nav-forward-sexp) | ||
| 1392 | (and (not (looking-at (python-rx block-start))) | ||
| 1393 | (point))))) | ||
| 1394 | (when (and parent-block-ending-pos | ||
| 1395 | (> parent-block-ending-pos prev-block-ending-pos)) | ||
| 1396 | ;; If we got here we are facing a case like this one: | ||
| 1397 | ;; | ||
| 1398 | ;; except ImportError: | ||
| 1399 | ;; if predicate(): | ||
| 1400 | ;; processing() | ||
| 1401 | ;; here() | ||
| 1402 | ;; except AttributeError: | ||
| 1403 | ;; | ||
| 1404 | ;; Where point is on the "except" and must move to | ||
| 1405 | ;; the end of "here()". Without this extra step we'd | ||
| 1406 | ;; just get to the end of processing(). | ||
| 1407 | (goto-char parent-block-ending-pos))))) | ||
| 1408 | (t | ||
| 1409 | (if (and prev-block-ending-pos (< prev-block-ending-pos (point))) | ||
| 1410 | (goto-char prev-block-ending-pos) | ||
| 1411 | (python-nav-beginning-of-block))))))))) | ||
| 1412 | 1407 | ||
| 1413 | (defun python-nav-forward-sexp (&optional arg) | 1408 | (defun python-nav-forward-sexp (&optional arg) |
| 1414 | "Move forward across one block of code. | 1409 | "Move forward across one block of code. |
| @@ -1423,6 +1418,67 @@ move backward N times." | |||
| 1423 | (python-nav--backward-sexp) | 1418 | (python-nav--backward-sexp) |
| 1424 | (setq arg (1+ arg)))) | 1419 | (setq arg (1+ arg)))) |
| 1425 | 1420 | ||
| 1421 | (defun python-nav--up-list (&optional dir) | ||
| 1422 | "Internal implementation of `python-nav-up-list'. | ||
| 1423 | DIR is always 1 or -1 and comes sanitized from | ||
| 1424 | `python-nav-up-list' calls." | ||
| 1425 | (let ((context (python-syntax-context-type)) | ||
| 1426 | (forward-p (> dir 0))) | ||
| 1427 | (cond | ||
| 1428 | ((memq context '(string comment))) | ||
| 1429 | ((eq context 'paren) | ||
| 1430 | (let ((forward-sexp-function)) | ||
| 1431 | (up-list dir))) | ||
| 1432 | ((and forward-p (python-info-end-of-block-p)) | ||
| 1433 | (let ((parent-end-pos | ||
| 1434 | (save-excursion | ||
| 1435 | (let ((indentation (and | ||
| 1436 | (python-nav-beginning-of-block) | ||
| 1437 | (current-indentation)))) | ||
| 1438 | (while (and indentation | ||
| 1439 | (> indentation 0) | ||
| 1440 | (>= (current-indentation) indentation) | ||
| 1441 | (python-nav-backward-block))) | ||
| 1442 | (python-nav-end-of-block))))) | ||
| 1443 | (and (> (or parent-end-pos (point)) (point)) | ||
| 1444 | (goto-char parent-end-pos)))) | ||
| 1445 | (forward-p (python-nav-end-of-block)) | ||
| 1446 | ((and (not forward-p) | ||
| 1447 | (> (current-indentation) 0) | ||
| 1448 | (python-info-beginning-of-block-p)) | ||
| 1449 | (let ((prev-block-pos | ||
| 1450 | (save-excursion | ||
| 1451 | (let ((indentation (current-indentation))) | ||
| 1452 | (while (and (python-nav-backward-block) | ||
| 1453 | (>= (current-indentation) indentation)))) | ||
| 1454 | (point)))) | ||
| 1455 | (and (> (point) prev-block-pos) | ||
| 1456 | (goto-char prev-block-pos)))) | ||
| 1457 | ((not forward-p) (python-nav-beginning-of-block))))) | ||
| 1458 | |||
| 1459 | (defun python-nav-up-list (&optional arg) | ||
| 1460 | "Move forward out of one level of parentheses (or blocks). | ||
| 1461 | With ARG, do this that many times. | ||
| 1462 | A negative argument means move backward but still to a less deep spot. | ||
| 1463 | This command assumes point is not in a string or comment." | ||
| 1464 | (interactive "^p") | ||
| 1465 | (or arg (setq arg 1)) | ||
| 1466 | (while (> arg 0) | ||
| 1467 | (python-nav--up-list 1) | ||
| 1468 | (setq arg (1- arg))) | ||
| 1469 | (while (< arg 0) | ||
| 1470 | (python-nav--up-list -1) | ||
| 1471 | (setq arg (1+ arg)))) | ||
| 1472 | |||
| 1473 | (defun python-nav-backward-up-list (&optional arg) | ||
| 1474 | "Move backward out of one level of parentheses (or blocks). | ||
| 1475 | With ARG, do this that many times. | ||
| 1476 | A negative argument means move backward but still to a less deep spot. | ||
| 1477 | This command assumes point is not in a string or comment." | ||
| 1478 | (interactive "^p") | ||
| 1479 | (or arg (setq arg 1)) | ||
| 1480 | (python-nav-up-list (- arg))) | ||
| 1481 | |||
| 1426 | 1482 | ||
| 1427 | ;;; Shell integration | 1483 | ;;; Shell integration |
| 1428 | 1484 | ||
| @@ -1621,6 +1677,22 @@ uniqueness for different types of configurations." | |||
| 1621 | OUTPUT is a string with the contents of the buffer." | 1677 | OUTPUT is a string with the contents of the buffer." |
| 1622 | (ansi-color-filter-apply output)) | 1678 | (ansi-color-filter-apply output)) |
| 1623 | 1679 | ||
| 1680 | (defvar python-shell--parent-buffer nil) | ||
| 1681 | |||
| 1682 | (defvar python-shell-output-syntax-table | ||
| 1683 | (let ((table (make-syntax-table python-dotty-syntax-table))) | ||
| 1684 | (modify-syntax-entry ?\' "." table) | ||
| 1685 | (modify-syntax-entry ?\" "." table) | ||
| 1686 | (modify-syntax-entry ?\( "." table) | ||
| 1687 | (modify-syntax-entry ?\[ "." table) | ||
| 1688 | (modify-syntax-entry ?\{ "." table) | ||
| 1689 | (modify-syntax-entry ?\) "." table) | ||
| 1690 | (modify-syntax-entry ?\] "." table) | ||
| 1691 | (modify-syntax-entry ?\} "." table) | ||
| 1692 | table) | ||
| 1693 | "Syntax table for shell output. | ||
| 1694 | It makes parens and quotes be treated as punctuation chars.") | ||
| 1695 | |||
| 1624 | (define-derived-mode inferior-python-mode comint-mode "Inferior Python" | 1696 | (define-derived-mode inferior-python-mode comint-mode "Inferior Python" |
| 1625 | "Major mode for Python inferior process. | 1697 | "Major mode for Python inferior process. |
| 1626 | Runs a Python interpreter as a subprocess of Emacs, with Python | 1698 | Runs a Python interpreter as a subprocess of Emacs, with Python |
| @@ -1643,12 +1715,13 @@ initialization of the interpreter via `python-shell-setup-codes' | |||
| 1643 | variable. | 1715 | variable. |
| 1644 | 1716 | ||
| 1645 | \(Type \\[describe-mode] in the process buffer for a list of commands.)" | 1717 | \(Type \\[describe-mode] in the process buffer for a list of commands.)" |
| 1646 | (set-syntax-table python-mode-syntax-table) | 1718 | (and python-shell--parent-buffer |
| 1647 | (setq mode-line-process '(":%s")) | 1719 | (python-util-clone-local-variables python-shell--parent-buffer)) |
| 1648 | (setq comint-prompt-regexp (format "^\\(?:%s\\|%s\\|%s\\)" | 1720 | (setq comint-prompt-regexp (format "^\\(?:%s\\|%s\\|%s\\)" |
| 1649 | python-shell-prompt-regexp | 1721 | python-shell-prompt-regexp |
| 1650 | python-shell-prompt-block-regexp | 1722 | python-shell-prompt-block-regexp |
| 1651 | python-shell-prompt-pdb-regexp)) | 1723 | python-shell-prompt-pdb-regexp)) |
| 1724 | (setq mode-line-process '(":%s")) | ||
| 1652 | (make-local-variable 'comint-output-filter-functions) | 1725 | (make-local-variable 'comint-output-filter-functions) |
| 1653 | (add-hook 'comint-output-filter-functions | 1726 | (add-hook 'comint-output-filter-functions |
| 1654 | 'python-comint-output-filter-function) | 1727 | 'python-comint-output-filter-function) |
| @@ -1668,10 +1741,28 @@ variable. | |||
| 1668 | (make-local-variable 'python-pdbtrack-tracked-buffer) | 1741 | (make-local-variable 'python-pdbtrack-tracked-buffer) |
| 1669 | (make-local-variable 'python-shell-internal-last-output) | 1742 | (make-local-variable 'python-shell-internal-last-output) |
| 1670 | (when python-shell-enable-font-lock | 1743 | (when python-shell-enable-font-lock |
| 1744 | (set-syntax-table python-mode-syntax-table) | ||
| 1671 | (set (make-local-variable 'font-lock-defaults) | 1745 | (set (make-local-variable 'font-lock-defaults) |
| 1672 | '(python-font-lock-keywords nil nil nil nil)) | 1746 | '(python-font-lock-keywords nil nil nil nil)) |
| 1673 | (set (make-local-variable 'syntax-propertize-function) | 1747 | (set (make-local-variable 'syntax-propertize-function) |
| 1674 | python-syntax-propertize-function)) | 1748 | (eval |
| 1749 | ;; XXX: Unfortunately eval is needed here to make use of the | ||
| 1750 | ;; dynamic value of `comint-prompt-regexp'. | ||
| 1751 | `(syntax-propertize-rules | ||
| 1752 | (,comint-prompt-regexp | ||
| 1753 | (0 (ignore | ||
| 1754 | (put-text-property | ||
| 1755 | comint-last-input-start end 'syntax-table | ||
| 1756 | python-shell-output-syntax-table) | ||
| 1757 | ;; XXX: This might look weird, but it is the easiest | ||
| 1758 | ;; way to ensure font lock gets cleaned up before the | ||
| 1759 | ;; current prompt, which is needed for unclosed | ||
| 1760 | ;; strings to not mess up with current input. | ||
| 1761 | (font-lock-unfontify-region comint-last-input-start end)))) | ||
| 1762 | (,(python-rx string-delimiter) | ||
| 1763 | (0 (ignore | ||
| 1764 | (and (not (eq (get-text-property start 'field) 'output)) | ||
| 1765 | (python-syntax-stringify))))))))) | ||
| 1675 | (compilation-shell-minor-mode 1)) | 1766 | (compilation-shell-minor-mode 1)) |
| 1676 | 1767 | ||
| 1677 | (defun python-shell-make-comint (cmd proc-name &optional pop internal) | 1768 | (defun python-shell-make-comint (cmd proc-name &optional pop internal) |
| @@ -1694,11 +1785,10 @@ killed." | |||
| 1694 | (let* ((cmdlist (split-string-and-unquote cmd)) | 1785 | (let* ((cmdlist (split-string-and-unquote cmd)) |
| 1695 | (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name | 1786 | (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name |
| 1696 | (car cmdlist) nil (cdr cmdlist))) | 1787 | (car cmdlist) nil (cdr cmdlist))) |
| 1697 | (current-buffer (current-buffer)) | 1788 | (python-shell--parent-buffer (current-buffer)) |
| 1698 | (process (get-buffer-process buffer))) | 1789 | (process (get-buffer-process buffer))) |
| 1699 | (with-current-buffer buffer | 1790 | (with-current-buffer buffer |
| 1700 | (inferior-python-mode) | 1791 | (inferior-python-mode)) |
| 1701 | (python-util-clone-local-variables current-buffer)) | ||
| 1702 | (accept-process-output process) | 1792 | (accept-process-output process) |
| 1703 | (and pop (pop-to-buffer buffer t)) | 1793 | (and pop (pop-to-buffer buffer t)) |
| 1704 | (and internal (set-process-query-on-exit-flag process nil)))) | 1794 | (and internal (set-process-query-on-exit-flag process nil)))) |
| @@ -1824,7 +1914,11 @@ When MSG is non-nil messages the first line of STRING." | |||
| 1824 | (lines (split-string string "\n" t))) | 1914 | (lines (split-string string "\n" t))) |
| 1825 | (and msg (message "Sent: %s..." (nth 0 lines))) | 1915 | (and msg (message "Sent: %s..." (nth 0 lines))) |
| 1826 | (if (> (length lines) 1) | 1916 | (if (> (length lines) 1) |
| 1827 | (let* ((temp-file-name (make-temp-file "py")) | 1917 | (let* ((temporary-file-directory |
| 1918 | (if (file-remote-p default-directory) | ||
| 1919 | (concat (file-remote-p default-directory) "/tmp") | ||
| 1920 | temporary-file-directory)) | ||
| 1921 | (temp-file-name (make-temp-file "py")) | ||
| 1828 | (file-name (or (buffer-file-name) temp-file-name))) | 1922 | (file-name (or (buffer-file-name) temp-file-name))) |
| 1829 | (with-temp-file temp-file-name | 1923 | (with-temp-file temp-file-name |
| 1830 | (insert string) | 1924 | (insert string) |
| @@ -1835,31 +1929,62 @@ When MSG is non-nil messages the first line of STRING." | |||
| 1835 | (string-match "\n[ \t].*\n?$" string)) | 1929 | (string-match "\n[ \t].*\n?$" string)) |
| 1836 | (comint-send-string process "\n"))))) | 1930 | (comint-send-string process "\n"))))) |
| 1837 | 1931 | ||
| 1932 | (defvar python-shell-output-filter-in-progress nil) | ||
| 1933 | (defvar python-shell-output-filter-buffer nil) | ||
| 1934 | |||
| 1935 | (defun python-shell-output-filter (string) | ||
| 1936 | "Filter used in `python-shell-send-string-no-output' to grab output. | ||
| 1937 | STRING is the output received to this point from the process. | ||
| 1938 | This filter saves received output from the process in | ||
| 1939 | `python-shell-output-filter-buffer' and stops receiving it after | ||
| 1940 | detecting a prompt at the end of the buffer." | ||
| 1941 | (setq | ||
| 1942 | string (ansi-color-filter-apply string) | ||
| 1943 | python-shell-output-filter-buffer | ||
| 1944 | (concat python-shell-output-filter-buffer string)) | ||
| 1945 | (when (string-match | ||
| 1946 | ;; XXX: It seems on OSX an extra carriage return is attached | ||
| 1947 | ;; at the end of output, this handles that too. | ||
| 1948 | (format "\r?\n\\(?:%s\\|%s\\|%s\\)$" | ||
| 1949 | python-shell-prompt-regexp | ||
| 1950 | python-shell-prompt-block-regexp | ||
| 1951 | python-shell-prompt-pdb-regexp) | ||
| 1952 | python-shell-output-filter-buffer) | ||
| 1953 | ;; Output ends when `python-shell-output-filter-buffer' contains | ||
| 1954 | ;; the prompt attached at the end of it. | ||
| 1955 | (setq python-shell-output-filter-in-progress nil | ||
| 1956 | python-shell-output-filter-buffer | ||
| 1957 | (substring python-shell-output-filter-buffer | ||
| 1958 | 0 (match-beginning 0))) | ||
| 1959 | (when (and (> (length python-shell-prompt-output-regexp) 0) | ||
| 1960 | (string-match (concat "^" python-shell-prompt-output-regexp) | ||
| 1961 | python-shell-output-filter-buffer)) | ||
| 1962 | ;; Some shells, like iPython might append a prompt before the | ||
| 1963 | ;; output, clean that. | ||
| 1964 | (setq python-shell-output-filter-buffer | ||
| 1965 | (substring python-shell-output-filter-buffer (match-end 0))))) | ||
| 1966 | "") | ||
| 1967 | |||
| 1838 | (defun python-shell-send-string-no-output (string &optional process msg) | 1968 | (defun python-shell-send-string-no-output (string &optional process msg) |
| 1839 | "Send STRING to PROCESS and inhibit output. | 1969 | "Send STRING to PROCESS and inhibit output. |
| 1840 | When MSG is non-nil messages the first line of STRING. Return | 1970 | When MSG is non-nil messages the first line of STRING. Return |
| 1841 | the output." | 1971 | the output." |
| 1842 | (let* ((output-buffer "") | 1972 | (let ((process (or process (python-shell-get-or-create-process))) |
| 1843 | (process (or process (python-shell-get-or-create-process))) | 1973 | (comint-preoutput-filter-functions |
| 1844 | (comint-preoutput-filter-functions | 1974 | '(python-shell-output-filter)) |
| 1845 | (append comint-preoutput-filter-functions | 1975 | (python-shell-output-filter-in-progress t) |
| 1846 | '(ansi-color-filter-apply | 1976 | (inhibit-quit t)) |
| 1847 | (lambda (string) | ||
| 1848 | (setq output-buffer (concat output-buffer string)) | ||
| 1849 | "")))) | ||
| 1850 | (inhibit-quit t)) | ||
| 1851 | (or | 1977 | (or |
| 1852 | (with-local-quit | 1978 | (with-local-quit |
| 1853 | (python-shell-send-string string process msg) | 1979 | (python-shell-send-string string process msg) |
| 1854 | (accept-process-output process) | 1980 | (while python-shell-output-filter-in-progress |
| 1855 | (replace-regexp-in-string | 1981 | ;; `python-shell-output-filter' takes care of setting |
| 1856 | (if (> (length python-shell-prompt-output-regexp) 0) | 1982 | ;; `python-shell-output-filter-in-progress' to NIL after it |
| 1857 | (format "\n*%s$\\|^%s\\|\n$" | 1983 | ;; detects end of output. |
| 1858 | python-shell-prompt-regexp | 1984 | (accept-process-output process)) |
| 1859 | (or python-shell-prompt-output-regexp "")) | 1985 | (prog1 |
| 1860 | (format "\n*$\\|^%s\\|\n$" | 1986 | python-shell-output-filter-buffer |
| 1861 | python-shell-prompt-regexp)) | 1987 | (setq python-shell-output-filter-buffer nil))) |
| 1862 | "" output-buffer)) | ||
| 1863 | (with-current-buffer (process-buffer process) | 1988 | (with-current-buffer (process-buffer process) |
| 1864 | (comint-interrupt-subjob))))) | 1989 | (comint-interrupt-subjob))))) |
| 1865 | 1990 | ||
| @@ -1888,19 +2013,18 @@ Returns the output. See `python-shell-send-string-no-output'." | |||
| 1888 | 2013 | ||
| 1889 | (defun python-shell-send-buffer (&optional arg) | 2014 | (defun python-shell-send-buffer (&optional arg) |
| 1890 | "Send the entire buffer to inferior Python process. | 2015 | "Send the entire buffer to inferior Python process. |
| 1891 | 2016 | With prefix ARG allow execution of code inside blocks delimited | |
| 1892 | With prefix ARG include lines surrounded by \"if __name__ == '__main__':\"" | 2017 | by \"if __name__== '__main__':\"" |
| 1893 | (interactive "P") | 2018 | (interactive "P") |
| 1894 | (save-restriction | 2019 | (save-restriction |
| 1895 | (widen) | 2020 | (widen) |
| 1896 | (python-shell-send-region | 2021 | (let ((str (buffer-substring (point-min) (point-max)))) |
| 1897 | (point-min) | 2022 | (and |
| 1898 | (or (and | 2023 | (not arg) |
| 1899 | (not arg) | 2024 | (setq str (replace-regexp-in-string |
| 1900 | (save-excursion | 2025 | (python-rx if-name-main) |
| 1901 | (re-search-forward (python-rx if-name-main) nil t)) | 2026 | "if __name__ == '__main__ ':" str))) |
| 1902 | (match-beginning 0)) | 2027 | (python-shell-send-string str)))) |
| 1903 | (point-max))))) | ||
| 1904 | 2028 | ||
| 1905 | (defun python-shell-send-defun (arg) | 2029 | (defun python-shell-send-defun (arg) |
| 1906 | "Send the current defun to inferior Python process. | 2030 | "Send the current defun to inferior Python process. |
| @@ -1910,7 +2034,7 @@ When argument ARG is non-nil do not include decorators." | |||
| 1910 | (python-shell-send-region | 2034 | (python-shell-send-region |
| 1911 | (progn | 2035 | (progn |
| 1912 | (end-of-line 1) | 2036 | (end-of-line 1) |
| 1913 | (while (and (or (python-beginning-of-defun-function) | 2037 | (while (and (or (python-nav-beginning-of-defun) |
| 1914 | (beginning-of-line 1)) | 2038 | (beginning-of-line 1)) |
| 1915 | (> (current-indentation) 0))) | 2039 | (> (current-indentation) 0))) |
| 1916 | (when (not arg) | 2040 | (when (not arg) |
| @@ -1919,7 +2043,7 @@ When argument ARG is non-nil do not include decorators." | |||
| 1919 | (forward-line 1)) | 2043 | (forward-line 1)) |
| 1920 | (point-marker)) | 2044 | (point-marker)) |
| 1921 | (progn | 2045 | (progn |
| 1922 | (or (python-end-of-defun-function) | 2046 | (or (python-nav-end-of-defun) |
| 1923 | (end-of-line 1)) | 2047 | (end-of-line 1)) |
| 1924 | (point-marker))))) | 2048 | (point-marker))))) |
| 1925 | 2049 | ||
| @@ -1931,8 +2055,14 @@ FILE-NAME." | |||
| 1931 | (interactive "fFile to send: ") | 2055 | (interactive "fFile to send: ") |
| 1932 | (let* ((process (or process (python-shell-get-or-create-process))) | 2056 | (let* ((process (or process (python-shell-get-or-create-process))) |
| 1933 | (temp-file-name (when temp-file-name | 2057 | (temp-file-name (when temp-file-name |
| 1934 | (expand-file-name temp-file-name))) | 2058 | (expand-file-name |
| 1935 | (file-name (or (expand-file-name file-name) temp-file-name))) | 2059 | (or (file-remote-p temp-file-name 'localname) |
| 2060 | temp-file-name)))) | ||
| 2061 | (file-name (or (when file-name | ||
| 2062 | (expand-file-name | ||
| 2063 | (or (file-remote-p file-name 'localname) | ||
| 2064 | file-name))) | ||
| 2065 | temp-file-name))) | ||
| 1936 | (when (not file-name) | 2066 | (when (not file-name) |
| 1937 | (error "If FILE-NAME is nil then TEMP-FILE-NAME must be non-nil")) | 2067 | (error "If FILE-NAME is nil then TEMP-FILE-NAME must be non-nil")) |
| 1938 | (python-shell-send-string | 2068 | (python-shell-send-string |
| @@ -2047,11 +2177,11 @@ INPUT." | |||
| 2047 | 'default) | 2177 | 'default) |
| 2048 | (t nil))) | 2178 | (t nil))) |
| 2049 | (completion-code | 2179 | (completion-code |
| 2050 | (case completion-context | 2180 | (pcase completion-context |
| 2051 | (pdb python-shell-completion-pdb-string-code) | 2181 | (`pdb python-shell-completion-pdb-string-code) |
| 2052 | (import python-shell-completion-module-string-code) | 2182 | (`import python-shell-completion-module-string-code) |
| 2053 | (default python-shell-completion-string-code) | 2183 | (`default python-shell-completion-string-code) |
| 2054 | (t nil))) | 2184 | (_ nil))) |
| 2055 | (input | 2185 | (input |
| 2056 | (if (eq completion-context 'import) | 2186 | (if (eq completion-context 'import) |
| 2057 | (replace-regexp-in-string "^[ \t]+" "" line) | 2187 | (replace-regexp-in-string "^[ \t]+" "" line) |
| @@ -2219,37 +2349,105 @@ inferior python process is updated properly." | |||
| 2219 | 2349 | ||
| 2220 | (defcustom python-fill-comment-function 'python-fill-comment | 2350 | (defcustom python-fill-comment-function 'python-fill-comment |
| 2221 | "Function to fill comments. | 2351 | "Function to fill comments. |
| 2222 | This is the function used by `python-fill-paragraph-function' to | 2352 | This is the function used by `python-fill-paragraph' to |
| 2223 | fill comments." | 2353 | fill comments." |
| 2224 | :type 'symbol | 2354 | :type 'symbol |
| 2225 | :group 'python | 2355 | :group 'python) |
| 2226 | :safe 'symbolp) | ||
| 2227 | 2356 | ||
| 2228 | (defcustom python-fill-string-function 'python-fill-string | 2357 | (defcustom python-fill-string-function 'python-fill-string |
| 2229 | "Function to fill strings. | 2358 | "Function to fill strings. |
| 2230 | This is the function used by `python-fill-paragraph-function' to | 2359 | This is the function used by `python-fill-paragraph' to |
| 2231 | fill strings." | 2360 | fill strings." |
| 2232 | :type 'symbol | 2361 | :type 'symbol |
| 2233 | :group 'python | 2362 | :group 'python) |
| 2234 | :safe 'symbolp) | ||
| 2235 | 2363 | ||
| 2236 | (defcustom python-fill-decorator-function 'python-fill-decorator | 2364 | (defcustom python-fill-decorator-function 'python-fill-decorator |
| 2237 | "Function to fill decorators. | 2365 | "Function to fill decorators. |
| 2238 | This is the function used by `python-fill-paragraph-function' to | 2366 | This is the function used by `python-fill-paragraph' to |
| 2239 | fill decorators." | 2367 | fill decorators." |
| 2240 | :type 'symbol | 2368 | :type 'symbol |
| 2241 | :group 'python | 2369 | :group 'python) |
| 2242 | :safe 'symbolp) | ||
| 2243 | 2370 | ||
| 2244 | (defcustom python-fill-paren-function 'python-fill-paren | 2371 | (defcustom python-fill-paren-function 'python-fill-paren |
| 2245 | "Function to fill parens. | 2372 | "Function to fill parens. |
| 2246 | This is the function used by `python-fill-paragraph-function' to | 2373 | This is the function used by `python-fill-paragraph' to |
| 2247 | fill parens." | 2374 | fill parens." |
| 2248 | :type 'symbol | 2375 | :type 'symbol |
| 2376 | :group 'python) | ||
| 2377 | |||
| 2378 | (defcustom python-fill-docstring-style 'pep-257 | ||
| 2379 | "Style used to fill docstrings. | ||
| 2380 | This affects `python-fill-string' behavior with regards to | ||
| 2381 | triple quotes positioning. | ||
| 2382 | |||
| 2383 | Possible values are DJANGO, ONETWO, PEP-257, PEP-257-NN, | ||
| 2384 | SYMMETRIC, and NIL. A value of NIL won't care about quotes | ||
| 2385 | position and will treat docstrings a normal string, any other | ||
| 2386 | value may result in one of the following docstring styles: | ||
| 2387 | |||
| 2388 | DJANGO: | ||
| 2389 | |||
| 2390 | \"\"\" | ||
| 2391 | Process foo, return bar. | ||
| 2392 | \"\"\" | ||
| 2393 | |||
| 2394 | \"\"\" | ||
| 2395 | Process foo, return bar. | ||
| 2396 | |||
| 2397 | If processing fails throw ProcessingError. | ||
| 2398 | \"\"\" | ||
| 2399 | |||
| 2400 | ONETWO: | ||
| 2401 | |||
| 2402 | \"\"\"Process foo, return bar.\"\"\" | ||
| 2403 | |||
| 2404 | \"\"\" | ||
| 2405 | Process foo, return bar. | ||
| 2406 | |||
| 2407 | If processing fails throw ProcessingError. | ||
| 2408 | |||
| 2409 | \"\"\" | ||
| 2410 | |||
| 2411 | PEP-257: | ||
| 2412 | |||
| 2413 | \"\"\"Process foo, return bar.\"\"\" | ||
| 2414 | |||
| 2415 | \"\"\"Process foo, return bar. | ||
| 2416 | |||
| 2417 | If processing fails throw ProcessingError. | ||
| 2418 | |||
| 2419 | \"\"\" | ||
| 2420 | |||
| 2421 | PEP-257-NN: | ||
| 2422 | |||
| 2423 | \"\"\"Process foo, return bar.\"\"\" | ||
| 2424 | |||
| 2425 | \"\"\"Process foo, return bar. | ||
| 2426 | |||
| 2427 | If processing fails throw ProcessingError. | ||
| 2428 | \"\"\" | ||
| 2429 | |||
| 2430 | SYMMETRIC: | ||
| 2431 | |||
| 2432 | \"\"\"Process foo, return bar.\"\"\" | ||
| 2433 | |||
| 2434 | \"\"\" | ||
| 2435 | Process foo, return bar. | ||
| 2436 | |||
| 2437 | If processing fails throw ProcessingError. | ||
| 2438 | \"\"\"" | ||
| 2439 | :type '(choice | ||
| 2440 | (const :tag "Don't format docstrings" nil) | ||
| 2441 | (const :tag "Django's coding standards style." django) | ||
| 2442 | (const :tag "One newline and start and Two at end style." onetwo) | ||
| 2443 | (const :tag "PEP-257 with 2 newlines at end of string." pep-257) | ||
| 2444 | (const :tag "PEP-257 with 1 newline at end of string." pep-257-nn) | ||
| 2445 | (const :tag "Symmetric style." symmetric)) | ||
| 2249 | :group 'python | 2446 | :group 'python |
| 2250 | :safe 'symbolp) | 2447 | :safe (lambda (val) |
| 2448 | (memq val '(django onetwo pep-257 pep-257-nn symmetric nil)))) | ||
| 2251 | 2449 | ||
| 2252 | (defun python-fill-paragraph-function (&optional justify) | 2450 | (defun python-fill-paragraph (&optional justify) |
| 2253 | "`fill-paragraph-function' handling multi-line strings and possibly comments. | 2451 | "`fill-paragraph-function' handling multi-line strings and possibly comments. |
| 2254 | If any of the current line is in or at the end of a multi-line string, | 2452 | If any of the current line is in or at the end of a multi-line string, |
| 2255 | fill the string or the paragraph of it that point is in, preserving | 2453 | fill the string or the paragraph of it that point is in, preserving |
| @@ -2257,18 +2455,18 @@ the string's indentation. | |||
| 2257 | Optional argument JUSTIFY defines if the paragraph should be justified." | 2455 | Optional argument JUSTIFY defines if the paragraph should be justified." |
| 2258 | (interactive "P") | 2456 | (interactive "P") |
| 2259 | (save-excursion | 2457 | (save-excursion |
| 2260 | (back-to-indentation) | ||
| 2261 | (cond | 2458 | (cond |
| 2262 | ;; Comments | 2459 | ;; Comments |
| 2263 | ((funcall python-fill-comment-function justify)) | 2460 | ((python-syntax-context 'comment) |
| 2461 | (funcall python-fill-comment-function justify)) | ||
| 2264 | ;; Strings/Docstrings | 2462 | ;; Strings/Docstrings |
| 2265 | ((save-excursion (skip-chars-forward "\"'uUrR") | 2463 | ((save-excursion (or (python-syntax-context 'string) |
| 2266 | (python-syntax-context 'string)) | 2464 | (equal (string-to-syntax "|") |
| 2465 | (syntax-after (point))))) | ||
| 2267 | (funcall python-fill-string-function justify)) | 2466 | (funcall python-fill-string-function justify)) |
| 2268 | ;; Decorators | 2467 | ;; Decorators |
| 2269 | ((equal (char-after (save-excursion | 2468 | ((equal (char-after (save-excursion |
| 2270 | (back-to-indentation) | 2469 | (python-nav-beginning-of-statement))) ?@) |
| 2271 | (point-marker))) ?@) | ||
| 2272 | (funcall python-fill-decorator-function justify)) | 2470 | (funcall python-fill-decorator-function justify)) |
| 2273 | ;; Parens | 2471 | ;; Parens |
| 2274 | ((or (python-syntax-context 'paren) | 2472 | ((or (python-syntax-context 'paren) |
| @@ -2280,58 +2478,87 @@ Optional argument JUSTIFY defines if the paragraph should be justified." | |||
| 2280 | (t t)))) | 2478 | (t t)))) |
| 2281 | 2479 | ||
| 2282 | (defun python-fill-comment (&optional justify) | 2480 | (defun python-fill-comment (&optional justify) |
| 2283 | "Comment fill function for `python-fill-paragraph-function'. | 2481 | "Comment fill function for `python-fill-paragraph'. |
| 2284 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2482 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." |
| 2285 | (fill-comment-paragraph justify)) | 2483 | (fill-comment-paragraph justify)) |
| 2286 | 2484 | ||
| 2287 | (defun python-fill-string (&optional justify) | 2485 | (defun python-fill-string (&optional justify) |
| 2288 | "String fill function for `python-fill-paragraph-function'. | 2486 | "String fill function for `python-fill-paragraph'. |
| 2289 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2487 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." |
| 2290 | (let ((marker (point-marker)) | 2488 | (let* ((marker (point-marker)) |
| 2291 | (string-start-marker | 2489 | (str-start-pos |
| 2292 | (progn | 2490 | (let ((m (make-marker))) |
| 2293 | (skip-chars-forward "\"'uUrR") | 2491 | (setf (marker-position m) |
| 2294 | (goto-char (python-syntax-context 'string)) | 2492 | (or (python-syntax-context 'string) |
| 2295 | (skip-chars-forward "\"'uUrR") | 2493 | (and (equal (string-to-syntax "|") |
| 2296 | (point-marker))) | 2494 | (syntax-after (point))) |
| 2297 | (reg-start (line-beginning-position)) | 2495 | (point)))) m)) |
| 2298 | (string-end-marker | 2496 | (num-quotes (python-syntax-count-quotes |
| 2299 | (progn | 2497 | (char-after str-start-pos) str-start-pos)) |
| 2300 | (while (python-syntax-context 'string) | 2498 | (str-end-pos |
| 2301 | (goto-char (1+ (point-marker)))) | 2499 | (save-excursion |
| 2302 | (skip-chars-backward "\"'") | 2500 | (goto-char (+ str-start-pos num-quotes)) |
| 2303 | (point-marker))) | 2501 | (or (re-search-forward (rx (syntax string-delimiter)) nil t) |
| 2304 | (reg-end (line-end-position)) | 2502 | (goto-char (point-max))) |
| 2305 | (fill-paragraph-function)) | 2503 | (point-marker))) |
| 2504 | (multi-line-p | ||
| 2505 | ;; Docstring styles may vary for oneliners and multi-liners. | ||
| 2506 | (> (count-matches "\n" str-start-pos str-end-pos) 0)) | ||
| 2507 | (delimiters-style | ||
| 2508 | (pcase python-fill-docstring-style | ||
| 2509 | ;; delimiters-style is a cons cell with the form | ||
| 2510 | ;; (START-NEWLINES . END-NEWLINES). When any of the sexps | ||
| 2511 | ;; is NIL means to not add any newlines for start or end | ||
| 2512 | ;; of docstring. See `python-fill-docstring-style' for a | ||
| 2513 | ;; graphic idea of each style. | ||
| 2514 | (`django (cons 1 1)) | ||
| 2515 | (`onetwo (and multi-line-p (cons 1 2))) | ||
| 2516 | (`pep-257 (and multi-line-p (cons nil 2))) | ||
| 2517 | (`pep-257-nn (and multi-line-p (cons nil 1))) | ||
| 2518 | (`symmetric (and multi-line-p (cons 1 1))))) | ||
| 2519 | (docstring-p (save-excursion | ||
| 2520 | ;; Consider docstrings those strings which | ||
| 2521 | ;; start on a line by themselves. | ||
| 2522 | (python-nav-beginning-of-statement) | ||
| 2523 | (and (= (point) str-start-pos)))) | ||
| 2524 | (fill-paragraph-function)) | ||
| 2306 | (save-restriction | 2525 | (save-restriction |
| 2307 | (narrow-to-region reg-start reg-end) | 2526 | (narrow-to-region str-start-pos str-end-pos) |
| 2308 | (save-excursion | 2527 | (fill-paragraph justify)) |
| 2309 | (goto-char string-start-marker) | 2528 | (save-excursion |
| 2310 | (delete-region (point-marker) (progn | 2529 | (when (and docstring-p python-fill-docstring-style) |
| 2311 | (skip-syntax-forward "> ") | 2530 | ;; Add the number of newlines indicated by the selected style |
| 2312 | (point-marker))) | 2531 | ;; at the start of the docstring. |
| 2313 | (goto-char string-end-marker) | 2532 | (goto-char (+ str-start-pos num-quotes)) |
| 2314 | (delete-region (point-marker) (progn | 2533 | (delete-region (point) (progn |
| 2315 | (skip-syntax-backward "> ") | 2534 | (skip-syntax-forward "> ") |
| 2316 | (point-marker))) | 2535 | (point))) |
| 2317 | (save-excursion | 2536 | (and (car delimiters-style) |
| 2318 | (goto-char marker) | 2537 | (or (newline (car delimiters-style)) t) |
| 2319 | (fill-paragraph justify)) | 2538 | ;; Indent only if a newline is added. |
| 2320 | ;; If there is a newline in the docstring lets put triple | 2539 | (indent-according-to-mode)) |
| 2321 | ;; quote in it's own line to follow pep 8 | 2540 | ;; Add the number of newlines indicated by the selected style |
| 2322 | (when (save-excursion | 2541 | ;; at the end of the docstring. |
| 2323 | (re-search-backward "\n" string-start-marker t)) | 2542 | (goto-char (if (not (= str-end-pos (point-max))) |
| 2324 | (newline) | 2543 | (- str-end-pos num-quotes) |
| 2325 | (newline-and-indent)) | 2544 | str-end-pos)) |
| 2326 | (fill-paragraph justify)))) t) | 2545 | (delete-region (point) (progn |
| 2546 | (skip-syntax-backward "> ") | ||
| 2547 | (point))) | ||
| 2548 | (and (cdr delimiters-style) | ||
| 2549 | ;; Add newlines only if string ends. | ||
| 2550 | (not (= str-end-pos (point-max))) | ||
| 2551 | (or (newline (cdr delimiters-style)) t) | ||
| 2552 | ;; Again indent only if a newline is added. | ||
| 2553 | (indent-according-to-mode))))) t) | ||
| 2327 | 2554 | ||
| 2328 | (defun python-fill-decorator (&optional justify) | 2555 | (defun python-fill-decorator (&optional justify) |
| 2329 | "Decorator fill function for `python-fill-paragraph-function'. | 2556 | "Decorator fill function for `python-fill-paragraph'. |
| 2330 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2557 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." |
| 2331 | t) | 2558 | t) |
| 2332 | 2559 | ||
| 2333 | (defun python-fill-paren (&optional justify) | 2560 | (defun python-fill-paren (&optional justify) |
| 2334 | "Paren fill function for `python-fill-paragraph-function'. | 2561 | "Paren fill function for `python-fill-paragraph'. |
| 2335 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2562 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." |
| 2336 | (save-restriction | 2563 | (save-restriction |
| 2337 | (narrow-to-region (progn | 2564 | (narrow-to-region (progn |
| @@ -2465,17 +2692,17 @@ The skeleton will be bound to python-skeleton-NAME." | |||
| 2465 | 2692 | ||
| 2466 | (python-skeleton-define def nil | 2693 | (python-skeleton-define def nil |
| 2467 | "Function name: " | 2694 | "Function name: " |
| 2468 | "def " str " (" ("Parameter, %s: " | 2695 | "def " str "(" ("Parameter, %s: " |
| 2469 | (unless (equal ?\( (char-before)) ", ") | 2696 | (unless (equal ?\( (char-before)) ", ") |
| 2470 | str) "):" \n | 2697 | str) "):" \n |
| 2471 | "\"\"\"" - "\"\"\"" \n | 2698 | "\"\"\"" - "\"\"\"" \n |
| 2472 | > _ \n) | 2699 | > _ \n) |
| 2473 | 2700 | ||
| 2474 | (python-skeleton-define class nil | 2701 | (python-skeleton-define class nil |
| 2475 | "Class name: " | 2702 | "Class name: " |
| 2476 | "class " str " (" ("Inheritance, %s: " | 2703 | "class " str "(" ("Inheritance, %s: " |
| 2477 | (unless (equal ?\( (char-before)) ", ") | 2704 | (unless (equal ?\( (char-before)) ", ") |
| 2478 | str) | 2705 | str) |
| 2479 | & ")" | -2 | 2706 | & ")" | -2 |
| 2480 | ":" \n | 2707 | ":" \n |
| 2481 | "\"\"\"" - "\"\"\"" \n | 2708 | "\"\"\"" - "\"\"\"" \n |
| @@ -2489,7 +2716,7 @@ The skeleton will be bound to python-skeleton-NAME." | |||
| 2489 | (easy-menu-add-item | 2716 | (easy-menu-add-item |
| 2490 | nil '("Python" "Skeletons") | 2717 | nil '("Python" "Skeletons") |
| 2491 | `[,(format | 2718 | `[,(format |
| 2492 | "Insert %s" (caddr (split-string (symbol-name skeleton) "-"))) | 2719 | "Insert %s" (nth 2 (split-string (symbol-name skeleton) "-"))) |
| 2493 | ,skeleton t])))) | 2720 | ,skeleton t])))) |
| 2494 | 2721 | ||
| 2495 | ;;; FFAP | 2722 | ;;; FFAP |
| @@ -2656,6 +2883,19 @@ Interactively, prompt for symbol." | |||
| 2656 | "^Eldoc needs an inferior Python process running.") | 2883 | "^Eldoc needs an inferior Python process running.") |
| 2657 | 2884 | ||
| 2658 | 2885 | ||
| 2886 | ;;; Imenu | ||
| 2887 | |||
| 2888 | (defun python-imenu-prev-index-position () | ||
| 2889 | "Python mode's `imenu-prev-index-position-function'." | ||
| 2890 | (let ((found)) | ||
| 2891 | (while (and (setq found | ||
| 2892 | (re-search-backward python-nav-beginning-of-defun-regexp nil t)) | ||
| 2893 | (not (python-info-looking-at-beginning-of-defun)))) | ||
| 2894 | (and found | ||
| 2895 | (python-info-looking-at-beginning-of-defun) | ||
| 2896 | (python-info-current-defun)))) | ||
| 2897 | |||
| 2898 | |||
| 2659 | ;;; Misc helpers | 2899 | ;;; Misc helpers |
| 2660 | 2900 | ||
| 2661 | (defun python-info-current-defun (&optional include-type) | 2901 | (defun python-info-current-defun (&optional include-type) |
| @@ -2664,38 +2904,40 @@ Optional argument INCLUDE-TYPE indicates to include the type of the defun. | |||
| 2664 | This function is compatible to be used as | 2904 | This function is compatible to be used as |
| 2665 | `add-log-current-defun-function' since it returns nil if point is | 2905 | `add-log-current-defun-function' since it returns nil if point is |
| 2666 | not inside a defun." | 2906 | not inside a defun." |
| 2667 | (let ((names '()) | ||
| 2668 | (starting-indentation) | ||
| 2669 | (starting-point) | ||
| 2670 | (first-run t)) | ||
| 2671 | (save-restriction | 2907 | (save-restriction |
| 2672 | (widen) | 2908 | (widen) |
| 2673 | (save-excursion | 2909 | (save-excursion |
| 2674 | (setq starting-point (point-marker)) | ||
| 2675 | (setq starting-indentation (save-excursion | ||
| 2676 | (python-nav-beginning-of-statement) | ||
| 2677 | (current-indentation))) | ||
| 2678 | (end-of-line 1) | 2910 | (end-of-line 1) |
| 2679 | (while (python-beginning-of-defun-function 1) | 2911 | (let ((names) |
| 2680 | (when (or (< (current-indentation) starting-indentation) | 2912 | (starting-indentation |
| 2681 | (and first-run | 2913 | (save-excursion |
| 2682 | (< | 2914 | (and |
| 2683 | starting-point | 2915 | (python-nav-beginning-of-defun 1) |
| 2684 | (save-excursion | 2916 | ;; This extra number is just for checking code |
| 2685 | (python-end-of-defun-function) | 2917 | ;; against indentation to work well on first run. |
| 2686 | (point-marker))))) | 2918 | (+ (current-indentation) 4)))) |
| 2687 | (setq first-run nil) | 2919 | (starting-point (point))) |
| 2688 | (setq starting-indentation (current-indentation)) | 2920 | ;; Check point is inside a defun. |
| 2689 | (looking-at python-nav-beginning-of-defun-regexp) | 2921 | (when (and starting-indentation |
| 2690 | (setq names (cons | 2922 | (< starting-point |
| 2923 | (save-excursion | ||
| 2924 | (python-nav-end-of-defun) | ||
| 2925 | (point)))) | ||
| 2926 | (catch 'exit | ||
| 2927 | (while (python-nav-beginning-of-defun 1) | ||
| 2928 | (when (< (current-indentation) starting-indentation) | ||
| 2929 | (setq starting-indentation (current-indentation)) | ||
| 2930 | (setq names | ||
| 2931 | (cons | ||
| 2691 | (if (not include-type) | 2932 | (if (not include-type) |
| 2692 | (match-string-no-properties 1) | 2933 | (match-string-no-properties 1) |
| 2693 | (mapconcat 'identity | 2934 | (mapconcat 'identity |
| 2694 | (split-string | 2935 | (split-string |
| 2695 | (match-string-no-properties 0)) " ")) | 2936 | (match-string-no-properties 0)) " ")) |
| 2696 | names)))))) | 2937 | names))) |
| 2697 | (when names | 2938 | (and (= (current-indentation) 0) (throw 'exit t))))) |
| 2698 | (mapconcat (lambda (string) string) names ".")))) | 2939 | (and names |
| 2940 | (mapconcat (lambda (string) string) names ".")))))) | ||
| 2699 | 2941 | ||
| 2700 | (defun python-info-current-symbol (&optional replace-self) | 2942 | (defun python-info-current-symbol (&optional replace-self) |
| 2701 | "Return current symbol using dotty syntax. | 2943 | "Return current symbol using dotty syntax. |
| @@ -2721,12 +2963,43 @@ parent defun name." | |||
| 2721 | ".") ".") | 2963 | ".") ".") |
| 2722 | name))))))) | 2964 | name))))))) |
| 2723 | 2965 | ||
| 2724 | (defsubst python-info-beginning-of-block-statement-p () | 2966 | (defun python-info-statement-starts-block-p () |
| 2725 | "Return non-nil if current statement opens a block." | 2967 | "Return non-nil if current statement opens a block." |
| 2726 | (save-excursion | 2968 | (save-excursion |
| 2727 | (python-nav-beginning-of-statement) | 2969 | (python-nav-beginning-of-statement) |
| 2728 | (looking-at (python-rx block-start)))) | 2970 | (looking-at (python-rx block-start)))) |
| 2729 | 2971 | ||
| 2972 | (defun python-info-statement-ends-block-p () | ||
| 2973 | "Return non-nil if point is at end of block." | ||
| 2974 | (let ((end-of-block-pos (save-excursion | ||
| 2975 | (python-nav-end-of-block))) | ||
| 2976 | (end-of-statement-pos (save-excursion | ||
| 2977 | (python-nav-end-of-statement)))) | ||
| 2978 | (and end-of-block-pos end-of-statement-pos | ||
| 2979 | (= end-of-block-pos end-of-statement-pos)))) | ||
| 2980 | |||
| 2981 | (defun python-info-beginning-of-statement-p () | ||
| 2982 | "Return non-nil if point is at beginning of statement." | ||
| 2983 | (= (point) (save-excursion | ||
| 2984 | (python-nav-beginning-of-statement) | ||
| 2985 | (point)))) | ||
| 2986 | |||
| 2987 | (defun python-info-end-of-statement-p () | ||
| 2988 | "Return non-nil if point is at end of statement." | ||
| 2989 | (= (point) (save-excursion | ||
| 2990 | (python-nav-end-of-statement) | ||
| 2991 | (point)))) | ||
| 2992 | |||
| 2993 | (defun python-info-beginning-of-block-p () | ||
| 2994 | "Return non-nil if point is at beginning of block." | ||
| 2995 | (and (python-info-beginning-of-statement-p) | ||
| 2996 | (python-info-statement-starts-block-p))) | ||
| 2997 | |||
| 2998 | (defun python-info-end-of-block-p () | ||
| 2999 | "Return non-nil if point is at end of block." | ||
| 3000 | (and (python-info-end-of-statement-p) | ||
| 3001 | (python-info-statement-ends-block-p))) | ||
| 3002 | |||
| 2730 | (defun python-info-closing-block () | 3003 | (defun python-info-closing-block () |
| 2731 | "Return the point of the block the current line closes." | 3004 | "Return the point of the block the current line closes." |
| 2732 | (let ((closing-word (save-excursion | 3005 | (let ((closing-word (save-excursion |
| @@ -2951,12 +3224,12 @@ if that value is non-nil." | |||
| 2951 | 3224 | ||
| 2952 | (set (make-local-variable 'paragraph-start) "\\s-*$") | 3225 | (set (make-local-variable 'paragraph-start) "\\s-*$") |
| 2953 | (set (make-local-variable 'fill-paragraph-function) | 3226 | (set (make-local-variable 'fill-paragraph-function) |
| 2954 | 'python-fill-paragraph-function) | 3227 | 'python-fill-paragraph) |
| 2955 | 3228 | ||
| 2956 | (set (make-local-variable 'beginning-of-defun-function) | 3229 | (set (make-local-variable 'beginning-of-defun-function) |
| 2957 | #'python-beginning-of-defun-function) | 3230 | #'python-nav-beginning-of-defun) |
| 2958 | (set (make-local-variable 'end-of-defun-function) | 3231 | (set (make-local-variable 'end-of-defun-function) |
| 2959 | #'python-end-of-defun-function) | 3232 | #'python-nav-end-of-defun) |
| 2960 | 3233 | ||
| 2961 | (add-hook 'completion-at-point-functions | 3234 | (add-hook 'completion-at-point-functions |
| 2962 | 'python-completion-complete-at-point nil 'local) | 3235 | 'python-completion-complete-at-point nil 'local) |
| @@ -2967,6 +3240,9 @@ if that value is non-nil." | |||
| 2967 | (set (make-local-variable 'imenu-extract-index-name-function) | 3240 | (set (make-local-variable 'imenu-extract-index-name-function) |
| 2968 | #'python-info-current-defun) | 3241 | #'python-info-current-defun) |
| 2969 | 3242 | ||
| 3243 | (set (make-local-variable 'imenu-prev-index-position-function) | ||
| 3244 | #'python-imenu-prev-index-position) | ||
| 3245 | |||
| 2970 | (set (make-local-variable 'add-log-current-defun-function) | 3246 | (set (make-local-variable 'add-log-current-defun-function) |
| 2971 | #'python-info-current-defun) | 3247 | #'python-info-current-defun) |
| 2972 | 3248 | ||
| @@ -2984,7 +3260,7 @@ if that value is non-nil." | |||
| 2984 | (add-to-list 'hs-special-modes-alist | 3260 | (add-to-list 'hs-special-modes-alist |
| 2985 | `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#" | 3261 | `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#" |
| 2986 | ,(lambda (arg) | 3262 | ,(lambda (arg) |
| 2987 | (python-end-of-defun-function)) nil)) | 3263 | (python-nav-end-of-defun)) nil)) |
| 2988 | 3264 | ||
| 2989 | (set (make-local-variable 'mode-require-final-newline) t) | 3265 | (set (make-local-variable 'mode-require-final-newline) t) |
| 2990 | 3266 | ||