diff options
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 610 |
1 files changed, 357 insertions, 253 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index f946509d6e0..601850ed0fb 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -54,7 +54,7 @@ | |||
| 54 | ;; `python-nav-beginning-of-statement', `python-nav-end-of-statement', | 54 | ;; `python-nav-beginning-of-statement', `python-nav-end-of-statement', |
| 55 | ;; `python-nav-beginning-of-block' and `python-nav-end-of-block' are | 55 | ;; `python-nav-beginning-of-block' and `python-nav-end-of-block' are |
| 56 | ;; included but no bound to any key. At last but not least the | 56 | ;; included but no bound to any key. At last but not least the |
| 57 | ;; specialized `python-nav-forward-sexp-function' allows easy | 57 | ;; specialized `python-nav-forward-sexp' allows easy |
| 58 | ;; navigation between code blocks. | 58 | ;; navigation between code blocks. |
| 59 | 59 | ||
| 60 | ;; Shell interaction: is provided and allows you to execute easily any | 60 | ;; Shell interaction: is provided and allows you to execute easily any |
| @@ -353,6 +353,40 @@ This variant of `rx' supports common python named REGEXPS." | |||
| 353 | 353 | ||
| 354 | 354 | ||
| 355 | ;;; Font-lock and syntax | 355 | ;;; Font-lock and syntax |
| 356 | |||
| 357 | (defun python-syntax-context (type &optional syntax-ppss) | ||
| 358 | "Return non-nil if point is on TYPE using SYNTAX-PPSS. | ||
| 359 | TYPE can be `comment', `string' or `paren'. It returns the start | ||
| 360 | character address of the specified TYPE." | ||
| 361 | (let ((ppss (or syntax-ppss (syntax-ppss)))) | ||
| 362 | (case type | ||
| 363 | (comment (and (nth 4 ppss) (nth 8 ppss))) | ||
| 364 | (string (and (not (nth 4 ppss)) (nth 8 ppss))) | ||
| 365 | (paren (nth 1 ppss)) | ||
| 366 | (t nil)))) | ||
| 367 | |||
| 368 | (defun python-syntax-context-type (&optional syntax-ppss) | ||
| 369 | "Return the context type using SYNTAX-PPSS. | ||
| 370 | The type returned can be `comment', `string' or `paren'." | ||
| 371 | (let ((ppss (or syntax-ppss (syntax-ppss)))) | ||
| 372 | (cond | ||
| 373 | ((nth 8 ppss) (if (nth 4 ppss) 'comment 'string)) | ||
| 374 | ((nth 1 ppss) 'paren)))) | ||
| 375 | |||
| 376 | (defsubst python-syntax-comment-or-string-p () | ||
| 377 | "Return non-nil if point is inside 'comment or 'string." | ||
| 378 | (nth 8 (syntax-ppss))) | ||
| 379 | |||
| 380 | (define-obsolete-function-alias | ||
| 381 | 'python-info-ppss-context #'python-syntax-context "24.3") | ||
| 382 | |||
| 383 | (define-obsolete-function-alias | ||
| 384 | 'python-info-ppss-context-type #'python-syntax-context-type "24.3") | ||
| 385 | |||
| 386 | (define-obsolete-function-alias | ||
| 387 | 'python-info-ppss-comment-or-string-p | ||
| 388 | #'python-syntax-comment-or-string-p "24.3") | ||
| 389 | |||
| 356 | (defvar python-font-lock-keywords | 390 | (defvar python-font-lock-keywords |
| 357 | ;; Keywords | 391 | ;; Keywords |
| 358 | `(,(rx symbol-start | 392 | `(,(rx symbol-start |
| @@ -439,9 +473,9 @@ This variant of `rx' supports common python named REGEXPS." | |||
| 439 | (? ?\[ (+ (not (any ?\]))) ?\]) (* space) | 473 | (? ?\[ (+ (not (any ?\]))) ?\]) (* space) |
| 440 | assignment-operator))) | 474 | assignment-operator))) |
| 441 | (when (re-search-forward re limit t) | 475 | (when (re-search-forward re limit t) |
| 442 | (while (and (python-info-ppss-context 'paren) | 476 | (while (and (python-syntax-context 'paren) |
| 443 | (re-search-forward re limit t))) | 477 | (re-search-forward re limit t))) |
| 444 | (if (and (not (python-info-ppss-context 'paren)) | 478 | (if (and (not (python-syntax-context 'paren)) |
| 445 | (not (equal (char-after (point-marker)) ?=))) | 479 | (not (equal (char-after (point-marker)) ?=))) |
| 446 | t | 480 | t |
| 447 | (set-match-data nil))))) | 481 | (set-match-data nil))))) |
| @@ -454,10 +488,10 @@ This variant of `rx' supports common python named REGEXPS." | |||
| 454 | assignment-operator))) | 488 | assignment-operator))) |
| 455 | (when (and (re-search-forward re limit t) | 489 | (when (and (re-search-forward re limit t) |
| 456 | (goto-char (nth 3 (match-data)))) | 490 | (goto-char (nth 3 (match-data)))) |
| 457 | (while (and (python-info-ppss-context 'paren) | 491 | (while (and (python-syntax-context 'paren) |
| 458 | (re-search-forward re limit t)) | 492 | (re-search-forward re limit t)) |
| 459 | (goto-char (nth 3 (match-data)))) | 493 | (goto-char (nth 3 (match-data)))) |
| 460 | (if (not (python-info-ppss-context 'paren)) | 494 | (if (not (python-syntax-context 'paren)) |
| 461 | t | 495 | t |
| 462 | (set-match-data nil))))) | 496 | (set-match-data nil))))) |
| 463 | (1 font-lock-variable-name-face nil nil)))) | 497 | (1 font-lock-variable-name-face nil nil)))) |
| @@ -554,10 +588,10 @@ It makes underscores and dots word constituent chars.") | |||
| 554 | :safe 'booleanp) | 588 | :safe 'booleanp) |
| 555 | 589 | ||
| 556 | (define-obsolete-variable-alias | 590 | (define-obsolete-variable-alias |
| 557 | 'python-indent 'python-indent-offset "24.2") | 591 | 'python-indent 'python-indent-offset "24.3") |
| 558 | 592 | ||
| 559 | (define-obsolete-variable-alias | 593 | (define-obsolete-variable-alias |
| 560 | 'python-guess-indent 'python-indent-guess-indent-offset "24.2") | 594 | 'python-guess-indent 'python-indent-guess-indent-offset "24.3") |
| 561 | 595 | ||
| 562 | (defvar python-indent-current-level 0 | 596 | (defvar python-indent-current-level 0 |
| 563 | "Current indentation level `python-indent-line-function' is using.") | 597 | "Current indentation level `python-indent-line-function' is using.") |
| @@ -582,7 +616,7 @@ These make `python-indent-calculate-indentation' subtract the value of | |||
| 582 | (re-search-forward | 616 | (re-search-forward |
| 583 | (python-rx line-start block-start) nil t)) | 617 | (python-rx line-start block-start) nil t)) |
| 584 | (when (and | 618 | (when (and |
| 585 | (not (python-info-ppss-context-type)) | 619 | (not (python-syntax-context-type)) |
| 586 | (progn | 620 | (progn |
| 587 | (goto-char (line-end-position)) | 621 | (goto-char (line-end-position)) |
| 588 | (python-util-forward-comment -1) | 622 | (python-util-forward-comment -1) |
| @@ -632,14 +666,14 @@ START is the buffer position where the sexp starts." | |||
| 632 | (bobp)) | 666 | (bobp)) |
| 633 | 'no-indent) | 667 | 'no-indent) |
| 634 | ;; Inside a paren | 668 | ;; Inside a paren |
| 635 | ((setq start (python-info-ppss-context 'paren ppss)) | 669 | ((setq start (python-syntax-context 'paren ppss)) |
| 636 | 'inside-paren) | 670 | 'inside-paren) |
| 637 | ;; Inside string | 671 | ;; Inside string |
| 638 | ((setq start (python-info-ppss-context 'string ppss)) | 672 | ((setq start (python-syntax-context 'string ppss)) |
| 639 | 'inside-string) | 673 | 'inside-string) |
| 640 | ;; After backslash | 674 | ;; After backslash |
| 641 | ((setq start (when (not (or (python-info-ppss-context 'string ppss) | 675 | ((setq start (when (not (or (python-syntax-context 'string ppss) |
| 642 | (python-info-ppss-context 'comment ppss))) | 676 | (python-syntax-context 'comment ppss))) |
| 643 | (let ((line-beg-pos (line-beginning-position))) | 677 | (let ((line-beg-pos (line-beginning-position))) |
| 644 | (when (python-info-line-ends-backslash-p | 678 | (when (python-info-line-ends-backslash-p |
| 645 | (1- line-beg-pos)) | 679 | (1- line-beg-pos)) |
| @@ -657,7 +691,7 @@ START is the buffer position where the sexp starts." | |||
| 657 | (while (and (re-search-backward | 691 | (while (and (re-search-backward |
| 658 | (python-rx block-start) nil t) | 692 | (python-rx block-start) nil t) |
| 659 | (or | 693 | (or |
| 660 | (python-info-ppss-context-type) | 694 | (python-syntax-context-type) |
| 661 | (python-info-continuation-line-p)))) | 695 | (python-info-continuation-line-p)))) |
| 662 | (when (looking-at (python-rx block-start)) | 696 | (when (looking-at (python-rx block-start)) |
| 663 | (point-marker))))) | 697 | (point-marker))))) |
| @@ -721,13 +755,13 @@ START is the buffer position where the sexp starts." | |||
| 721 | (while (prog2 | 755 | (while (prog2 |
| 722 | (forward-line -1) | 756 | (forward-line -1) |
| 723 | (and (not (bobp)) | 757 | (and (not (bobp)) |
| 724 | (python-info-ppss-context 'paren)))) | 758 | (python-syntax-context 'paren)))) |
| 725 | (goto-char (line-end-position)) | 759 | (goto-char (line-end-position)) |
| 726 | (while (and (re-search-backward | 760 | (while (and (re-search-backward |
| 727 | "\\." (line-beginning-position) t) | 761 | "\\." (line-beginning-position) t) |
| 728 | (python-info-ppss-context-type))) | 762 | (python-syntax-context-type))) |
| 729 | (if (and (looking-at "\\.") | 763 | (if (and (looking-at "\\.") |
| 730 | (not (python-info-ppss-context-type))) | 764 | (not (python-syntax-context-type))) |
| 731 | ;; The indentation is the same column of the | 765 | ;; The indentation is the same column of the |
| 732 | ;; first matching dot that's not inside a | 766 | ;; first matching dot that's not inside a |
| 733 | ;; comment, a string or a paren | 767 | ;; comment, a string or a paren |
| @@ -783,7 +817,7 @@ START is the buffer position where the sexp starts." | |||
| 783 | (when (and (looking-at (regexp-opt '(")" "]" "}"))) | 817 | (when (and (looking-at (regexp-opt '(")" "]" "}"))) |
| 784 | (progn | 818 | (progn |
| 785 | (forward-char 1) | 819 | (forward-char 1) |
| 786 | (not (python-info-ppss-context 'paren)))) | 820 | (not (python-syntax-context 'paren)))) |
| 787 | (goto-char context-start) | 821 | (goto-char context-start) |
| 788 | (current-indentation)))) | 822 | (current-indentation)))) |
| 789 | ;; If open paren is contained on a line by itself add another | 823 | ;; If open paren is contained on a line by itself add another |
| @@ -883,7 +917,7 @@ See `python-indent-line' for details." | |||
| 883 | (defun python-indent-dedent-line () | 917 | (defun python-indent-dedent-line () |
| 884 | "De-indent current line." | 918 | "De-indent current line." |
| 885 | (interactive "*") | 919 | (interactive "*") |
| 886 | (when (and (not (python-info-ppss-comment-or-string-p)) | 920 | (when (and (not (python-syntax-comment-or-string-p)) |
| 887 | (<= (point-marker) (save-excursion | 921 | (<= (point-marker) (save-excursion |
| 888 | (back-to-indentation) | 922 | (back-to-indentation) |
| 889 | (point-marker))) | 923 | (point-marker))) |
| @@ -974,7 +1008,7 @@ With numeric ARG, just insert that many colons. With | |||
| 974 | (when (and (not arg) | 1008 | (when (and (not arg) |
| 975 | (eolp) | 1009 | (eolp) |
| 976 | (not (equal ?: (char-after (- (point-marker) 2)))) | 1010 | (not (equal ?: (char-after (- (point-marker) 2)))) |
| 977 | (not (python-info-ppss-comment-or-string-p))) | 1011 | (not (python-syntax-comment-or-string-p))) |
| 978 | (let ((indentation (current-indentation)) | 1012 | (let ((indentation (current-indentation)) |
| 979 | (calculated-indentation (python-indent-calculate-indentation))) | 1013 | (calculated-indentation (python-indent-calculate-indentation))) |
| 980 | (python-info-closing-block-message) | 1014 | (python-info-closing-block-message) |
| @@ -998,7 +1032,7 @@ automatically if needed." | |||
| 998 | (goto-char (line-beginning-position)) | 1032 | (goto-char (line-beginning-position)) |
| 999 | ;; If after going to the beginning of line the point | 1033 | ;; If after going to the beginning of line the point |
| 1000 | ;; is still inside a paren it's ok to do the trick | 1034 | ;; is still inside a paren it's ok to do the trick |
| 1001 | (when (python-info-ppss-context 'paren) | 1035 | (when (python-syntax-context 'paren) |
| 1002 | (let ((indentation (python-indent-calculate-indentation))) | 1036 | (let ((indentation (python-indent-calculate-indentation))) |
| 1003 | (when (< (current-indentation) indentation) | 1037 | (when (< (current-indentation) indentation) |
| 1004 | (indent-line-to indentation))))))) | 1038 | (indent-line-to indentation))))))) |
| @@ -1032,7 +1066,7 @@ non-nil if point is moved to `beginning-of-defun'." | |||
| 1032 | (end-of-line 1)) | 1066 | (end-of-line 1)) |
| 1033 | (while (and (funcall re-search-fn | 1067 | (while (and (funcall re-search-fn |
| 1034 | python-nav-beginning-of-defun-regexp nil t) | 1068 | python-nav-beginning-of-defun-regexp nil t) |
| 1035 | (python-info-ppss-context-type))) | 1069 | (python-syntax-context-type))) |
| 1036 | (and (python-info-looking-at-beginning-of-defun) | 1070 | (and (python-info-looking-at-beginning-of-defun) |
| 1037 | (or (not (= (line-number-at-pos pos) | 1071 | (or (not (= (line-number-at-pos pos) |
| 1038 | (line-number-at-pos))) | 1072 | (line-number-at-pos))) |
| @@ -1082,15 +1116,15 @@ Returns nil if point is not in a def or class." | |||
| 1082 | (equal (char-after (+ (point) (current-indentation))) ?#) | 1116 | (equal (char-after (+ (point) (current-indentation))) ?#) |
| 1083 | (<= (current-indentation) beg-defun-indent) | 1117 | (<= (current-indentation) beg-defun-indent) |
| 1084 | (looking-at (python-rx decorator)) | 1118 | (looking-at (python-rx decorator)) |
| 1085 | (python-info-ppss-context-type)))) | 1119 | (python-syntax-context-type)))) |
| 1086 | (forward-line 1) | 1120 | (forward-line 1) |
| 1087 | ;; If point falls inside a paren or string context the point is | 1121 | ;; If point falls inside a paren or string context the point is |
| 1088 | ;; forwarded at the end of it (or end of buffer if its not closed) | 1122 | ;; forwarded at the end of it (or end of buffer if its not closed) |
| 1089 | (let ((context-type (python-info-ppss-context-type))) | 1123 | (let ((context-type (python-syntax-context-type))) |
| 1090 | (when (memq context-type '(paren string)) | 1124 | (when (memq context-type '(paren string)) |
| 1091 | ;; Slow but safe. | 1125 | ;; Slow but safe. |
| 1092 | (while (and (not (eobp)) | 1126 | (while (and (not (eobp)) |
| 1093 | (python-info-ppss-context-type)) | 1127 | (python-syntax-context-type)) |
| 1094 | (forward-line 1))))))) | 1128 | (forward-line 1))))))) |
| 1095 | 1129 | ||
| 1096 | (defun python-nav-beginning-of-statement () | 1130 | (defun python-nav-beginning-of-statement () |
| @@ -1102,8 +1136,8 @@ Returns nil if point is not in a def or class." | |||
| 1102 | (save-excursion | 1136 | (save-excursion |
| 1103 | (forward-line -1) | 1137 | (forward-line -1) |
| 1104 | (python-info-line-ends-backslash-p)) | 1138 | (python-info-line-ends-backslash-p)) |
| 1105 | (python-info-ppss-context 'string) | 1139 | (python-syntax-context 'string) |
| 1106 | (python-info-ppss-context 'paren)) | 1140 | (python-syntax-context 'paren)) |
| 1107 | (forward-line -1))))) | 1141 | (forward-line -1))))) |
| 1108 | 1142 | ||
| 1109 | (defun python-nav-end-of-statement () | 1143 | (defun python-nav-end-of-statement () |
| @@ -1113,8 +1147,8 @@ Returns nil if point is not in a def or class." | |||
| 1113 | (not (eobp)) | 1147 | (not (eobp)) |
| 1114 | (when (or | 1148 | (when (or |
| 1115 | (python-info-line-ends-backslash-p) | 1149 | (python-info-line-ends-backslash-p) |
| 1116 | (python-info-ppss-context 'string) | 1150 | (python-syntax-context 'string) |
| 1117 | (python-info-ppss-context 'paren)) | 1151 | (python-syntax-context 'paren)) |
| 1118 | (forward-line 1))))) | 1152 | (forward-line 1))))) |
| 1119 | 1153 | ||
| 1120 | (defun python-nav-backward-statement (&optional arg) | 1154 | (defun python-nav-backward-statement (&optional arg) |
| @@ -1202,96 +1236,191 @@ backward to previous block." | |||
| 1202 | (python-nav-end-of-statement) | 1236 | (python-nav-end-of-statement) |
| 1203 | (while (and | 1237 | (while (and |
| 1204 | (re-search-forward block-start-regexp nil t) | 1238 | (re-search-forward block-start-regexp nil t) |
| 1205 | (python-info-ppss-context-type))) | 1239 | (python-syntax-context-type))) |
| 1206 | (setq arg (1- arg))) | 1240 | (setq arg (1- arg))) |
| 1207 | (while (< arg 0) | 1241 | (while (< arg 0) |
| 1208 | (python-nav-beginning-of-statement) | 1242 | (python-nav-beginning-of-statement) |
| 1209 | (while (and | 1243 | (while (and |
| 1210 | (re-search-backward block-start-regexp nil t) | 1244 | (re-search-backward block-start-regexp nil t) |
| 1211 | (python-info-ppss-context-type))) | 1245 | (python-syntax-context-type))) |
| 1212 | (setq arg (1+ arg))) | 1246 | (setq arg (1+ arg))) |
| 1213 | (python-nav-beginning-of-statement) | 1247 | (python-nav-beginning-of-statement) |
| 1214 | (if (not (looking-at (python-rx block-start))) | 1248 | (if (not (looking-at (python-rx block-start))) |
| 1215 | (and (goto-char starting-pos) nil) | 1249 | (and (goto-char starting-pos) nil) |
| 1216 | (and (not (= (point) starting-pos)) (point-marker))))) | 1250 | (and (not (= (point) starting-pos)) (point-marker))))) |
| 1217 | 1251 | ||
| 1218 | (defun python-nav-forward-sexp-function (&optional arg) | 1252 | (defun python-nav-lisp-forward-sexp-safe (&optional arg) |
| 1253 | "Safe version of standard `forward-sexp'. | ||
| 1254 | When ARG > 0 move forward, else if ARG is < 0." | ||
| 1255 | (or arg (setq arg 1)) | ||
| 1256 | (let ((forward-sexp-function nil) | ||
| 1257 | (paren-regexp | ||
| 1258 | (if (> arg 0) (python-rx close-paren) (python-rx open-paren))) | ||
| 1259 | (search-fn | ||
| 1260 | (if (> arg 0) #'re-search-forward #'re-search-backward))) | ||
| 1261 | (condition-case nil | ||
| 1262 | (forward-sexp arg) | ||
| 1263 | (error | ||
| 1264 | (while (and (funcall search-fn paren-regexp nil t) | ||
| 1265 | (python-syntax-context 'paren))))))) | ||
| 1266 | |||
| 1267 | (defun python-nav--forward-sexp () | ||
| 1268 | "Move to forward sexp." | ||
| 1269 | (case (python-syntax-context-type) | ||
| 1270 | (string | ||
| 1271 | ;; Inside of a string, get out of it. | ||
| 1272 | (while (and (re-search-forward "[\"']" nil t) | ||
| 1273 | (python-syntax-context 'string)))) | ||
| 1274 | (comment | ||
| 1275 | ;; Inside of a comment, just move forward. | ||
| 1276 | (python-util-forward-comment)) | ||
| 1277 | (paren | ||
| 1278 | (python-nav-lisp-forward-sexp-safe 1)) | ||
| 1279 | (t | ||
| 1280 | (if (and (not (eobp)) | ||
| 1281 | (= (syntax-class (syntax-after (point))) 4)) | ||
| 1282 | ;; Looking an open-paren | ||
| 1283 | (python-nav-lisp-forward-sexp-safe 1) | ||
| 1284 | (let ((block-starting-pos | ||
| 1285 | (save-excursion (python-nav-beginning-of-block))) | ||
| 1286 | (block-ending-pos | ||
| 1287 | (save-excursion (python-nav-end-of-block))) | ||
| 1288 | (next-block-starting-pos | ||
| 1289 | (save-excursion (python-nav-forward-block)))) | ||
| 1290 | (cond | ||
| 1291 | ((not block-starting-pos) | ||
| 1292 | ;; Not inside a block, move to closest one. | ||
| 1293 | (and next-block-starting-pos | ||
| 1294 | (goto-char next-block-starting-pos))) | ||
| 1295 | ((= (point) block-starting-pos) | ||
| 1296 | ;; Point is at beginning of block | ||
| 1297 | (if (and next-block-starting-pos | ||
| 1298 | (< next-block-starting-pos block-ending-pos)) | ||
| 1299 | ;; Beginning of next block is closer than current's | ||
| 1300 | ;; end, move to it. | ||
| 1301 | (goto-char next-block-starting-pos) | ||
| 1302 | (goto-char block-ending-pos))) | ||
| 1303 | ((= block-ending-pos (point)) | ||
| 1304 | ;; Point is at end of current block | ||
| 1305 | (let ((parent-block-end-pos | ||
| 1306 | (save-excursion | ||
| 1307 | (python-util-forward-comment) | ||
| 1308 | (python-nav-beginning-of-block) | ||
| 1309 | (python-nav-end-of-block)))) | ||
| 1310 | (if (and parent-block-end-pos | ||
| 1311 | (or (not next-block-starting-pos) | ||
| 1312 | (> next-block-starting-pos parent-block-end-pos))) | ||
| 1313 | ;; If the parent block ends before next block | ||
| 1314 | ;; starts move to it. | ||
| 1315 | (goto-char parent-block-end-pos) | ||
| 1316 | (and next-block-starting-pos | ||
| 1317 | (goto-char next-block-starting-pos))))) | ||
| 1318 | (t (python-nav-end-of-block)))))))) | ||
| 1319 | |||
| 1320 | (defun python-nav--backward-sexp () | ||
| 1321 | "Move to backward sexp." | ||
| 1322 | (case (python-syntax-context-type) | ||
| 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 | |||
| 1413 | (defun python-nav-forward-sexp (&optional arg) | ||
| 1219 | "Move forward across one block of code. | 1414 | "Move forward across one block of code. |
| 1220 | With ARG, do it that many times. Negative arg -N means | 1415 | With ARG, do it that many times. Negative arg -N means |
| 1221 | move backward N times." | 1416 | move backward N times." |
| 1222 | (interactive "^p") | 1417 | (interactive "^p") |
| 1223 | (or arg (setq arg 1)) | 1418 | (or arg (setq arg 1)) |
| 1224 | (while (> arg 0) | 1419 | (while (> arg 0) |
| 1225 | (let ((block-starting-pos | 1420 | (python-nav--forward-sexp) |
| 1226 | (save-excursion (python-nav-beginning-of-block))) | 1421 | (setq arg (1- arg))) |
| 1227 | (block-ending-pos | ||
| 1228 | (save-excursion (python-nav-end-of-block))) | ||
| 1229 | (next-block-starting-pos | ||
| 1230 | (save-excursion (python-nav-forward-block)))) | ||
| 1231 | (cond ((not block-starting-pos) | ||
| 1232 | (python-nav-forward-block)) | ||
| 1233 | ((= (point) block-starting-pos) | ||
| 1234 | (if (or (not next-block-starting-pos) | ||
| 1235 | (< block-ending-pos next-block-starting-pos)) | ||
| 1236 | (python-nav-end-of-block) | ||
| 1237 | (python-nav-forward-block))) | ||
| 1238 | ((= block-ending-pos (point)) | ||
| 1239 | (let ((parent-block-end-pos | ||
| 1240 | (save-excursion | ||
| 1241 | (python-util-forward-comment) | ||
| 1242 | (python-nav-beginning-of-block) | ||
| 1243 | (python-nav-end-of-block)))) | ||
| 1244 | (if (and parent-block-end-pos | ||
| 1245 | (or (not next-block-starting-pos) | ||
| 1246 | (> next-block-starting-pos parent-block-end-pos))) | ||
| 1247 | (goto-char parent-block-end-pos) | ||
| 1248 | (python-nav-forward-block)))) | ||
| 1249 | (t (python-nav-end-of-block)))) | ||
| 1250 | (setq arg (1- arg))) | ||
| 1251 | (while (< arg 0) | 1422 | (while (< arg 0) |
| 1252 | (let* ((block-starting-pos | 1423 | (python-nav--backward-sexp) |
| 1253 | (save-excursion (python-nav-beginning-of-block))) | ||
| 1254 | (block-ending-pos | ||
| 1255 | (save-excursion (python-nav-end-of-block))) | ||
| 1256 | (prev-block-ending-pos | ||
| 1257 | (save-excursion (when (python-nav-backward-block) | ||
| 1258 | (python-nav-end-of-block)))) | ||
| 1259 | (prev-block-parent-ending-pos | ||
| 1260 | (save-excursion | ||
| 1261 | (when prev-block-ending-pos | ||
| 1262 | (goto-char prev-block-ending-pos) | ||
| 1263 | (python-util-forward-comment) | ||
| 1264 | (python-nav-beginning-of-block) | ||
| 1265 | (python-nav-end-of-block))))) | ||
| 1266 | (cond ((not block-ending-pos) | ||
| 1267 | (and (python-nav-backward-block) | ||
| 1268 | (python-nav-end-of-block))) | ||
| 1269 | ((= (point) block-ending-pos) | ||
| 1270 | (let ((candidates)) | ||
| 1271 | (dolist (name | ||
| 1272 | '(prev-block-parent-ending-pos | ||
| 1273 | prev-block-ending-pos | ||
| 1274 | block-ending-pos | ||
| 1275 | block-starting-pos)) | ||
| 1276 | (when (and (symbol-value name) | ||
| 1277 | (< (symbol-value name) (point))) | ||
| 1278 | (add-to-list 'candidates (symbol-value name)))) | ||
| 1279 | (goto-char (apply 'max candidates)))) | ||
| 1280 | ((> (point) block-ending-pos) | ||
| 1281 | (python-nav-end-of-block)) | ||
| 1282 | ((= (point) block-starting-pos) | ||
| 1283 | (if (not (> (point) (or prev-block-ending-pos (point)))) | ||
| 1284 | (python-nav-backward-block) | ||
| 1285 | (goto-char prev-block-ending-pos) | ||
| 1286 | (let ((parent-block-ending-pos | ||
| 1287 | (save-excursion | ||
| 1288 | (python-nav-forward-sexp-function) | ||
| 1289 | (and (not (looking-at (python-rx block-start))) | ||
| 1290 | (point))))) | ||
| 1291 | (when (and parent-block-ending-pos | ||
| 1292 | (> parent-block-ending-pos prev-block-ending-pos)) | ||
| 1293 | (goto-char parent-block-ending-pos))))) | ||
| 1294 | (t (python-nav-beginning-of-block)))) | ||
| 1295 | (setq arg (1+ arg)))) | 1424 | (setq arg (1+ arg)))) |
| 1296 | 1425 | ||
| 1297 | 1426 | ||
| @@ -1420,16 +1549,12 @@ virtualenv." | |||
| 1420 | If DEDICATED is t and the variable `buffer-file-name' is non-nil | 1549 | If DEDICATED is t and the variable `buffer-file-name' is non-nil |
| 1421 | returns a string with the form | 1550 | returns a string with the form |
| 1422 | `python-shell-buffer-name'[variable `buffer-file-name'] else | 1551 | `python-shell-buffer-name'[variable `buffer-file-name'] else |
| 1423 | returns the value of `python-shell-buffer-name'. After | 1552 | returns the value of `python-shell-buffer-name'." |
| 1424 | calculating the process name adds the buffer name for the process | ||
| 1425 | in the `same-window-buffer-names' list." | ||
| 1426 | (let ((process-name | 1553 | (let ((process-name |
| 1427 | (if (and dedicated | 1554 | (if (and dedicated |
| 1428 | buffer-file-name) | 1555 | buffer-file-name) |
| 1429 | (format "%s[%s]" python-shell-buffer-name buffer-file-name) | 1556 | (format "%s[%s]" python-shell-buffer-name buffer-file-name) |
| 1430 | (format "%s" python-shell-buffer-name)))) | 1557 | (format "%s" python-shell-buffer-name)))) |
| 1431 | (add-to-list 'same-window-buffer-names (purecopy | ||
| 1432 | (format "*%s*" process-name))) | ||
| 1433 | process-name)) | 1558 | process-name)) |
| 1434 | 1559 | ||
| 1435 | (defun python-shell-internal-get-process-name () | 1560 | (defun python-shell-internal-get-process-name () |
| @@ -1539,6 +1664,9 @@ variable. | |||
| 1539 | 'python-shell-completion-complete-at-point) | 1664 | 'python-shell-completion-complete-at-point) |
| 1540 | (define-key inferior-python-mode-map "\t" | 1665 | (define-key inferior-python-mode-map "\t" |
| 1541 | 'python-shell-completion-complete-or-indent) | 1666 | 'python-shell-completion-complete-or-indent) |
| 1667 | (make-local-variable 'python-pdbtrack-buffers-to-kill) | ||
| 1668 | (make-local-variable 'python-pdbtrack-tracked-buffer) | ||
| 1669 | (make-local-variable 'python-shell-internal-last-output) | ||
| 1542 | (when python-shell-enable-font-lock | 1670 | (when python-shell-enable-font-lock |
| 1543 | (set (make-local-variable 'font-lock-defaults) | 1671 | (set (make-local-variable 'font-lock-defaults) |
| 1544 | '(python-font-lock-keywords nil nil nil nil)) | 1672 | '(python-font-lock-keywords nil nil nil nil)) |
| @@ -1546,26 +1674,34 @@ variable. | |||
| 1546 | python-syntax-propertize-function)) | 1674 | python-syntax-propertize-function)) |
| 1547 | (compilation-shell-minor-mode 1)) | 1675 | (compilation-shell-minor-mode 1)) |
| 1548 | 1676 | ||
| 1549 | (defun python-shell-make-comint (cmd proc-name &optional pop) | 1677 | (defun python-shell-make-comint (cmd proc-name &optional pop internal) |
| 1550 | "Create a python shell comint buffer. | 1678 | "Create a python shell comint buffer. |
| 1551 | CMD is the python command to be executed and PROC-NAME is the | 1679 | CMD is the python command to be executed and PROC-NAME is the |
| 1552 | process name the comint buffer will get. After the comint buffer | 1680 | process name the comint buffer will get. After the comint buffer |
| 1553 | is created the `inferior-python-mode' is activated. If POP is | 1681 | is created the `inferior-python-mode' is activated. When |
| 1554 | non-nil the buffer is shown." | 1682 | optional argument POP is non-nil the buffer is shown. When |
| 1683 | optional argument INTERNAL is non-nil this process is run on a | ||
| 1684 | buffer with a name that starts with a space, following the Emacs | ||
| 1685 | convention for temporary/internal buffers, and also makes sure | ||
| 1686 | the user is not queried for confirmation when the process is | ||
| 1687 | killed." | ||
| 1555 | (save-excursion | 1688 | (save-excursion |
| 1556 | (let* ((proc-buffer-name (format "*%s*" proc-name)) | 1689 | (let* ((proc-buffer-name |
| 1690 | (format (if (not internal) "*%s*" " *%s*") proc-name)) | ||
| 1557 | (process-environment (python-shell-calculate-process-environment)) | 1691 | (process-environment (python-shell-calculate-process-environment)) |
| 1558 | (exec-path (python-shell-calculate-exec-path))) | 1692 | (exec-path (python-shell-calculate-exec-path))) |
| 1559 | (when (not (comint-check-proc proc-buffer-name)) | 1693 | (when (not (comint-check-proc proc-buffer-name)) |
| 1560 | (let* ((cmdlist (split-string-and-unquote cmd)) | 1694 | (let* ((cmdlist (split-string-and-unquote cmd)) |
| 1561 | (buffer (apply 'make-comint proc-name (car cmdlist) nil | 1695 | (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name |
| 1562 | (cdr cmdlist))) | 1696 | (car cmdlist) nil (cdr cmdlist))) |
| 1563 | (current-buffer (current-buffer))) | 1697 | (current-buffer (current-buffer)) |
| 1698 | (process (get-buffer-process buffer))) | ||
| 1564 | (with-current-buffer buffer | 1699 | (with-current-buffer buffer |
| 1565 | (inferior-python-mode) | 1700 | (inferior-python-mode) |
| 1566 | (python-util-clone-local-variables current-buffer)) | 1701 | (python-util-clone-local-variables current-buffer)) |
| 1567 | (accept-process-output (get-buffer-process buffer)))) | 1702 | (accept-process-output process) |
| 1568 | (and pop (pop-to-buffer proc-buffer-name t)) | 1703 | (and pop (pop-to-buffer buffer t)) |
| 1704 | (and internal (set-process-query-on-exit-flag process nil)))) | ||
| 1569 | proc-buffer-name))) | 1705 | proc-buffer-name))) |
| 1570 | 1706 | ||
| 1571 | ;;;###autoload | 1707 | ;;;###autoload |
| @@ -1611,11 +1747,10 @@ are set to nil for these shells, so setup codes are not sent at | |||
| 1611 | startup." | 1747 | startup." |
| 1612 | (let ((python-shell-enable-font-lock nil) | 1748 | (let ((python-shell-enable-font-lock nil) |
| 1613 | (inferior-python-mode-hook nil)) | 1749 | (inferior-python-mode-hook nil)) |
| 1614 | (set-process-query-on-exit-flag | 1750 | (get-buffer-process |
| 1615 | (get-buffer-process | 1751 | (python-shell-make-comint |
| 1616 | (python-shell-make-comint | 1752 | (python-shell-parse-command) |
| 1617 | (python-shell-parse-command) | 1753 | (python-shell-internal-get-process-name) nil t)))) |
| 1618 | (python-shell-internal-get-process-name))) nil))) | ||
| 1619 | 1754 | ||
| 1620 | (defun python-shell-get-process () | 1755 | (defun python-shell-get-process () |
| 1621 | "Get inferior Python process for current buffer and return it." | 1756 | "Get inferior Python process for current buffer and return it." |
| @@ -1651,18 +1786,16 @@ startup." | |||
| 1651 | "Current internal shell buffer for the current buffer. | 1786 | "Current internal shell buffer for the current buffer. |
| 1652 | This is really not necessary at all for the code to work but it's | 1787 | This is really not necessary at all for the code to work but it's |
| 1653 | there for compatibility with CEDET.") | 1788 | there for compatibility with CEDET.") |
| 1654 | (make-variable-buffer-local 'python-shell-internal-buffer) | ||
| 1655 | 1789 | ||
| 1656 | (defvar python-shell-internal-last-output nil | 1790 | (defvar python-shell-internal-last-output nil |
| 1657 | "Last output captured by the internal shell. | 1791 | "Last output captured by the internal shell. |
| 1658 | This is really not necessary at all for the code to work but it's | 1792 | This is really not necessary at all for the code to work but it's |
| 1659 | there for compatibility with CEDET.") | 1793 | there for compatibility with CEDET.") |
| 1660 | (make-variable-buffer-local 'python-shell-internal-last-output) | ||
| 1661 | 1794 | ||
| 1662 | (defun python-shell-internal-get-or-create-process () | 1795 | (defun python-shell-internal-get-or-create-process () |
| 1663 | "Get or create an inferior Internal Python process." | 1796 | "Get or create an inferior Internal Python process." |
| 1664 | (let* ((proc-name (python-shell-internal-get-process-name)) | 1797 | (let* ((proc-name (python-shell-internal-get-process-name)) |
| 1665 | (proc-buffer-name (format "*%s*" proc-name))) | 1798 | (proc-buffer-name (format " *%s*" proc-name))) |
| 1666 | (when (not (process-live-p proc-name)) | 1799 | (when (not (process-live-p proc-name)) |
| 1667 | (run-python-internal) | 1800 | (run-python-internal) |
| 1668 | (setq python-shell-internal-buffer proc-buffer-name) | 1801 | (setq python-shell-internal-buffer proc-buffer-name) |
| @@ -1675,13 +1808,13 @@ there for compatibility with CEDET.") | |||
| 1675 | (get-buffer-process proc-buffer-name))) | 1808 | (get-buffer-process proc-buffer-name))) |
| 1676 | 1809 | ||
| 1677 | (define-obsolete-function-alias | 1810 | (define-obsolete-function-alias |
| 1678 | 'python-proc 'python-shell-internal-get-or-create-process "24.2") | 1811 | 'python-proc 'python-shell-internal-get-or-create-process "24.3") |
| 1679 | 1812 | ||
| 1680 | (define-obsolete-variable-alias | 1813 | (define-obsolete-variable-alias |
| 1681 | 'python-buffer 'python-shell-internal-buffer "24.2") | 1814 | 'python-buffer 'python-shell-internal-buffer "24.3") |
| 1682 | 1815 | ||
| 1683 | (define-obsolete-variable-alias | 1816 | (define-obsolete-variable-alias |
| 1684 | 'python-preoutput-result 'python-shell-internal-last-output "24.2") | 1817 | 'python-preoutput-result 'python-shell-internal-last-output "24.3") |
| 1685 | 1818 | ||
| 1686 | (defun python-shell-send-string (string &optional process msg) | 1819 | (defun python-shell-send-string (string &optional process msg) |
| 1687 | "Send STRING to inferior Python PROCESS. | 1820 | "Send STRING to inferior Python PROCESS. |
| @@ -1689,8 +1822,7 @@ When MSG is non-nil messages the first line of STRING." | |||
| 1689 | (interactive "sPython command: ") | 1822 | (interactive "sPython command: ") |
| 1690 | (let ((process (or process (python-shell-get-or-create-process))) | 1823 | (let ((process (or process (python-shell-get-or-create-process))) |
| 1691 | (lines (split-string string "\n" t))) | 1824 | (lines (split-string string "\n" t))) |
| 1692 | (when msg | 1825 | (and msg (message "Sent: %s..." (nth 0 lines))) |
| 1693 | (message (format "Sent: %s..." (nth 0 lines)))) | ||
| 1694 | (if (> (length lines) 1) | 1826 | (if (> (length lines) 1) |
| 1695 | (let* ((temp-file-name (make-temp-file "py")) | 1827 | (let* ((temp-file-name (make-temp-file "py")) |
| 1696 | (file-name (or (buffer-file-name) temp-file-name))) | 1828 | (file-name (or (buffer-file-name) temp-file-name))) |
| @@ -1744,10 +1876,10 @@ Returns the output. See `python-shell-send-string-no-output'." | |||
| 1744 | (python-shell-internal-get-or-create-process) nil))) | 1876 | (python-shell-internal-get-or-create-process) nil))) |
| 1745 | 1877 | ||
| 1746 | (define-obsolete-function-alias | 1878 | (define-obsolete-function-alias |
| 1747 | 'python-send-receive 'python-shell-internal-send-string "24.2") | 1879 | 'python-send-receive 'python-shell-internal-send-string "24.3") |
| 1748 | 1880 | ||
| 1749 | (define-obsolete-function-alias | 1881 | (define-obsolete-function-alias |
| 1750 | 'python-send-string 'python-shell-internal-send-string "24.2") | 1882 | 'python-send-string 'python-shell-internal-send-string "24.3") |
| 1751 | 1883 | ||
| 1752 | (defun python-shell-send-region (start end) | 1884 | (defun python-shell-send-region (start end) |
| 1753 | "Send the region delimited by START and END to inferior Python process." | 1885 | "Send the region delimited by START and END to inferior Python process." |
| @@ -1820,11 +1952,10 @@ FILE-NAME." | |||
| 1820 | "Send all setup code for shell. | 1952 | "Send all setup code for shell. |
| 1821 | This function takes the list of setup code to send from the | 1953 | This function takes the list of setup code to send from the |
| 1822 | `python-shell-setup-codes' list." | 1954 | `python-shell-setup-codes' list." |
| 1823 | (let ((msg "Sent %s") | 1955 | (let ((process (get-buffer-process (current-buffer)))) |
| 1824 | (process (get-buffer-process (current-buffer)))) | ||
| 1825 | (dolist (code python-shell-setup-codes) | 1956 | (dolist (code python-shell-setup-codes) |
| 1826 | (when code | 1957 | (when code |
| 1827 | (message (format msg code)) | 1958 | (message "Sent %s" code) |
| 1828 | (python-shell-send-string | 1959 | (python-shell-send-string |
| 1829 | (symbol-value code) process))))) | 1960 | (symbol-value code) process))))) |
| 1830 | 1961 | ||
| @@ -1885,27 +2016,71 @@ and use the following as the value of this variable: | |||
| 1885 | :type 'string | 2016 | :type 'string |
| 1886 | :group 'python) | 2017 | :group 'python) |
| 1887 | 2018 | ||
| 1888 | (defun python-shell-completion--get-completions (input process completion-code) | 2019 | (defun python-shell-completion-get-completions (process line input) |
| 1889 | "Retrieve available completions for INPUT using PROCESS. | 2020 | "Do completion at point for PROCESS. |
| 1890 | Argument COMPLETION-CODE is the python code used to get | 2021 | LINE is used to detect the context on how to complete given |
| 1891 | completions on the current context." | 2022 | INPUT." |
| 1892 | (with-current-buffer (process-buffer process) | 2023 | (let* ((prompt |
| 1893 | (let ((completions (python-shell-send-string-no-output | 2024 | ;; Get the last prompt for the inferior process |
| 1894 | (format completion-code input) process))) | 2025 | ;; buffer. This is used for the completion code selection |
| 1895 | (when (> (length completions) 2) | 2026 | ;; heuristic. |
| 1896 | (split-string completions "^'\\|^\"\\|;\\|'$\\|\"$" t))))) | 2027 | (with-current-buffer (process-buffer process) |
| 1897 | 2028 | (buffer-substring-no-properties | |
| 1898 | (defun python-shell-completion--do-completion-at-point (process) | 2029 | (overlay-start comint-last-prompt-overlay) |
| 1899 | "Do completion at point for PROCESS." | 2030 | (overlay-end comint-last-prompt-overlay)))) |
| 1900 | (with-syntax-table python-dotty-syntax-table | 2031 | (completion-context |
| 1901 | (let* ((beg | 2032 | ;; Check whether a prompt matches a pdb string, an import |
| 1902 | (save-excursion | 2033 | ;; statement or just the standard prompt and use the |
| 2034 | ;; correct python-shell-completion-*-code string | ||
| 2035 | (cond ((and (> (length python-shell-completion-pdb-string-code) 0) | ||
| 2036 | (string-match | ||
| 2037 | (concat "^" python-shell-prompt-pdb-regexp) prompt)) | ||
| 2038 | 'pdb) | ||
| 2039 | ((and (> | ||
| 2040 | (length python-shell-completion-module-string-code) 0) | ||
| 2041 | (string-match | ||
| 2042 | (concat "^" python-shell-prompt-regexp) prompt) | ||
| 2043 | (string-match "^[ \t]*\\(from\\|import\\)[ \t]" line)) | ||
| 2044 | 'import) | ||
| 2045 | ((string-match | ||
| 2046 | (concat "^" python-shell-prompt-regexp) prompt) | ||
| 2047 | 'default) | ||
| 2048 | (t nil))) | ||
| 2049 | (completion-code | ||
| 2050 | (case completion-context | ||
| 2051 | (pdb python-shell-completion-pdb-string-code) | ||
| 2052 | (import python-shell-completion-module-string-code) | ||
| 2053 | (default python-shell-completion-string-code) | ||
| 2054 | (t nil))) | ||
| 2055 | (input | ||
| 2056 | (if (eq completion-context 'import) | ||
| 2057 | (replace-regexp-in-string "^[ \t]+" "" line) | ||
| 2058 | input))) | ||
| 2059 | (and completion-code | ||
| 2060 | (> (length input) 0) | ||
| 2061 | (with-current-buffer (process-buffer process) | ||
| 2062 | (let ((completions (python-shell-send-string-no-output | ||
| 2063 | (format completion-code input) process))) | ||
| 2064 | (and (> (length completions) 2) | ||
| 2065 | (split-string completions | ||
| 2066 | "^'\\|^\"\\|;\\|'$\\|\"$" t))))))) | ||
| 2067 | |||
| 2068 | (defun python-shell-completion-complete-at-point (&optional process) | ||
| 2069 | "Perform completion at point in inferior Python. | ||
| 2070 | Optional argument PROCESS forces completions to be retrieved | ||
| 2071 | using that one instead of current buffer's process." | ||
| 2072 | (setq process (or process (get-buffer-process (current-buffer)))) | ||
| 2073 | (let* ((start | ||
| 2074 | (save-excursion | ||
| 2075 | (with-syntax-table python-dotty-syntax-table | ||
| 1903 | (let* ((paren-depth (car (syntax-ppss))) | 2076 | (let* ((paren-depth (car (syntax-ppss))) |
| 1904 | (syntax-string "w_") | 2077 | (syntax-string "w_") |
| 1905 | (syntax-list (string-to-syntax syntax-string))) | 2078 | (syntax-list (string-to-syntax syntax-string))) |
| 1906 | ;; Stop scanning for the beginning of the completion subject | 2079 | ;; Stop scanning for the beginning of the completion |
| 1907 | ;; after the char before point matches a delimiter | 2080 | ;; subject after the char before point matches a |
| 1908 | (while (member (car (syntax-after (1- (point)))) syntax-list) | 2081 | ;; delimiter |
| 2082 | (while (member | ||
| 2083 | (car (syntax-after (1- (point)))) syntax-list) | ||
| 1909 | (skip-syntax-backward syntax-string) | 2084 | (skip-syntax-backward syntax-string) |
| 1910 | (when (or (equal (char-before) ?\)) | 2085 | (when (or (equal (char-before) ?\)) |
| 1911 | (equal (char-before) ?\")) | 2086 | (equal (char-before) ?\")) |
| @@ -1913,59 +2088,16 @@ completions on the current context." | |||
| 1913 | (while (or | 2088 | (while (or |
| 1914 | ;; honor initial paren depth | 2089 | ;; honor initial paren depth |
| 1915 | (> (car (syntax-ppss)) paren-depth) | 2090 | (> (car (syntax-ppss)) paren-depth) |
| 1916 | (python-info-ppss-context 'string)) | 2091 | (python-syntax-context 'string)) |
| 1917 | (forward-char -1)))) | 2092 | (forward-char -1))) |
| 1918 | (point))) | 2093 | (point))))) |
| 1919 | (end (point)) | 2094 | (end (point))) |
| 1920 | (line (buffer-substring-no-properties (point-at-bol) end)) | 2095 | (list start end |
| 1921 | (input (buffer-substring-no-properties beg end)) | 2096 | (completion-table-dynamic |
| 1922 | ;; Get the last prompt for the inferior process buffer. This is | 2097 | (apply-partially |
| 1923 | ;; used for the completion code selection heuristic. | 2098 | #'python-shell-completion-get-completions |
| 1924 | (prompt | 2099 | process (buffer-substring-no-properties |
| 1925 | (with-current-buffer (process-buffer process) | 2100 | (line-beginning-position) end)))))) |
| 1926 | (buffer-substring-no-properties | ||
| 1927 | (overlay-start comint-last-prompt-overlay) | ||
| 1928 | (overlay-end comint-last-prompt-overlay)))) | ||
| 1929 | (completion-context | ||
| 1930 | ;; Check whether a prompt matches a pdb string, an import statement | ||
| 1931 | ;; or just the standard prompt and use the correct | ||
| 1932 | ;; python-shell-completion-*-code string | ||
| 1933 | (cond ((and (> (length python-shell-completion-pdb-string-code) 0) | ||
| 1934 | (string-match | ||
| 1935 | (concat "^" python-shell-prompt-pdb-regexp) prompt)) | ||
| 1936 | 'pdb) | ||
| 1937 | ((and (> | ||
| 1938 | (length python-shell-completion-module-string-code) 0) | ||
| 1939 | (string-match | ||
| 1940 | (concat "^" python-shell-prompt-regexp) prompt) | ||
| 1941 | (string-match "^[ \t]*\\(from\\|import\\)[ \t]" line)) | ||
| 1942 | 'import) | ||
| 1943 | ((string-match | ||
| 1944 | (concat "^" python-shell-prompt-regexp) prompt) | ||
| 1945 | 'default) | ||
| 1946 | (t nil))) | ||
| 1947 | (completion-code | ||
| 1948 | (case completion-context | ||
| 1949 | ('pdb python-shell-completion-pdb-string-code) | ||
| 1950 | ('import python-shell-completion-module-string-code) | ||
| 1951 | ('default python-shell-completion-string-code) | ||
| 1952 | (t nil))) | ||
| 1953 | (input | ||
| 1954 | (if (eq completion-context 'import) | ||
| 1955 | (replace-regexp-in-string "^[ \t]+" "" line) | ||
| 1956 | input)) | ||
| 1957 | (completions | ||
| 1958 | (and completion-code (> (length input) 0) | ||
| 1959 | (python-shell-completion--get-completions | ||
| 1960 | input process completion-code)))) | ||
| 1961 | (list beg end completions)))) | ||
| 1962 | |||
| 1963 | (defun python-shell-completion-complete-at-point () | ||
| 1964 | "Perform completion at point in inferior Python process." | ||
| 1965 | (and comint-last-prompt-overlay | ||
| 1966 | (> (point-marker) (overlay-end comint-last-prompt-overlay)) | ||
| 1967 | (python-shell-completion--do-completion-at-point | ||
| 1968 | (get-buffer-process (current-buffer))))) | ||
| 1969 | 2101 | ||
| 1970 | (defun python-shell-completion-complete-or-indent () | 2102 | (defun python-shell-completion-complete-or-indent () |
| 1971 | "Complete or indent depending on the context. | 2103 | "Complete or indent depending on the context. |
| @@ -1999,11 +2131,9 @@ Used to extract the current line and module being inspected." | |||
| 1999 | "Variable containing the value of the current tracked buffer. | 2131 | "Variable containing the value of the current tracked buffer. |
| 2000 | Never set this variable directly, use | 2132 | Never set this variable directly, use |
| 2001 | `python-pdbtrack-set-tracked-buffer' instead.") | 2133 | `python-pdbtrack-set-tracked-buffer' instead.") |
| 2002 | (make-variable-buffer-local 'python-pdbtrack-tracked-buffer) | ||
| 2003 | 2134 | ||
| 2004 | (defvar python-pdbtrack-buffers-to-kill nil | 2135 | (defvar python-pdbtrack-buffers-to-kill nil |
| 2005 | "List of buffers to be deleted after tracking finishes.") | 2136 | "List of buffers to be deleted after tracking finishes.") |
| 2006 | (make-variable-buffer-local 'python-pdbtrack-buffers-to-kill) | ||
| 2007 | 2137 | ||
| 2008 | (defun python-pdbtrack-set-tracked-buffer (file-name) | 2138 | (defun python-pdbtrack-set-tracked-buffer (file-name) |
| 2009 | "Set the buffer for FILE-NAME as the tracked buffer. | 2139 | "Set the buffer for FILE-NAME as the tracked buffer. |
| @@ -2079,7 +2209,7 @@ inferior python process is updated properly." | |||
| 2079 | (let ((process (python-shell-get-process))) | 2209 | (let ((process (python-shell-get-process))) |
| 2080 | (if (not process) | 2210 | (if (not process) |
| 2081 | (error "Completion needs an inferior Python process running") | 2211 | (error "Completion needs an inferior Python process running") |
| 2082 | (python-shell-completion--do-completion-at-point process)))) | 2212 | (python-shell-completion-complete-at-point process)))) |
| 2083 | 2213 | ||
| 2084 | (add-to-list 'debug-ignored-errors | 2214 | (add-to-list 'debug-ignored-errors |
| 2085 | "^Completion needs an inferior Python process running.") | 2215 | "^Completion needs an inferior Python process running.") |
| @@ -2133,7 +2263,7 @@ Optional argument JUSTIFY defines if the paragraph should be justified." | |||
| 2133 | ((funcall python-fill-comment-function justify)) | 2263 | ((funcall python-fill-comment-function justify)) |
| 2134 | ;; Strings/Docstrings | 2264 | ;; Strings/Docstrings |
| 2135 | ((save-excursion (skip-chars-forward "\"'uUrR") | 2265 | ((save-excursion (skip-chars-forward "\"'uUrR") |
| 2136 | (python-info-ppss-context 'string)) | 2266 | (python-syntax-context 'string)) |
| 2137 | (funcall python-fill-string-function justify)) | 2267 | (funcall python-fill-string-function justify)) |
| 2138 | ;; Decorators | 2268 | ;; Decorators |
| 2139 | ((equal (char-after (save-excursion | 2269 | ((equal (char-after (save-excursion |
| @@ -2141,7 +2271,7 @@ Optional argument JUSTIFY defines if the paragraph should be justified." | |||
| 2141 | (point-marker))) ?@) | 2271 | (point-marker))) ?@) |
| 2142 | (funcall python-fill-decorator-function justify)) | 2272 | (funcall python-fill-decorator-function justify)) |
| 2143 | ;; Parens | 2273 | ;; Parens |
| 2144 | ((or (python-info-ppss-context 'paren) | 2274 | ((or (python-syntax-context 'paren) |
| 2145 | (looking-at (python-rx open-paren)) | 2275 | (looking-at (python-rx open-paren)) |
| 2146 | (save-excursion | 2276 | (save-excursion |
| 2147 | (skip-syntax-forward "^(" (line-end-position)) | 2277 | (skip-syntax-forward "^(" (line-end-position)) |
| @@ -2161,13 +2291,13 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'." | |||
| 2161 | (string-start-marker | 2291 | (string-start-marker |
| 2162 | (progn | 2292 | (progn |
| 2163 | (skip-chars-forward "\"'uUrR") | 2293 | (skip-chars-forward "\"'uUrR") |
| 2164 | (goto-char (python-info-ppss-context 'string)) | 2294 | (goto-char (python-syntax-context 'string)) |
| 2165 | (skip-chars-forward "\"'uUrR") | 2295 | (skip-chars-forward "\"'uUrR") |
| 2166 | (point-marker))) | 2296 | (point-marker))) |
| 2167 | (reg-start (line-beginning-position)) | 2297 | (reg-start (line-beginning-position)) |
| 2168 | (string-end-marker | 2298 | (string-end-marker |
| 2169 | (progn | 2299 | (progn |
| 2170 | (while (python-info-ppss-context 'string) | 2300 | (while (python-syntax-context 'string) |
| 2171 | (goto-char (1+ (point-marker)))) | 2301 | (goto-char (1+ (point-marker)))) |
| 2172 | (skip-chars-backward "\"'") | 2302 | (skip-chars-backward "\"'") |
| 2173 | (point-marker))) | 2303 | (point-marker))) |
| @@ -2205,16 +2335,16 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'." | |||
| 2205 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2335 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." |
| 2206 | (save-restriction | 2336 | (save-restriction |
| 2207 | (narrow-to-region (progn | 2337 | (narrow-to-region (progn |
| 2208 | (while (python-info-ppss-context 'paren) | 2338 | (while (python-syntax-context 'paren) |
| 2209 | (goto-char (1- (point-marker)))) | 2339 | (goto-char (1- (point-marker)))) |
| 2210 | (point-marker) | 2340 | (point-marker) |
| 2211 | (line-beginning-position)) | 2341 | (line-beginning-position)) |
| 2212 | (progn | 2342 | (progn |
| 2213 | (when (not (python-info-ppss-context 'paren)) | 2343 | (when (not (python-syntax-context 'paren)) |
| 2214 | (end-of-line) | 2344 | (end-of-line) |
| 2215 | (when (not (python-info-ppss-context 'paren)) | 2345 | (when (not (python-syntax-context 'paren)) |
| 2216 | (skip-syntax-backward "^)"))) | 2346 | (skip-syntax-backward "^)"))) |
| 2217 | (while (python-info-ppss-context 'paren) | 2347 | (while (python-syntax-context 'paren) |
| 2218 | (goto-char (1+ (point-marker)))) | 2348 | (goto-char (1+ (point-marker)))) |
| 2219 | (point-marker))) | 2349 | (point-marker))) |
| 2220 | (let ((paragraph-start "\f\\|[ \t]*$") | 2350 | (let ((paragraph-start "\f\\|[ \t]*$") |
| @@ -2239,7 +2369,7 @@ the if condition." | |||
| 2239 | :safe 'booleanp) | 2369 | :safe 'booleanp) |
| 2240 | 2370 | ||
| 2241 | (define-obsolete-variable-alias | 2371 | (define-obsolete-variable-alias |
| 2242 | 'python-use-skeletons 'python-skeleton-autoinsert "24.2") | 2372 | 'python-use-skeletons 'python-skeleton-autoinsert "24.3") |
| 2243 | 2373 | ||
| 2244 | (defvar python-skeleton-available '() | 2374 | (defvar python-skeleton-available '() |
| 2245 | "Internal list of available skeletons.") | 2375 | "Internal list of available skeletons.") |
| @@ -2252,7 +2382,7 @@ the if condition." | |||
| 2252 | ;; Only expand in code. | 2382 | ;; Only expand in code. |
| 2253 | :enable-function (lambda () | 2383 | :enable-function (lambda () |
| 2254 | (and | 2384 | (and |
| 2255 | (not (python-info-ppss-comment-or-string-p)) | 2385 | (not (python-syntax-comment-or-string-p)) |
| 2256 | python-skeleton-autoinsert))) | 2386 | python-skeleton-autoinsert))) |
| 2257 | 2387 | ||
| 2258 | (defmacro python-skeleton-define (name doc &rest skel) | 2388 | (defmacro python-skeleton-define (name doc &rest skel) |
| @@ -2572,7 +2702,7 @@ not inside a defun." | |||
| 2572 | With optional argument REPLACE-SELF convert \"self\" to current | 2702 | With optional argument REPLACE-SELF convert \"self\" to current |
| 2573 | parent defun name." | 2703 | parent defun name." |
| 2574 | (let ((name | 2704 | (let ((name |
| 2575 | (and (not (python-info-ppss-comment-or-string-p)) | 2705 | (and (not (python-syntax-comment-or-string-p)) |
| 2576 | (with-syntax-table python-dotty-syntax-table | 2706 | (with-syntax-table python-dotty-syntax-table |
| 2577 | (let ((sym (symbol-at-point))) | 2707 | (let ((sym (symbol-at-point))) |
| 2578 | (and sym | 2708 | (and sym |
| @@ -2650,7 +2780,7 @@ With optional argument LINE-NUMBER, check that line instead." | |||
| 2650 | (goto-char line-number)) | 2780 | (goto-char line-number)) |
| 2651 | (while (and (not (eobp)) | 2781 | (while (and (not (eobp)) |
| 2652 | (goto-char (line-end-position)) | 2782 | (goto-char (line-end-position)) |
| 2653 | (python-info-ppss-context 'paren) | 2783 | (python-syntax-context 'paren) |
| 2654 | (not (equal (char-before (point)) ?\\))) | 2784 | (not (equal (char-before (point)) ?\\))) |
| 2655 | (forward-line 1)) | 2785 | (forward-line 1)) |
| 2656 | (when (equal (char-before) ?\\) | 2786 | (when (equal (char-before) ?\\) |
| @@ -2667,7 +2797,7 @@ Optional argument LINE-NUMBER forces the line number to check against." | |||
| 2667 | (when (python-info-line-ends-backslash-p) | 2797 | (when (python-info-line-ends-backslash-p) |
| 2668 | (while (save-excursion | 2798 | (while (save-excursion |
| 2669 | (goto-char (line-beginning-position)) | 2799 | (goto-char (line-beginning-position)) |
| 2670 | (python-info-ppss-context 'paren)) | 2800 | (python-syntax-context 'paren)) |
| 2671 | (forward-line -1)) | 2801 | (forward-line -1)) |
| 2672 | (back-to-indentation) | 2802 | (back-to-indentation) |
| 2673 | (point-marker))))) | 2803 | (point-marker))))) |
| @@ -2681,10 +2811,10 @@ where the continued line ends." | |||
| 2681 | (widen) | 2811 | (widen) |
| 2682 | (let* ((context-type (progn | 2812 | (let* ((context-type (progn |
| 2683 | (back-to-indentation) | 2813 | (back-to-indentation) |
| 2684 | (python-info-ppss-context-type))) | 2814 | (python-syntax-context-type))) |
| 2685 | (line-start (line-number-at-pos)) | 2815 | (line-start (line-number-at-pos)) |
| 2686 | (context-start (when context-type | 2816 | (context-start (when context-type |
| 2687 | (python-info-ppss-context context-type)))) | 2817 | (python-syntax-context context-type)))) |
| 2688 | (cond ((equal context-type 'paren) | 2818 | (cond ((equal context-type 'paren) |
| 2689 | ;; Lines inside a paren are always a continuation line | 2819 | ;; Lines inside a paren are always a continuation line |
| 2690 | ;; (except the first one). | 2820 | ;; (except the first one). |
| @@ -2729,41 +2859,13 @@ operator." | |||
| 2729 | assignment-operator | 2859 | assignment-operator |
| 2730 | not-simple-operator) | 2860 | not-simple-operator) |
| 2731 | (line-end-position) t) | 2861 | (line-end-position) t) |
| 2732 | (not (python-info-ppss-context-type)))) | 2862 | (not (python-syntax-context-type)))) |
| 2733 | (skip-syntax-forward "\s") | 2863 | (skip-syntax-forward "\s") |
| 2734 | (point-marker))))) | 2864 | (point-marker))))) |
| 2735 | 2865 | ||
| 2736 | (defun python-info-ppss-context (type &optional syntax-ppss) | ||
| 2737 | "Return non-nil if point is on TYPE using SYNTAX-PPSS. | ||
| 2738 | TYPE can be `comment', `string' or `paren'. It returns the start | ||
| 2739 | character address of the specified TYPE." | ||
| 2740 | (let ((ppss (or syntax-ppss (syntax-ppss)))) | ||
| 2741 | (case type | ||
| 2742 | (comment | ||
| 2743 | (and (nth 4 ppss) | ||
| 2744 | (nth 8 ppss))) | ||
| 2745 | (string | ||
| 2746 | (and (not (nth 4 ppss)) | ||
| 2747 | (nth 8 ppss))) | ||
| 2748 | (paren | ||
| 2749 | (nth 1 ppss)) | ||
| 2750 | (t nil)))) | ||
| 2751 | |||
| 2752 | (defun python-info-ppss-context-type (&optional syntax-ppss) | ||
| 2753 | "Return the context type using SYNTAX-PPSS. | ||
| 2754 | The type returned can be `comment', `string' or `paren'." | ||
| 2755 | (let ((ppss (or syntax-ppss (syntax-ppss)))) | ||
| 2756 | (cond | ||
| 2757 | ((nth 8 ppss) (if (nth 4 ppss) 'comment 'string)) | ||
| 2758 | ((nth 1 ppss) 'paren)))) | ||
| 2759 | |||
| 2760 | (defsubst python-info-ppss-comment-or-string-p () | ||
| 2761 | "Return non-nil if point is inside 'comment or 'string." | ||
| 2762 | (nth 8 (syntax-ppss))) | ||
| 2763 | |||
| 2764 | (defun python-info-looking-at-beginning-of-defun (&optional syntax-ppss) | 2866 | (defun python-info-looking-at-beginning-of-defun (&optional syntax-ppss) |
| 2765 | "Check if point is at `beginning-of-defun' using SYNTAX-PPSS." | 2867 | "Check if point is at `beginning-of-defun' using SYNTAX-PPSS." |
| 2766 | (and (not (python-info-ppss-context-type (or syntax-ppss (syntax-ppss)))) | 2868 | (and (not (python-syntax-context-type (or syntax-ppss (syntax-ppss)))) |
| 2767 | (save-excursion | 2869 | (save-excursion |
| 2768 | (beginning-of-line 1) | 2870 | (beginning-of-line 1) |
| 2769 | (looking-at python-nav-beginning-of-defun-regexp)))) | 2871 | (looking-at python-nav-beginning-of-defun-regexp)))) |
| @@ -2809,7 +2911,7 @@ to \"^python-\"." | |||
| 2809 | (defun python-util-forward-comment (&optional direction) | 2911 | (defun python-util-forward-comment (&optional direction) |
| 2810 | "Python mode specific version of `forward-comment'. | 2912 | "Python mode specific version of `forward-comment'. |
| 2811 | Optional argument DIRECTION defines the direction to move to." | 2913 | Optional argument DIRECTION defines the direction to move to." |
| 2812 | (let ((comment-start (python-info-ppss-context 'comment)) | 2914 | (let ((comment-start (python-syntax-context 'comment)) |
| 2813 | (factor (if (< (or direction 0) 0) | 2915 | (factor (if (< (or direction 0) 0) |
| 2814 | -99999 | 2916 | -99999 |
| 2815 | 99999))) | 2917 | 99999))) |
| @@ -2835,7 +2937,7 @@ if that value is non-nil." | |||
| 2835 | (set (make-local-variable 'parse-sexp-ignore-comments) t) | 2937 | (set (make-local-variable 'parse-sexp-ignore-comments) t) |
| 2836 | 2938 | ||
| 2837 | (set (make-local-variable 'forward-sexp-function) | 2939 | (set (make-local-variable 'forward-sexp-function) |
| 2838 | 'python-nav-forward-sexp-function) | 2940 | 'python-nav-forward-sexp) |
| 2839 | 2941 | ||
| 2840 | (set (make-local-variable 'font-lock-defaults) | 2942 | (set (make-local-variable 'font-lock-defaults) |
| 2841 | '(python-font-lock-keywords nil nil nil nil)) | 2943 | '(python-font-lock-keywords nil nil nil nil)) |
| @@ -2896,6 +2998,8 @@ if that value is non-nil." | |||
| 2896 | 2998 | ||
| 2897 | (python-skeleton-add-menu-items) | 2999 | (python-skeleton-add-menu-items) |
| 2898 | 3000 | ||
| 3001 | (make-local-variable 'python-shell-internal-buffer) | ||
| 3002 | |||
| 2899 | (when python-indent-guess-indent-offset | 3003 | (when python-indent-guess-indent-offset |
| 2900 | (python-indent-guess-indent-offset))) | 3004 | (python-indent-guess-indent-offset))) |
| 2901 | 3005 | ||