diff options
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 1270 |
1 files changed, 912 insertions, 358 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 743981b3714..d1dd9bef4bc 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | ;; Author: Fabián E. Gallina <fabian@anue.biz> | 5 | ;; Author: Fabián E. Gallina <fabian@anue.biz> |
| 6 | ;; URL: https://github.com/fgallina/python.el | 6 | ;; URL: https://github.com/fgallina/python.el |
| 7 | ;; Version: 0.24.2 | 7 | ;; Version: 0.24.4 |
| 8 | ;; Maintainer: emacs-devel@gnu.org | 8 | ;; Maintainer: emacs-devel@gnu.org |
| 9 | ;; Created: Jul 2010 | 9 | ;; Created: Jul 2010 |
| 10 | ;; Keywords: languages | 10 | ;; Keywords: languages |
| @@ -31,9 +31,9 @@ | |||
| 31 | ;; found in GNU/Emacs. | 31 | ;; found in GNU/Emacs. |
| 32 | 32 | ||
| 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, Shell |
| 35 | ;; tracking, Symbol completion, Skeletons, FFAP, Code Check, Eldoc, | 35 | ;; package support, Shell syntax highlighting, Pdb tracking, Symbol |
| 36 | ;; Imenu. | 36 | ;; completion, Skeletons, FFAP, Code Check, Eldoc, 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. |
| @@ -62,57 +62,80 @@ | |||
| 62 | ;; (add-hook 'python-mode-hook | 62 | ;; (add-hook 'python-mode-hook |
| 63 | ;; (lambda () (setq forward-sexp-function nil))) | 63 | ;; (lambda () (setq forward-sexp-function nil))) |
| 64 | 64 | ||
| 65 | ;; Shell interaction: is provided and allows you to execute easily any | 65 | ;; Shell interaction: is provided and allows opening Python shells |
| 66 | ;; block of code of your current buffer in an inferior Python process. | 66 | ;; inside Emacs and executing any block of code of your current buffer |
| 67 | ;; in that inferior Python process. | ||
| 68 | |||
| 69 | ;; Besides that only the standard CPython (2.x and 3.x) shell and | ||
| 70 | ;; IPython are officially supported out of the box, the interaction | ||
| 71 | ;; should support any other readline based Python shells as well | ||
| 72 | ;; (e.g. Jython and Pypy have been reported to work). You can change | ||
| 73 | ;; your default interpreter and commandline arguments by setting the | ||
| 74 | ;; `python-shell-interpreter' and `python-shell-interpreter-args' | ||
| 75 | ;; variables. This example enables IPython globally: | ||
| 76 | |||
| 77 | ;; (setq python-shell-interpreter "ipython" | ||
| 78 | ;; python-shell-interpreter-args "-i") | ||
| 79 | |||
| 80 | ;; Using the "console" subcommand to start IPython in server-client | ||
| 81 | ;; mode is known to fail intermittently due a bug on IPython itself | ||
| 82 | ;; (see URL `http://debbugs.gnu.org/cgi/bugreport.cgi?bug=18052#27'). | ||
| 83 | ;; There seems to be a race condition in the IPython server (A.K.A | ||
| 84 | ;; kernel) when code is sent while it is still initializing, sometimes | ||
| 85 | ;; causing the shell to get stalled. With that said, if an IPython | ||
| 86 | ;; kernel is already running, "console --existing" seems to work fine. | ||
| 87 | |||
| 88 | ;; Running IPython on Windows needs more tweaking. The way you should | ||
| 89 | ;; set `python-shell-interpreter' and `python-shell-interpreter-args' | ||
| 90 | ;; is as follows (of course you need to modify the paths according to | ||
| 91 | ;; your system): | ||
| 92 | |||
| 93 | ;; (setq python-shell-interpreter "C:\\Python27\\python.exe" | ||
| 94 | ;; python-shell-interpreter-args | ||
| 95 | ;; "-i C:\\Python27\\Scripts\\ipython-script.py") | ||
| 96 | |||
| 97 | ;; If you are experiencing missing or delayed output in your shells, | ||
| 98 | ;; that's likely caused by your Operating System's pipe buffering | ||
| 99 | ;; (e.g. this is known to happen running CPython 3.3.4 in Windows 7. | ||
| 100 | ;; See URL `http://debbugs.gnu.org/cgi/bugreport.cgi?bug=17304'). To | ||
| 101 | ;; fix this, using CPython's "-u" commandline argument or setting the | ||
| 102 | ;; "PYTHONUNBUFFERED" environment variable should help: See URL | ||
| 103 | ;; `https://docs.python.org/3/using/cmdline.html#cmdoption-u'. | ||
| 104 | |||
| 105 | ;; The interaction relies upon having prompts for input (e.g. ">>> " | ||
| 106 | ;; and "... " in standard Python shell) and output (e.g. "Out[1]: " in | ||
| 107 | ;; IPython) detected properly. Failing that Emacs may hang but, in | ||
| 108 | ;; the case that happens, you can recover with \\[keyboard-quit]. To | ||
| 109 | ;; avoid this issue, a two-step prompt autodetection mechanism is | ||
| 110 | ;; provided: the first step is manual and consists of a collection of | ||
| 111 | ;; regular expressions matching common prompts for Python shells | ||
| 112 | ;; stored in `python-shell-prompt-input-regexps' and | ||
| 113 | ;; `python-shell-prompt-output-regexps', and dir-local friendly vars | ||
| 114 | ;; `python-shell-prompt-regexp', `python-shell-prompt-block-regexp', | ||
| 115 | ;; `python-shell-prompt-output-regexp' which are appended to the | ||
| 116 | ;; former automatically when a shell spawns; the second step is | ||
| 117 | ;; automatic and depends on the `python-shell-prompt-detect' helper | ||
| 118 | ;; function. See its docstring for details on global variables that | ||
| 119 | ;; modify its behavior. | ||
| 67 | 120 | ||
| 68 | ;; Shell completion: hitting tab will try to complete the current | 121 | ;; Shell completion: hitting tab will try to complete the current |
| 69 | ;; word. Shell completion is implemented in a manner that if you | 122 | ;; word. Shell completion is implemented in such way that if you |
| 70 | ;; change the `python-shell-interpreter' to any other (for example | 123 | ;; change the `python-shell-interpreter' it should be possible to |
| 71 | ;; IPython) it should be easy to integrate another way to calculate | 124 | ;; integrate custom logic to calculate completions. To achieve this |
| 72 | ;; completions. You just need to specify your custom | 125 | ;; you just need to set `python-shell-completion-setup-code' and |
| 73 | ;; `python-shell-completion-setup-code' and | 126 | ;; `python-shell-completion-string-code'. The default provided code, |
| 74 | ;; `python-shell-completion-string-code'. | 127 | ;; enables autocompletion for both CPython and IPython (and ideally |
| 75 | 128 | ;; any readline based Python shell). This code depends on the | |
| 76 | ;; Here is a complete example of the settings you would use for | ||
| 77 | ;; iPython 0.11: | ||
| 78 | |||
| 79 | ;; (setq | ||
| 80 | ;; python-shell-interpreter "ipython" | ||
| 81 | ;; python-shell-interpreter-args "" | ||
| 82 | ;; python-shell-prompt-regexp "In \\[[0-9]+\\]: " | ||
| 83 | ;; python-shell-prompt-output-regexp "Out\\[[0-9]+\\]: " | ||
| 84 | ;; python-shell-completion-setup-code | ||
| 85 | ;; "from IPython.core.completerlib import module_completion" | ||
| 86 | ;; python-shell-completion-module-string-code | ||
| 87 | ;; "';'.join(module_completion('''%s'''))\n" | ||
| 88 | ;; python-shell-completion-string-code | ||
| 89 | ;; "';'.join(get_ipython().Completer.all_completions('''%s'''))\n") | ||
| 90 | |||
| 91 | ;; For iPython 0.10 everything would be the same except for | ||
| 92 | ;; `python-shell-completion-string-code' and | ||
| 93 | ;; `python-shell-completion-module-string-code': | ||
| 94 | |||
| 95 | ;; (setq python-shell-completion-string-code | ||
| 96 | ;; "';'.join(__IP.complete('''%s'''))\n" | ||
| 97 | ;; python-shell-completion-module-string-code "") | ||
| 98 | |||
| 99 | ;; Unfortunately running iPython on Windows needs some more tweaking. | ||
| 100 | ;; The way you must set `python-shell-interpreter' and | ||
| 101 | ;; `python-shell-interpreter-args' is as follows: | ||
| 102 | |||
| 103 | ;; (setq | ||
| 104 | ;; python-shell-interpreter "C:\\Python27\\python.exe" | ||
| 105 | ;; python-shell-interpreter-args | ||
| 106 | ;; "-i C:\\Python27\\Scripts\\ipython-script.py") | ||
| 107 | |||
| 108 | ;; That will spawn the iPython process correctly (Of course you need | ||
| 109 | ;; to modify the paths according to your system). | ||
| 110 | |||
| 111 | ;; Please note that the default completion system depends on the | ||
| 112 | ;; readline module, so if you are using some Operating System that | 129 | ;; readline module, so if you are using some Operating System that |
| 113 | ;; bundles Python without it (like Windows) just install the | 130 | ;; bundles Python without it (like Windows), installing pyreadline |
| 114 | ;; pyreadline from http://ipython.scipy.org/moin/PyReadline/Intro and | 131 | ;; from URL `http://ipython.scipy.org/moin/PyReadline/Intro' should |
| 115 | ;; you should be good to go. | 132 | ;; suffice. To troubleshoot why you are not getting any completions |
| 133 | ;; you can try the following in your Python shell: | ||
| 134 | |||
| 135 | ;; >>> import readline, rlcompleter | ||
| 136 | |||
| 137 | ;; If you see an error, then you need to either install pyreadline or | ||
| 138 | ;; setup custom code that avoids that dependency. | ||
| 116 | 139 | ||
| 117 | ;; Shell virtualenv support: The shell also contains support for | 140 | ;; Shell virtualenv support: The shell also contains support for |
| 118 | ;; virtualenvs and other special environment modifications thanks to | 141 | ;; virtualenvs and other special environment modifications thanks to |
| @@ -147,6 +170,16 @@ | |||
| 147 | ;; introduced as simple way of adding paths to the PYTHONPATH without | 170 | ;; introduced as simple way of adding paths to the PYTHONPATH without |
| 148 | ;; affecting existing values. | 171 | ;; affecting existing values. |
| 149 | 172 | ||
| 173 | ;; Shell package support: you can enable a package in the current | ||
| 174 | ;; shell so that relative imports work properly using the | ||
| 175 | ;; `python-shell-package-enable' command. | ||
| 176 | |||
| 177 | ;; Shell syntax highlighting: when enabled current input in shell is | ||
| 178 | ;; highlighted. The variable `python-shell-font-lock-enable' controls | ||
| 179 | ;; activation of this feature globally when shells are started. | ||
| 180 | ;; Activation/deactivation can be also controlled on the fly via the | ||
| 181 | ;; `python-shell-font-lock-toggle' command. | ||
| 182 | |||
| 150 | ;; Pdb tracking: when you execute a block of code that contains some | 183 | ;; Pdb tracking: when you execute a block of code that contains some |
| 151 | ;; call to pdb (or ipdb) it will prompt the block of code and will | 184 | ;; call to pdb (or ipdb) it will prompt the block of code and will |
| 152 | ;; follow the execution of pdb marking the current line with an arrow. | 185 | ;; follow the execution of pdb marking the current line with an arrow. |
| @@ -211,7 +244,9 @@ | |||
| 211 | ;;; Code: | 244 | ;;; Code: |
| 212 | 245 | ||
| 213 | (require 'ansi-color) | 246 | (require 'ansi-color) |
| 247 | (require 'cl-lib) | ||
| 214 | (require 'comint) | 248 | (require 'comint) |
| 249 | (require 'json) | ||
| 215 | 250 | ||
| 216 | ;; Avoid compiler warnings | 251 | ;; Avoid compiler warnings |
| 217 | (defvar view-return-to-alist) | 252 | (defvar view-return-to-alist) |
| @@ -321,6 +356,13 @@ | |||
| 321 | (or "def" "class" "if" "elif" "else" "try" | 356 | (or "def" "class" "if" "elif" "else" "try" |
| 322 | "except" "finally" "for" "while" "with") | 357 | "except" "finally" "for" "while" "with") |
| 323 | symbol-end)) | 358 | symbol-end)) |
| 359 | (dedenter . ,(rx symbol-start | ||
| 360 | (or "elif" "else" "except" "finally") | ||
| 361 | symbol-end)) | ||
| 362 | (block-ender . ,(rx symbol-start | ||
| 363 | (or | ||
| 364 | "break" "continue" "pass" "raise" "return") | ||
| 365 | symbol-end)) | ||
| 324 | (decorator . ,(rx line-start (* space) ?@ (any letter ?_) | 366 | (decorator . ,(rx line-start (* space) ?@ (any letter ?_) |
| 325 | (* (any word ?_)))) | 367 | (* (any word ?_)))) |
| 326 | (defun . ,(rx symbol-start (or "def" "class") symbol-end)) | 368 | (defun . ,(rx symbol-start (or "def" "class") symbol-end)) |
| @@ -630,18 +672,6 @@ It makes underscores and dots word constituent chars.") | |||
| 630 | (defvar python-indent-levels '(0) | 672 | (defvar python-indent-levels '(0) |
| 631 | "Levels of indentation available for `python-indent-line-function'.") | 673 | "Levels of indentation available for `python-indent-line-function'.") |
| 632 | 674 | ||
| 633 | (defvar python-indent-dedenters '("else" "elif" "except" "finally") | ||
| 634 | "List of words that should be dedented. | ||
| 635 | These make `python-indent-calculate-indentation' subtract the value of | ||
| 636 | `python-indent-offset'.") | ||
| 637 | |||
| 638 | (defvar python-indent-block-enders | ||
| 639 | '("break" "continue" "pass" "raise" "return") | ||
| 640 | "List of words that mark the end of a block. | ||
| 641 | These make `python-indent-calculate-indentation' subtract the | ||
| 642 | value of `python-indent-offset' when `python-indent-context' is | ||
| 643 | AFTER-LINE.") | ||
| 644 | |||
| 645 | (defun python-indent-guess-indent-offset () | 675 | (defun python-indent-guess-indent-offset () |
| 646 | "Guess and set `python-indent-offset' for the current buffer." | 676 | "Guess and set `python-indent-offset' for the current buffer." |
| 647 | (interactive) | 677 | (interactive) |
| @@ -692,6 +722,7 @@ Where status can be any of the following symbols: | |||
| 692 | * after-backslash: Previous line ends in a backslash | 722 | * after-backslash: Previous line ends in a backslash |
| 693 | * after-beginning-of-block: Point is after beginning of block | 723 | * after-beginning-of-block: Point is after beginning of block |
| 694 | * after-line: Point is after normal line | 724 | * after-line: Point is after normal line |
| 725 | * dedenter-statement: Point is on a dedenter statement. | ||
| 695 | * no-indent: Point is at beginning of buffer or other special case | 726 | * no-indent: Point is at beginning of buffer or other special case |
| 696 | START is the buffer position where the sexp starts." | 727 | START is the buffer position where the sexp starts." |
| 697 | (save-restriction | 728 | (save-restriction |
| @@ -746,6 +777,8 @@ START is the buffer position where the sexp starts." | |||
| 746 | (when (looking-at (python-rx block-start)) | 777 | (when (looking-at (python-rx block-start)) |
| 747 | (point-marker))))) | 778 | (point-marker))))) |
| 748 | 'after-beginning-of-block) | 779 | 'after-beginning-of-block) |
| 780 | ((when (setq start (python-info-dedenter-statement-p)) | ||
| 781 | 'dedenter-statement)) | ||
| 749 | ;; After normal line | 782 | ;; After normal line |
| 750 | ((setq start (save-excursion | 783 | ((setq start (save-excursion |
| 751 | (back-to-indentation) | 784 | (back-to-indentation) |
| @@ -776,8 +809,7 @@ START is the buffer position where the sexp starts." | |||
| 776 | (goto-char context-start) | 809 | (goto-char context-start) |
| 777 | (+ (current-indentation) python-indent-offset)) | 810 | (+ (current-indentation) python-indent-offset)) |
| 778 | ;; When after a simple line just use previous line | 811 | ;; When after a simple line just use previous line |
| 779 | ;; indentation, in the case current line starts with a | 812 | ;; indentation. |
| 780 | ;; `python-indent-dedenters' de-indent one level. | ||
| 781 | (`after-line | 813 | (`after-line |
| 782 | (let* ((pair (save-excursion | 814 | (let* ((pair (save-excursion |
| 783 | (goto-char context-start) | 815 | (goto-char context-start) |
| @@ -785,25 +817,27 @@ START is the buffer position where the sexp starts." | |||
| 785 | (current-indentation) | 817 | (current-indentation) |
| 786 | (python-info-beginning-of-block-p)))) | 818 | (python-info-beginning-of-block-p)))) |
| 787 | (context-indentation (car pair)) | 819 | (context-indentation (car pair)) |
| 788 | (after-block-start-p (cdr pair)) | 820 | ;; TODO: Separate block enders into its own case. |
| 789 | (adjustment | 821 | (adjustment |
| 790 | (if (or (save-excursion | 822 | (if (save-excursion |
| 791 | (back-to-indentation) | 823 | (python-util-forward-comment -1) |
| 792 | (and | 824 | (python-nav-beginning-of-statement) |
| 793 | ;; De-indent only when dedenters are not | 825 | (looking-at (python-rx block-ender))) |
| 794 | ;; next to a block start. This allows | ||
| 795 | ;; one-liner constructs such as: | ||
| 796 | ;; if condition: print "yay" | ||
| 797 | ;; else: print "wry" | ||
| 798 | (not after-block-start-p) | ||
| 799 | (looking-at (regexp-opt python-indent-dedenters)))) | ||
| 800 | (save-excursion | ||
| 801 | (python-util-forward-comment -1) | ||
| 802 | (python-nav-beginning-of-statement) | ||
| 803 | (looking-at (regexp-opt python-indent-block-enders)))) | ||
| 804 | python-indent-offset | 826 | python-indent-offset |
| 805 | 0))) | 827 | 0))) |
| 806 | (- context-indentation adjustment))) | 828 | (- context-indentation adjustment))) |
| 829 | ;; When point is on a dedenter statement, search for the | ||
| 830 | ;; opening block that corresponds to it and use its | ||
| 831 | ;; indentation. If no opening block is found just remove | ||
| 832 | ;; indentation as this is an invalid python file. | ||
| 833 | (`dedenter-statement | ||
| 834 | (let ((block-start-point | ||
| 835 | (python-info-dedenter-opening-block-position))) | ||
| 836 | (save-excursion | ||
| 837 | (if (not block-start-point) | ||
| 838 | 0 | ||
| 839 | (goto-char block-start-point) | ||
| 840 | (current-indentation))))) | ||
| 807 | ;; When inside of a string, do nothing. just use the current | 841 | ;; When inside of a string, do nothing. just use the current |
| 808 | ;; indentation. XXX: perhaps it would be a good idea to | 842 | ;; indentation. XXX: perhaps it would be a good idea to |
| 809 | ;; invoke standard text indentation here | 843 | ;; invoke standard text indentation here |
| @@ -930,16 +964,25 @@ START is the buffer position where the sexp starts." | |||
| 930 | 964 | ||
| 931 | (defun python-indent-calculate-levels () | 965 | (defun python-indent-calculate-levels () |
| 932 | "Calculate `python-indent-levels' and reset `python-indent-current-level'." | 966 | "Calculate `python-indent-levels' and reset `python-indent-current-level'." |
| 933 | (let* ((indentation (python-indent-calculate-indentation)) | 967 | (if (not (python-info-dedenter-statement-p)) |
| 934 | (remainder (% indentation python-indent-offset)) | 968 | (let* ((indentation (python-indent-calculate-indentation)) |
| 935 | (steps (/ (- indentation remainder) python-indent-offset))) | 969 | (remainder (% indentation python-indent-offset)) |
| 936 | (setq python-indent-levels (list 0)) | 970 | (steps (/ (- indentation remainder) python-indent-offset))) |
| 937 | (dotimes (step steps) | 971 | (setq python-indent-levels (list 0)) |
| 938 | (push (* python-indent-offset (1+ step)) python-indent-levels)) | 972 | (dotimes (step steps) |
| 939 | (when (not (eq 0 remainder)) | 973 | (push (* python-indent-offset (1+ step)) python-indent-levels)) |
| 940 | (push (+ (* python-indent-offset steps) remainder) python-indent-levels)) | 974 | (when (not (eq 0 remainder)) |
| 941 | (setq python-indent-levels (nreverse python-indent-levels)) | 975 | (push (+ (* python-indent-offset steps) remainder) python-indent-levels))) |
| 942 | (setq python-indent-current-level (1- (length python-indent-levels))))) | 976 | (setq python-indent-levels |
| 977 | (or | ||
| 978 | (mapcar (lambda (pos) | ||
| 979 | (save-excursion | ||
| 980 | (goto-char pos) | ||
| 981 | (current-indentation))) | ||
| 982 | (python-info-dedenter-opening-block-positions)) | ||
| 983 | (list 0)))) | ||
| 984 | (setq python-indent-current-level (1- (length python-indent-levels)) | ||
| 985 | python-indent-levels (nreverse python-indent-levels))) | ||
| 943 | 986 | ||
| 944 | (defun python-indent-toggle-levels () | 987 | (defun python-indent-toggle-levels () |
| 945 | "Toggle `python-indent-current-level' over `python-indent-levels'." | 988 | "Toggle `python-indent-current-level' over `python-indent-levels'." |
| @@ -988,7 +1031,7 @@ equal to | |||
| 988 | (indent-to next-indent) | 1031 | (indent-to next-indent) |
| 989 | (goto-char starting-pos)) | 1032 | (goto-char starting-pos)) |
| 990 | (and follow-indentation-p (back-to-indentation))) | 1033 | (and follow-indentation-p (back-to-indentation))) |
| 991 | (python-info-closing-block-message)) | 1034 | (python-info-dedenter-opening-block-message)) |
| 992 | 1035 | ||
| 993 | (defun python-indent-line-function () | 1036 | (defun python-indent-line-function () |
| 994 | "`indent-line-function' for Python mode. | 1037 | "`indent-line-function' for Python mode. |
| @@ -1068,12 +1111,10 @@ any lines in the region are indented less than COUNT columns." | |||
| 1068 | (while (< (point) end) | 1111 | (while (< (point) end) |
| 1069 | (if (and (< (current-indentation) count) | 1112 | (if (and (< (current-indentation) count) |
| 1070 | (not (looking-at "[ \t]*$"))) | 1113 | (not (looking-at "[ \t]*$"))) |
| 1071 | (error "Can't shift all lines enough")) | 1114 | (user-error "Can't shift all lines enough")) |
| 1072 | (forward-line)) | 1115 | (forward-line)) |
| 1073 | (indent-rigidly start end (- count)))))) | 1116 | (indent-rigidly start end (- count)))))) |
| 1074 | 1117 | ||
| 1075 | (add-to-list 'debug-ignored-errors "^Can't shift all lines enough") | ||
| 1076 | |||
| 1077 | (defun python-indent-shift-right (start end &optional count) | 1118 | (defun python-indent-shift-right (start end &optional count) |
| 1078 | "Shift lines contained in region START END by COUNT columns to the right. | 1119 | "Shift lines contained in region START END by COUNT columns to the right. |
| 1079 | COUNT defaults to `python-indent-offset'. If region isn't | 1120 | COUNT defaults to `python-indent-offset'. If region isn't |
| @@ -1096,30 +1137,35 @@ the line will be re-indented automatically if needed." | |||
| 1096 | (when (and electric-indent-mode | 1137 | (when (and electric-indent-mode |
| 1097 | (eq (char-before) last-command-event)) | 1138 | (eq (char-before) last-command-event)) |
| 1098 | (cond | 1139 | (cond |
| 1099 | ((and (not (bolp)) | 1140 | ;; Electric indent inside parens |
| 1100 | (memq (char-after) '(?\) ?\] ?\}))) | 1141 | ((and |
| 1142 | (not (bolp)) | ||
| 1143 | (let ((paren-start (python-syntax-context 'paren))) | ||
| 1144 | ;; Check that point is inside parens. | ||
| 1145 | (when paren-start | ||
| 1146 | (not | ||
| 1147 | ;; Filter the case where input is happening in the same | ||
| 1148 | ;; line where the open paren is. | ||
| 1149 | (= (line-number-at-pos) | ||
| 1150 | (line-number-at-pos paren-start))))) | ||
| 1151 | ;; When content has been added before the closing paren or a | ||
| 1152 | ;; comma has been inserted, it's ok to do the trick. | ||
| 1153 | (or | ||
| 1154 | (memq (char-after) '(?\) ?\] ?\})) | ||
| 1155 | (eq (char-before) ?,))) | ||
| 1101 | (save-excursion | 1156 | (save-excursion |
| 1102 | (goto-char (line-beginning-position)) | 1157 | (goto-char (line-beginning-position)) |
| 1103 | ;; If after going to the beginning of line the point | 1158 | (let ((indentation (python-indent-calculate-indentation))) |
| 1104 | ;; is still inside a paren it's ok to do the trick | 1159 | (when (< (current-indentation) indentation) |
| 1105 | (when (python-syntax-context 'paren) | 1160 | (indent-line-to indentation))))) |
| 1106 | (let ((indentation (python-indent-calculate-indentation))) | 1161 | ;; Electric colon |
| 1107 | (when (< (current-indentation) indentation) | ||
| 1108 | (indent-line-to indentation)))))) | ||
| 1109 | ((and (eq ?: last-command-event) | 1162 | ((and (eq ?: last-command-event) |
| 1110 | (memq ?: electric-indent-chars) | 1163 | (memq ?: electric-indent-chars) |
| 1111 | (not current-prefix-arg) | 1164 | (not current-prefix-arg) |
| 1112 | (eolp) | 1165 | (eolp) |
| 1113 | (not (equal ?: (char-before (1- (point))))) | 1166 | (not (equal ?: (char-before (1- (point))))) |
| 1114 | (not (python-syntax-comment-or-string-p))) | 1167 | (not (python-syntax-comment-or-string-p))) |
| 1115 | (let ((indentation (current-indentation)) | 1168 | (python-indent-line))))) |
| 1116 | (calculated-indentation (python-indent-calculate-indentation))) | ||
| 1117 | (python-info-closing-block-message) | ||
| 1118 | (when (> indentation calculated-indentation) | ||
| 1119 | (save-excursion | ||
| 1120 | (indent-line-to calculated-indentation) | ||
| 1121 | (when (not (python-info-closing-block-message)) | ||
| 1122 | (indent-line-to indentation))))))))) | ||
| 1123 | 1169 | ||
| 1124 | 1170 | ||
| 1125 | ;;; Navigation | 1171 | ;;; Navigation |
| @@ -1692,35 +1738,66 @@ position, else returns nil." | |||
| 1692 | :type 'string | 1738 | :type 'string |
| 1693 | :group 'python) | 1739 | :group 'python) |
| 1694 | 1740 | ||
| 1741 | (defcustom python-shell-interpreter-interactive-arg "-i" | ||
| 1742 | "Interpreter argument to force it to run interactively." | ||
| 1743 | :type 'string | ||
| 1744 | :version "24.4") | ||
| 1745 | |||
| 1746 | (defcustom python-shell-prompt-detect-enabled t | ||
| 1747 | "Non-nil enables autodetection of interpreter prompts." | ||
| 1748 | :type 'boolean | ||
| 1749 | :safe 'booleanp | ||
| 1750 | :version "24.4") | ||
| 1751 | |||
| 1752 | (defcustom python-shell-prompt-detect-failure-warning t | ||
| 1753 | "Non-nil enables warnings when detection of prompts fail." | ||
| 1754 | :type 'boolean | ||
| 1755 | :safe 'booleanp | ||
| 1756 | :version "24.4") | ||
| 1757 | |||
| 1758 | (defcustom python-shell-prompt-input-regexps | ||
| 1759 | '(">>> " "\\.\\.\\. " ; Python | ||
| 1760 | "In \\[[0-9]+\\]: " ; IPython | ||
| 1761 | " \\.\\.\\.: " ; IPython | ||
| 1762 | ;; Using ipdb outside IPython may fail to cleanup and leave static | ||
| 1763 | ;; IPython prompts activated, this adds some safeguard for that. | ||
| 1764 | "In : " "\\.\\.\\.: ") | ||
| 1765 | "List of regular expressions matching input prompts." | ||
| 1766 | :type '(repeat string) | ||
| 1767 | :version "24.4") | ||
| 1768 | |||
| 1769 | (defcustom python-shell-prompt-output-regexps | ||
| 1770 | '("" ; Python | ||
| 1771 | "Out\\[[0-9]+\\]: " ; IPython | ||
| 1772 | "Out :") ; ipdb safeguard | ||
| 1773 | "List of regular expressions matching output prompts." | ||
| 1774 | :type '(repeat string) | ||
| 1775 | :version "24.4") | ||
| 1776 | |||
| 1695 | (defcustom python-shell-prompt-regexp ">>> " | 1777 | (defcustom python-shell-prompt-regexp ">>> " |
| 1696 | "Regular expression matching top-level input prompt of Python shell. | 1778 | "Regular expression matching top level input prompt of Python shell. |
| 1697 | It should not contain a caret (^) at the beginning." | 1779 | It should not contain a caret (^) at the beginning." |
| 1698 | :type 'string | 1780 | :type 'string) |
| 1699 | :group 'python | ||
| 1700 | :safe 'stringp) | ||
| 1701 | 1781 | ||
| 1702 | (defcustom python-shell-prompt-block-regexp "[.][.][.] " | 1782 | (defcustom python-shell-prompt-block-regexp "\\.\\.\\. " |
| 1703 | "Regular expression matching block input prompt of Python shell. | 1783 | "Regular expression matching block input prompt of Python shell. |
| 1704 | It should not contain a caret (^) at the beginning." | 1784 | It should not contain a caret (^) at the beginning." |
| 1705 | :type 'string | 1785 | :type 'string) |
| 1706 | :group 'python | ||
| 1707 | :safe 'stringp) | ||
| 1708 | 1786 | ||
| 1709 | (defcustom python-shell-prompt-output-regexp "" | 1787 | (defcustom python-shell-prompt-output-regexp "" |
| 1710 | "Regular expression matching output prompt of Python shell. | 1788 | "Regular expression matching output prompt of Python shell. |
| 1711 | It should not contain a caret (^) at the beginning." | 1789 | It should not contain a caret (^) at the beginning." |
| 1712 | :type 'string | 1790 | :type 'string) |
| 1713 | :group 'python | ||
| 1714 | :safe 'stringp) | ||
| 1715 | 1791 | ||
| 1716 | (defcustom python-shell-prompt-pdb-regexp "[(<]*[Ii]?[Pp]db[>)]+ " | 1792 | (defcustom python-shell-prompt-pdb-regexp "[(<]*[Ii]?[Pp]db[>)]+ " |
| 1717 | "Regular expression matching pdb input prompt of Python shell. | 1793 | "Regular expression matching pdb input prompt of Python shell. |
| 1718 | It should not contain a caret (^) at the beginning." | 1794 | It should not contain a caret (^) at the beginning." |
| 1719 | :type 'string | 1795 | :type 'string) |
| 1720 | :group 'python | 1796 | |
| 1721 | :safe 'stringp) | 1797 | (define-obsolete-variable-alias |
| 1798 | 'python-shell-enable-font-lock 'python-shell-font-lock-enable "24.5") | ||
| 1722 | 1799 | ||
| 1723 | (defcustom python-shell-enable-font-lock t | 1800 | (defcustom python-shell-font-lock-enable t |
| 1724 | "Should syntax highlighting be enabled in the Python shell buffer? | 1801 | "Should syntax highlighting be enabled in the Python shell buffer? |
| 1725 | Restart the Python shell after changing this variable for it to take effect." | 1802 | Restart the Python shell after changing this variable for it to take effect." |
| 1726 | :type 'boolean | 1803 | :type 'boolean |
| @@ -1788,6 +1865,169 @@ virtualenv." | |||
| 1788 | :type '(alist string) | 1865 | :type '(alist string) |
| 1789 | :group 'python) | 1866 | :group 'python) |
| 1790 | 1867 | ||
| 1868 | (defvar python-shell--prompt-calculated-input-regexp nil | ||
| 1869 | "Calculated input prompt regexp for inferior python shell. | ||
| 1870 | Do not set this variable directly, instead use | ||
| 1871 | `python-shell-prompt-set-calculated-regexps'.") | ||
| 1872 | |||
| 1873 | (defvar python-shell--prompt-calculated-output-regexp nil | ||
| 1874 | "Calculated output prompt regexp for inferior python shell. | ||
| 1875 | Do not set this variable directly, instead use | ||
| 1876 | `python-shell-set-prompt-regexp'.") | ||
| 1877 | |||
| 1878 | (defun python-shell-prompt-detect () | ||
| 1879 | "Detect prompts for the current `python-shell-interpreter'. | ||
| 1880 | When prompts can be retrieved successfully from the | ||
| 1881 | `python-shell-interpreter' run with | ||
| 1882 | `python-shell-interpreter-interactive-arg', returns a list of | ||
| 1883 | three elements, where the first two are input prompts and the | ||
| 1884 | last one is an output prompt. When no prompts can be detected | ||
| 1885 | and `python-shell-prompt-detect-failure-warning' is non-nil, | ||
| 1886 | shows a warning with instructions to avoid hangs and returns nil. | ||
| 1887 | When `python-shell-prompt-detect-enabled' is nil avoids any | ||
| 1888 | detection and just returns nil." | ||
| 1889 | (when python-shell-prompt-detect-enabled | ||
| 1890 | (let* ((process-environment (python-shell-calculate-process-environment)) | ||
| 1891 | (exec-path (python-shell-calculate-exec-path)) | ||
| 1892 | (code (concat | ||
| 1893 | "import sys\n" | ||
| 1894 | "ps = [getattr(sys, 'ps%s' % i, '') for i in range(1,4)]\n" | ||
| 1895 | ;; JSON is built manually for compatibility | ||
| 1896 | "ps_json = '\\n[\"%s\", \"%s\", \"%s\"]\\n' % tuple(ps)\n" | ||
| 1897 | "print (ps_json)\n" | ||
| 1898 | "sys.exit(0)\n")) | ||
| 1899 | (output | ||
| 1900 | (with-temp-buffer | ||
| 1901 | ;; TODO: improve error handling by using | ||
| 1902 | ;; `condition-case' and displaying the error message to | ||
| 1903 | ;; the user in the no-prompts warning. | ||
| 1904 | (ignore-errors | ||
| 1905 | (let ((code-file (python-shell--save-temp-file code))) | ||
| 1906 | ;; Use `process-file' as it is remote-host friendly. | ||
| 1907 | (process-file | ||
| 1908 | (executable-find python-shell-interpreter) | ||
| 1909 | code-file | ||
| 1910 | '(t nil) | ||
| 1911 | nil | ||
| 1912 | python-shell-interpreter-interactive-arg) | ||
| 1913 | ;; Try to cleanup | ||
| 1914 | (delete-file code-file))) | ||
| 1915 | (buffer-string))) | ||
| 1916 | (prompts | ||
| 1917 | (catch 'prompts | ||
| 1918 | (dolist (line (split-string output "\n" t)) | ||
| 1919 | (let ((res | ||
| 1920 | ;; Check if current line is a valid JSON array | ||
| 1921 | (and (string= (substring line 0 2) "[\"") | ||
| 1922 | (ignore-errors | ||
| 1923 | ;; Return prompts as a list, not vector | ||
| 1924 | (append (json-read-from-string line) nil))))) | ||
| 1925 | ;; The list must contain 3 strings, where the first | ||
| 1926 | ;; is the input prompt, the second is the block | ||
| 1927 | ;; prompt and the last one is the output prompt. The | ||
| 1928 | ;; input prompt is the only one that can't be empty. | ||
| 1929 | (when (and (= (length res) 3) | ||
| 1930 | (cl-every #'stringp res) | ||
| 1931 | (not (string= (car res) ""))) | ||
| 1932 | (throw 'prompts res)))) | ||
| 1933 | nil))) | ||
| 1934 | (when (and (not prompts) | ||
| 1935 | python-shell-prompt-detect-failure-warning) | ||
| 1936 | (lwarn | ||
| 1937 | '(python python-shell-prompt-regexp) | ||
| 1938 | :warning | ||
| 1939 | (concat | ||
| 1940 | "Python shell prompts cannot be detected.\n" | ||
| 1941 | "If your emacs session hangs when starting python shells\n" | ||
| 1942 | "recover with `keyboard-quit' and then try fixing the\n" | ||
| 1943 | "interactive flag for your interpreter by adjusting the\n" | ||
| 1944 | "`python-shell-interpreter-interactive-arg' or add regexps\n" | ||
| 1945 | "matching shell prompts in the directory-local friendly vars:\n" | ||
| 1946 | " + `python-shell-prompt-regexp'\n" | ||
| 1947 | " + `python-shell-prompt-block-regexp'\n" | ||
| 1948 | " + `python-shell-prompt-output-regexp'\n" | ||
| 1949 | "Or alternatively in:\n" | ||
| 1950 | " + `python-shell-prompt-input-regexps'\n" | ||
| 1951 | " + `python-shell-prompt-output-regexps'"))) | ||
| 1952 | prompts))) | ||
| 1953 | |||
| 1954 | (defun python-shell-prompt-validate-regexps () | ||
| 1955 | "Validate all user provided regexps for prompts. | ||
| 1956 | Signals `user-error' if any of these vars contain invalid | ||
| 1957 | regexps: `python-shell-prompt-regexp', | ||
| 1958 | `python-shell-prompt-block-regexp', | ||
| 1959 | `python-shell-prompt-pdb-regexp', | ||
| 1960 | `python-shell-prompt-output-regexp', | ||
| 1961 | `python-shell-prompt-input-regexps', | ||
| 1962 | `python-shell-prompt-output-regexps'." | ||
| 1963 | (dolist (symbol (list 'python-shell-prompt-input-regexps | ||
| 1964 | 'python-shell-prompt-output-regexps | ||
| 1965 | 'python-shell-prompt-regexp | ||
| 1966 | 'python-shell-prompt-block-regexp | ||
| 1967 | 'python-shell-prompt-pdb-regexp | ||
| 1968 | 'python-shell-prompt-output-regexp)) | ||
| 1969 | (dolist (regexp (let ((regexps (symbol-value symbol))) | ||
| 1970 | (if (listp regexps) | ||
| 1971 | regexps | ||
| 1972 | (list regexps)))) | ||
| 1973 | (when (not (python-util-valid-regexp-p regexp)) | ||
| 1974 | (user-error "Invalid regexp %s in `%s'" | ||
| 1975 | regexp symbol))))) | ||
| 1976 | |||
| 1977 | (defun python-shell-prompt-set-calculated-regexps () | ||
| 1978 | "Detect and set input and output prompt regexps. | ||
| 1979 | Build and set the values for `python-shell-input-prompt-regexp' | ||
| 1980 | and `python-shell-output-prompt-regexp' using the values from | ||
| 1981 | `python-shell-prompt-regexp', `python-shell-prompt-block-regexp', | ||
| 1982 | `python-shell-prompt-pdb-regexp', | ||
| 1983 | `python-shell-prompt-output-regexp', | ||
| 1984 | `python-shell-prompt-input-regexps', | ||
| 1985 | `python-shell-prompt-output-regexps' and detected prompts from | ||
| 1986 | `python-shell-prompt-detect'." | ||
| 1987 | (when (not (and python-shell--prompt-calculated-input-regexp | ||
| 1988 | python-shell--prompt-calculated-output-regexp)) | ||
| 1989 | (let* ((detected-prompts (python-shell-prompt-detect)) | ||
| 1990 | (input-prompts nil) | ||
| 1991 | (output-prompts nil) | ||
| 1992 | (build-regexp | ||
| 1993 | (lambda (prompts) | ||
| 1994 | (concat "^\\(" | ||
| 1995 | (mapconcat #'identity | ||
| 1996 | (sort prompts | ||
| 1997 | (lambda (a b) | ||
| 1998 | (let ((length-a (length a)) | ||
| 1999 | (length-b (length b))) | ||
| 2000 | (if (= length-a length-b) | ||
| 2001 | (string< a b) | ||
| 2002 | (> (length a) (length b)))))) | ||
| 2003 | "\\|") | ||
| 2004 | "\\)")))) | ||
| 2005 | ;; Validate ALL regexps | ||
| 2006 | (python-shell-prompt-validate-regexps) | ||
| 2007 | ;; Collect all user defined input prompts | ||
| 2008 | (dolist (prompt (append python-shell-prompt-input-regexps | ||
| 2009 | (list python-shell-prompt-regexp | ||
| 2010 | python-shell-prompt-block-regexp | ||
| 2011 | python-shell-prompt-pdb-regexp))) | ||
| 2012 | (cl-pushnew prompt input-prompts :test #'string=)) | ||
| 2013 | ;; Collect all user defined output prompts | ||
| 2014 | (dolist (prompt (cons python-shell-prompt-output-regexp | ||
| 2015 | python-shell-prompt-output-regexps)) | ||
| 2016 | (cl-pushnew prompt output-prompts :test #'string=)) | ||
| 2017 | ;; Collect detected prompts if any | ||
| 2018 | (when detected-prompts | ||
| 2019 | (dolist (prompt (butlast detected-prompts)) | ||
| 2020 | (setq prompt (regexp-quote prompt)) | ||
| 2021 | (cl-pushnew prompt input-prompts :test #'string=)) | ||
| 2022 | (cl-pushnew (regexp-quote | ||
| 2023 | (car (last detected-prompts))) | ||
| 2024 | output-prompts :test #'string=)) | ||
| 2025 | ;; Set input and output prompt regexps from collected prompts | ||
| 2026 | (setq python-shell--prompt-calculated-input-regexp | ||
| 2027 | (funcall build-regexp input-prompts) | ||
| 2028 | python-shell--prompt-calculated-output-regexp | ||
| 2029 | (funcall build-regexp output-prompts))))) | ||
| 2030 | |||
| 1791 | (defun python-shell-get-process-name (dedicated) | 2031 | (defun python-shell-get-process-name (dedicated) |
| 1792 | "Calculate the appropriate process name for inferior Python process. | 2032 | "Calculate the appropriate process name for inferior Python process. |
| 1793 | If DEDICATED is t and the variable `buffer-file-name' is non-nil | 2033 | If DEDICATED is t and the variable `buffer-file-name' is non-nil |
| @@ -1810,10 +2050,10 @@ uniqueness for different types of configurations." | |||
| 1810 | python-shell-internal-buffer-name | 2050 | python-shell-internal-buffer-name |
| 1811 | (md5 | 2051 | (md5 |
| 1812 | (concat | 2052 | (concat |
| 1813 | (python-shell-parse-command) | 2053 | python-shell-interpreter |
| 1814 | python-shell-prompt-regexp | 2054 | python-shell-interpreter-args |
| 1815 | python-shell-prompt-block-regexp | 2055 | python-shell--prompt-calculated-input-regexp |
| 1816 | python-shell-prompt-output-regexp | 2056 | python-shell--prompt-calculated-output-regexp |
| 1817 | (mapconcat #'symbol-value python-shell-setup-codes "") | 2057 | (mapconcat #'symbol-value python-shell-setup-codes "") |
| 1818 | (mapconcat #'identity python-shell-process-environment "") | 2058 | (mapconcat #'identity python-shell-process-environment "") |
| 1819 | (mapconcat #'identity python-shell-extra-pythonpaths "") | 2059 | (mapconcat #'identity python-shell-extra-pythonpaths "") |
| @@ -1864,26 +2104,221 @@ uniqueness for different types of configurations." | |||
| 1864 | (directory-file-name python-shell-virtualenv-path)) | 2104 | (directory-file-name python-shell-virtualenv-path)) |
| 1865 | path)))) | 2105 | path)))) |
| 1866 | 2106 | ||
| 1867 | (defun python-comint-output-filter-function (output) | 2107 | (defvar python-shell--package-depth 10) |
| 1868 | "Hook run after content is put into comint buffer. | 2108 | |
| 1869 | OUTPUT is a string with the contents of the buffer." | 2109 | (defun python-shell-package-enable (directory package) |
| 1870 | (ansi-color-filter-apply output)) | 2110 | "Add DIRECTORY parent to $PYTHONPATH and enable PACKAGE." |
| 2111 | (interactive | ||
| 2112 | (let* ((dir (expand-file-name | ||
| 2113 | (read-directory-name | ||
| 2114 | "Package root: " | ||
| 2115 | (file-name-directory | ||
| 2116 | (or (buffer-file-name) default-directory))))) | ||
| 2117 | (name (completing-read | ||
| 2118 | "Package: " | ||
| 2119 | (python-util-list-packages | ||
| 2120 | dir python-shell--package-depth)))) | ||
| 2121 | (list dir name))) | ||
| 2122 | (python-shell-send-string | ||
| 2123 | (format | ||
| 2124 | (concat | ||
| 2125 | "import os.path;import sys;" | ||
| 2126 | "sys.path.append(os.path.dirname(os.path.dirname('''%s''')));" | ||
| 2127 | "__package__ = '''%s''';" | ||
| 2128 | "import %s") | ||
| 2129 | directory package package) | ||
| 2130 | (python-shell-get-process))) | ||
| 2131 | |||
| 2132 | (defun python-shell-comint-end-of-output-p (output) | ||
| 2133 | "Return non-nil if OUTPUT is ends with input prompt." | ||
| 2134 | (string-match | ||
| 2135 | ;; XXX: It seems on OSX an extra carriage return is attached | ||
| 2136 | ;; at the end of output, this handles that too. | ||
| 2137 | (concat | ||
| 2138 | "\r?\n?" | ||
| 2139 | ;; Remove initial caret from calculated regexp | ||
| 2140 | (replace-regexp-in-string | ||
| 2141 | (rx string-start ?^) "" | ||
| 2142 | python-shell--prompt-calculated-input-regexp) | ||
| 2143 | (rx eos)) | ||
| 2144 | output)) | ||
| 2145 | |||
| 2146 | (define-obsolete-function-alias | ||
| 2147 | 'python-comint-output-filter-function | ||
| 2148 | 'ansi-color-filter-apply | ||
| 2149 | "24.5") | ||
| 2150 | |||
| 2151 | (defun python-comint-postoutput-scroll-to-bottom (output) | ||
| 2152 | "Faster version of `comint-postoutput-scroll-to-bottom'. | ||
| 2153 | Avoids `recenter' calls until OUTPUT is completely sent." | ||
| 2154 | (when (and (not (string= "" output)) | ||
| 2155 | (python-shell-comint-end-of-output-p | ||
| 2156 | (ansi-color-filter-apply output))) | ||
| 2157 | (comint-postoutput-scroll-to-bottom output)) | ||
| 2158 | output) | ||
| 1871 | 2159 | ||
| 1872 | (defvar python-shell--parent-buffer nil) | 2160 | (defvar python-shell--parent-buffer nil) |
| 1873 | 2161 | ||
| 1874 | (defvar python-shell-output-syntax-table | 2162 | (defmacro python-shell-with-shell-buffer (&rest body) |
| 1875 | (let ((table (make-syntax-table python-dotty-syntax-table))) | 2163 | "Execute the forms in BODY with the shell buffer temporarily current. |
| 1876 | (modify-syntax-entry ?\' "." table) | 2164 | Signals an error if no shell buffer is available for current buffer." |
| 1877 | (modify-syntax-entry ?\" "." table) | 2165 | (declare (indent 0) (debug t)) |
| 1878 | (modify-syntax-entry ?\( "." table) | 2166 | (let ((shell-buffer (make-symbol "shell-buffer"))) |
| 1879 | (modify-syntax-entry ?\[ "." table) | 2167 | `(let ((,shell-buffer (python-shell-get-buffer))) |
| 1880 | (modify-syntax-entry ?\{ "." table) | 2168 | (when (not ,shell-buffer) |
| 1881 | (modify-syntax-entry ?\) "." table) | 2169 | (error "No inferior Python buffer available.")) |
| 1882 | (modify-syntax-entry ?\] "." table) | 2170 | (with-current-buffer ,shell-buffer |
| 1883 | (modify-syntax-entry ?\} "." table) | 2171 | ,@body)))) |
| 1884 | table) | 2172 | |
| 1885 | "Syntax table for shell output. | 2173 | (defvar python-shell--font-lock-buffer nil) |
| 1886 | It makes parens and quotes be treated as punctuation chars.") | 2174 | |
| 2175 | (defun python-shell-font-lock-get-or-create-buffer () | ||
| 2176 | "Get or create a font-lock buffer for current inferior process." | ||
| 2177 | (python-shell-with-shell-buffer | ||
| 2178 | (if python-shell--font-lock-buffer | ||
| 2179 | python-shell--font-lock-buffer | ||
| 2180 | (let ((process-name | ||
| 2181 | (process-name (get-buffer-process (current-buffer))))) | ||
| 2182 | (generate-new-buffer | ||
| 2183 | (format "*%s-font-lock*" process-name)))))) | ||
| 2184 | |||
| 2185 | (defun python-shell-font-lock-kill-buffer () | ||
| 2186 | "Kill the font-lock buffer safely." | ||
| 2187 | (python-shell-with-shell-buffer | ||
| 2188 | (when (and python-shell--font-lock-buffer | ||
| 2189 | (buffer-live-p python-shell--font-lock-buffer)) | ||
| 2190 | (kill-buffer python-shell--font-lock-buffer) | ||
| 2191 | (when (eq major-mode 'inferior-python-mode) | ||
| 2192 | (setq python-shell--font-lock-buffer nil))))) | ||
| 2193 | |||
| 2194 | (defmacro python-shell-font-lock-with-font-lock-buffer (&rest body) | ||
| 2195 | "Execute the forms in BODY in the font-lock buffer. | ||
| 2196 | The value returned is the value of the last form in BODY. See | ||
| 2197 | also `with-current-buffer'." | ||
| 2198 | (declare (indent 0) (debug t)) | ||
| 2199 | `(python-shell-with-shell-buffer | ||
| 2200 | (save-current-buffer | ||
| 2201 | (when (not (and python-shell--font-lock-buffer | ||
| 2202 | (get-buffer python-shell--font-lock-buffer))) | ||
| 2203 | (setq python-shell--font-lock-buffer | ||
| 2204 | (python-shell-font-lock-get-or-create-buffer))) | ||
| 2205 | (set-buffer python-shell--font-lock-buffer) | ||
| 2206 | (set (make-local-variable 'delay-mode-hooks) t) | ||
| 2207 | (let ((python-indent-guess-indent-offset nil)) | ||
| 2208 | (when (not (eq major-mode 'python-mode)) | ||
| 2209 | (python-mode)) | ||
| 2210 | ,@body)))) | ||
| 2211 | |||
| 2212 | (defun python-shell-font-lock-cleanup-buffer () | ||
| 2213 | "Cleanup the font-lock buffer. | ||
| 2214 | Provided as a command because this might be handy if something | ||
| 2215 | goes wrong and syntax highlighting in the shell gets messed up." | ||
| 2216 | (interactive) | ||
| 2217 | (python-shell-with-shell-buffer | ||
| 2218 | (python-shell-font-lock-with-font-lock-buffer | ||
| 2219 | (delete-region (point-min) (point-max))))) | ||
| 2220 | |||
| 2221 | (defun python-shell-font-lock-comint-output-filter-function (output) | ||
| 2222 | "Clean up the font-lock buffer after any OUTPUT." | ||
| 2223 | (when (and (not (string= "" output)) | ||
| 2224 | ;; Is end of output and is not just a prompt. | ||
| 2225 | (not (member | ||
| 2226 | (python-shell-comint-end-of-output-p | ||
| 2227 | (ansi-color-filter-apply output)) | ||
| 2228 | '(nil 0)))) | ||
| 2229 | ;; If output is other than an input prompt then "real" output has | ||
| 2230 | ;; been received and the font-lock buffer must be cleaned up. | ||
| 2231 | (python-shell-font-lock-cleanup-buffer)) | ||
| 2232 | output) | ||
| 2233 | |||
| 2234 | (defun python-shell-font-lock-post-command-hook () | ||
| 2235 | "Fontifies current line in shell buffer." | ||
| 2236 | (if (eq this-command 'comint-send-input) | ||
| 2237 | ;; Add a newline when user sends input as this may be a block. | ||
| 2238 | (python-shell-font-lock-with-font-lock-buffer | ||
| 2239 | (goto-char (line-end-position)) | ||
| 2240 | (newline)) | ||
| 2241 | (when (and (python-util-comint-last-prompt) | ||
| 2242 | (> (point) (cdr (python-util-comint-last-prompt)))) | ||
| 2243 | (let ((input (buffer-substring-no-properties | ||
| 2244 | (cdr (python-util-comint-last-prompt)) (point-max))) | ||
| 2245 | (old-input (python-shell-font-lock-with-font-lock-buffer | ||
| 2246 | (buffer-substring-no-properties | ||
| 2247 | (line-beginning-position) (point-max)))) | ||
| 2248 | (current-point (point)) | ||
| 2249 | (buffer-undo-list t)) | ||
| 2250 | ;; When input hasn't changed, do nothing. | ||
| 2251 | (when (not (string= input old-input)) | ||
| 2252 | (delete-region (cdr (python-util-comint-last-prompt)) (point-max)) | ||
| 2253 | (insert | ||
| 2254 | (python-shell-font-lock-with-font-lock-buffer | ||
| 2255 | (delete-region (line-beginning-position) | ||
| 2256 | (line-end-position)) | ||
| 2257 | (insert input) | ||
| 2258 | ;; Ensure buffer is fontified, keeping it | ||
| 2259 | ;; compatible with Emacs < 24.4. | ||
| 2260 | (if (fboundp 'font-lock-ensure) | ||
| 2261 | (funcall 'font-lock-ensure) | ||
| 2262 | (font-lock-default-fontify-buffer)) | ||
| 2263 | ;; Replace FACE text properties with FONT-LOCK-FACE so | ||
| 2264 | ;; they are not overwritten by comint buffer's font lock. | ||
| 2265 | (python-util-text-properties-replace-name | ||
| 2266 | 'face 'font-lock-face) | ||
| 2267 | (buffer-substring (line-beginning-position) | ||
| 2268 | (line-end-position)))) | ||
| 2269 | (goto-char current-point)))))) | ||
| 2270 | |||
| 2271 | (defun python-shell-font-lock-turn-on (&optional msg) | ||
| 2272 | "Turn on shell font-lock. | ||
| 2273 | With argument MSG show activation message." | ||
| 2274 | (interactive "p") | ||
| 2275 | (python-shell-with-shell-buffer | ||
| 2276 | (python-shell-font-lock-kill-buffer) | ||
| 2277 | (set (make-local-variable 'python-shell--font-lock-buffer) nil) | ||
| 2278 | (add-hook 'post-command-hook | ||
| 2279 | #'python-shell-font-lock-post-command-hook nil 'local) | ||
| 2280 | (add-hook 'kill-buffer-hook | ||
| 2281 | #'python-shell-font-lock-kill-buffer nil 'local) | ||
| 2282 | (add-hook 'comint-output-filter-functions | ||
| 2283 | #'python-shell-font-lock-comint-output-filter-function | ||
| 2284 | 'append 'local) | ||
| 2285 | (when msg | ||
| 2286 | (message "Shell font-lock is enabled")))) | ||
| 2287 | |||
| 2288 | (defun python-shell-font-lock-turn-off (&optional msg) | ||
| 2289 | "Turn off shell font-lock. | ||
| 2290 | With argument MSG show deactivation message." | ||
| 2291 | (interactive "p") | ||
| 2292 | (python-shell-with-shell-buffer | ||
| 2293 | (python-shell-font-lock-kill-buffer) | ||
| 2294 | (when (python-util-comint-last-prompt) | ||
| 2295 | ;; Cleanup current fontification | ||
| 2296 | (remove-text-properties | ||
| 2297 | (cdr (python-util-comint-last-prompt)) | ||
| 2298 | (line-end-position) | ||
| 2299 | '(face nil font-lock-face nil))) | ||
| 2300 | (set (make-local-variable 'python-shell--font-lock-buffer) nil) | ||
| 2301 | (remove-hook 'post-command-hook | ||
| 2302 | #'python-shell-font-lock-post-command-hook'local) | ||
| 2303 | (remove-hook 'kill-buffer-hook | ||
| 2304 | #'python-shell-font-lock-kill-buffer 'local) | ||
| 2305 | (remove-hook 'comint-output-filter-functions | ||
| 2306 | #'python-shell-font-lock-comint-output-filter-function | ||
| 2307 | 'local) | ||
| 2308 | (when msg | ||
| 2309 | (message "Shell font-lock is disabled")))) | ||
| 2310 | |||
| 2311 | (defun python-shell-font-lock-toggle (&optional msg) | ||
| 2312 | "Toggle font-lock for shell. | ||
| 2313 | With argument MSG show activation/deactivation message." | ||
| 2314 | (interactive "p") | ||
| 2315 | (python-shell-with-shell-buffer | ||
| 2316 | (set (make-local-variable 'python-shell-font-lock-enable) | ||
| 2317 | (not python-shell-font-lock-enable)) | ||
| 2318 | (if python-shell-font-lock-enable | ||
| 2319 | (python-shell-font-lock-turn-on msg) | ||
| 2320 | (python-shell-font-lock-turn-off msg)) | ||
| 2321 | python-shell-font-lock-enable)) | ||
| 1887 | 2322 | ||
| 1888 | (define-derived-mode inferior-python-mode comint-mode "Inferior Python" | 2323 | (define-derived-mode inferior-python-mode comint-mode "Inferior Python" |
| 1889 | "Major mode for Python inferior process. | 2324 | "Major mode for Python inferior process. |
| @@ -1894,68 +2329,64 @@ interpreter is run. Variables | |||
| 1894 | `python-shell-prompt-regexp', | 2329 | `python-shell-prompt-regexp', |
| 1895 | `python-shell-prompt-output-regexp', | 2330 | `python-shell-prompt-output-regexp', |
| 1896 | `python-shell-prompt-block-regexp', | 2331 | `python-shell-prompt-block-regexp', |
| 1897 | `python-shell-enable-font-lock', | 2332 | `python-shell-font-lock-enable', |
| 1898 | `python-shell-completion-setup-code', | 2333 | `python-shell-completion-setup-code', |
| 1899 | `python-shell-completion-string-code', | 2334 | `python-shell-completion-string-code', |
| 1900 | `python-shell-completion-module-string-code', | ||
| 1901 | `python-eldoc-setup-code', `python-eldoc-string-code', | 2335 | `python-eldoc-setup-code', `python-eldoc-string-code', |
| 1902 | `python-ffap-setup-code' and `python-ffap-string-code' can | 2336 | `python-ffap-setup-code' and `python-ffap-string-code' can |
| 1903 | customize this mode for different Python interpreters. | 2337 | customize this mode for different Python interpreters. |
| 1904 | 2338 | ||
| 2339 | This mode resets `comint-output-filter-functions' locally, so you | ||
| 2340 | may want to re-add custom functions to it using the | ||
| 2341 | `inferior-python-mode-hook'. | ||
| 2342 | |||
| 1905 | You can also add additional setup code to be run at | 2343 | You can also add additional setup code to be run at |
| 1906 | initialization of the interpreter via `python-shell-setup-codes' | 2344 | initialization of the interpreter via `python-shell-setup-codes' |
| 1907 | variable. | 2345 | variable. |
| 1908 | 2346 | ||
| 1909 | \(Type \\[describe-mode] in the process buffer for a list of commands.)" | 2347 | \(Type \\[describe-mode] in the process buffer for a list of commands.)" |
| 1910 | (and python-shell--parent-buffer | 2348 | (let ((interpreter python-shell-interpreter) |
| 1911 | (python-util-clone-local-variables python-shell--parent-buffer)) | 2349 | (args python-shell-interpreter-args)) |
| 1912 | (setq comint-prompt-regexp (format "^\\(?:%s\\|%s\\|%s\\)" | 2350 | (when python-shell--parent-buffer |
| 1913 | python-shell-prompt-regexp | 2351 | (python-util-clone-local-variables python-shell--parent-buffer)) |
| 1914 | python-shell-prompt-block-regexp | 2352 | ;; Users can override default values for these vars when calling |
| 1915 | python-shell-prompt-pdb-regexp)) | 2353 | ;; `run-python'. This ensures new values let-bound in |
| 2354 | ;; `python-shell-make-comint' are locally set. | ||
| 2355 | (set (make-local-variable 'python-shell-interpreter) interpreter) | ||
| 2356 | (set (make-local-variable 'python-shell-interpreter-args) args)) | ||
| 2357 | (set (make-local-variable 'python-shell--prompt-calculated-input-regexp) nil) | ||
| 2358 | (set (make-local-variable 'python-shell--prompt-calculated-output-regexp) nil) | ||
| 2359 | (python-shell-prompt-set-calculated-regexps) | ||
| 2360 | (setq comint-prompt-regexp python-shell--prompt-calculated-input-regexp | ||
| 2361 | comint-prompt-read-only t) | ||
| 1916 | (setq mode-line-process '(":%s")) | 2362 | (setq mode-line-process '(":%s")) |
| 1917 | (make-local-variable 'comint-output-filter-functions) | 2363 | (set (make-local-variable 'comint-output-filter-functions) |
| 1918 | (add-hook 'comint-output-filter-functions | 2364 | '(ansi-color-process-output |
| 1919 | 'python-comint-output-filter-function) | 2365 | python-pdbtrack-comint-output-filter-function |
| 1920 | (add-hook 'comint-output-filter-functions | 2366 | python-comint-postoutput-scroll-to-bottom)) |
| 1921 | 'python-pdbtrack-comint-output-filter-function) | ||
| 1922 | (set (make-local-variable 'compilation-error-regexp-alist) | 2367 | (set (make-local-variable 'compilation-error-regexp-alist) |
| 1923 | python-shell-compilation-regexp-alist) | 2368 | python-shell-compilation-regexp-alist) |
| 1924 | (define-key inferior-python-mode-map [remap complete-symbol] | 2369 | (define-key inferior-python-mode-map [remap complete-symbol] |
| 1925 | 'completion-at-point) | 2370 | 'completion-at-point) |
| 1926 | (add-hook 'completion-at-point-functions | 2371 | (add-hook 'completion-at-point-functions |
| 1927 | 'python-shell-completion-complete-at-point nil 'local) | 2372 | 'python-shell-completion-at-point nil 'local) |
| 1928 | (add-to-list (make-local-variable 'comint-dynamic-complete-functions) | 2373 | (add-to-list (make-local-variable 'comint-dynamic-complete-functions) |
| 1929 | 'python-shell-completion-complete-at-point) | 2374 | 'python-shell-completion-at-point) |
| 1930 | (define-key inferior-python-mode-map "\t" | 2375 | (define-key inferior-python-mode-map "\t" |
| 1931 | 'python-shell-completion-complete-or-indent) | 2376 | 'python-shell-completion-complete-or-indent) |
| 1932 | (make-local-variable 'python-pdbtrack-buffers-to-kill) | 2377 | (make-local-variable 'python-pdbtrack-buffers-to-kill) |
| 1933 | (make-local-variable 'python-pdbtrack-tracked-buffer) | 2378 | (make-local-variable 'python-pdbtrack-tracked-buffer) |
| 1934 | (make-local-variable 'python-shell-internal-last-output) | 2379 | (make-local-variable 'python-shell-internal-last-output) |
| 1935 | (when python-shell-enable-font-lock | 2380 | (when python-shell-font-lock-enable |
| 1936 | (set-syntax-table python-mode-syntax-table) | 2381 | (python-shell-font-lock-turn-on)) |
| 1937 | (set (make-local-variable 'font-lock-defaults) | 2382 | (compilation-shell-minor-mode 1) |
| 1938 | '(python-font-lock-keywords nil nil nil nil)) | 2383 | ;; Ensure all the output is accepted before running any hooks. |
| 1939 | (set (make-local-variable 'syntax-propertize-function) | 2384 | (accept-process-output (get-buffer-process (current-buffer))) |
| 1940 | (eval | 2385 | ;; At this point, all process output should have been received, but |
| 1941 | ;; XXX: Unfortunately eval is needed here to make use of the | 2386 | ;; on GNU/Linux, calling `python-shell-internal-send-string' without |
| 1942 | ;; dynamic value of `comint-prompt-regexp'. | 2387 | ;; a running internal shell fails to grab output properly unless |
| 1943 | `(syntax-propertize-rules | 2388 | ;; this `sit-for' is in place. |
| 1944 | (,comint-prompt-regexp | 2389 | (sit-for 0.1 t)) |
| 1945 | (0 (ignore | ||
| 1946 | (put-text-property | ||
| 1947 | comint-last-input-start end 'syntax-table | ||
| 1948 | python-shell-output-syntax-table) | ||
| 1949 | ;; XXX: This might look weird, but it is the easiest | ||
| 1950 | ;; way to ensure font lock gets cleaned up before the | ||
| 1951 | ;; current prompt, which is needed for unclosed | ||
| 1952 | ;; strings to not mess up with current input. | ||
| 1953 | (font-lock-unfontify-region comint-last-input-start end)))) | ||
| 1954 | (,(python-rx string-delimiter) | ||
| 1955 | (0 (ignore | ||
| 1956 | (and (not (eq (get-text-property start 'field) 'output)) | ||
| 1957 | (python-syntax-stringify))))))))) | ||
| 1958 | (compilation-shell-minor-mode 1)) | ||
| 1959 | 2390 | ||
| 1960 | (defun python-shell-make-comint (cmd proc-name &optional pop internal) | 2391 | (defun python-shell-make-comint (cmd proc-name &optional pop internal) |
| 1961 | "Create a Python shell comint buffer. | 2392 | "Create a Python shell comint buffer. |
| @@ -1975,13 +2406,22 @@ killed." | |||
| 1975 | (exec-path (python-shell-calculate-exec-path))) | 2406 | (exec-path (python-shell-calculate-exec-path))) |
| 1976 | (when (not (comint-check-proc proc-buffer-name)) | 2407 | (when (not (comint-check-proc proc-buffer-name)) |
| 1977 | (let* ((cmdlist (split-string-and-unquote cmd)) | 2408 | (let* ((cmdlist (split-string-and-unquote cmd)) |
| 2409 | (interpreter (car cmdlist)) | ||
| 2410 | (args (cdr cmdlist)) | ||
| 1978 | (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name | 2411 | (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name |
| 1979 | (car cmdlist) nil (cdr cmdlist))) | 2412 | interpreter nil args)) |
| 1980 | (python-shell--parent-buffer (current-buffer)) | 2413 | (python-shell--parent-buffer (current-buffer)) |
| 1981 | (process (get-buffer-process buffer))) | 2414 | (process (get-buffer-process buffer)) |
| 2415 | ;; As the user may have overridden default values for | ||
| 2416 | ;; these vars on `run-python', let-binding them allows | ||
| 2417 | ;; to have the new right values in all setup code | ||
| 2418 | ;; that's is done in `inferior-python-mode', which is | ||
| 2419 | ;; important, especially for prompt detection. | ||
| 2420 | (python-shell-interpreter interpreter) | ||
| 2421 | (python-shell-interpreter-args | ||
| 2422 | (mapconcat #'identity args " "))) | ||
| 1982 | (with-current-buffer buffer | 2423 | (with-current-buffer buffer |
| 1983 | (inferior-python-mode)) | 2424 | (inferior-python-mode)) |
| 1984 | (accept-process-output process) | ||
| 1985 | (and pop (pop-to-buffer buffer t)) | 2425 | (and pop (pop-to-buffer buffer t)) |
| 1986 | (and internal (set-process-query-on-exit-flag process nil)))) | 2426 | (and internal (set-process-query-on-exit-flag process nil)))) |
| 1987 | proc-buffer-name))) | 2427 | proc-buffer-name))) |
| @@ -2024,10 +2464,10 @@ difference with global or dedicated shells is that these ones are | |||
| 2024 | attached to a configuration, not a buffer. This means that can | 2464 | attached to a configuration, not a buffer. This means that can |
| 2025 | be used for example to retrieve the sys.path and other stuff, | 2465 | be used for example to retrieve the sys.path and other stuff, |
| 2026 | without messing with user shells. Note that | 2466 | without messing with user shells. Note that |
| 2027 | `python-shell-enable-font-lock' and `inferior-python-mode-hook' | 2467 | `python-shell-font-lock-enable' and `inferior-python-mode-hook' |
| 2028 | are set to nil for these shells, so setup codes are not sent at | 2468 | are set to nil for these shells, so setup codes are not sent at |
| 2029 | startup." | 2469 | startup." |
| 2030 | (let ((python-shell-enable-font-lock nil) | 2470 | (let ((python-shell-font-lock-enable nil) |
| 2031 | (inferior-python-mode-hook nil)) | 2471 | (inferior-python-mode-hook nil)) |
| 2032 | (get-buffer-process | 2472 | (get-buffer-process |
| 2033 | (python-shell-make-comint | 2473 | (python-shell-make-comint |
| @@ -2035,37 +2475,38 @@ startup." | |||
| 2035 | (python-shell-internal-get-process-name) nil t)))) | 2475 | (python-shell-internal-get-process-name) nil t)))) |
| 2036 | 2476 | ||
| 2037 | (defun python-shell-get-buffer () | 2477 | (defun python-shell-get-buffer () |
| 2038 | "Return inferior Python buffer for current buffer." | 2478 | "Return inferior Python buffer for current buffer. |
| 2039 | (let* ((dedicated-proc-name (python-shell-get-process-name t)) | 2479 | If current buffer is in `inferior-python-mode', return it." |
| 2040 | (dedicated-proc-buffer-name (format "*%s*" dedicated-proc-name)) | 2480 | (if (eq major-mode 'inferior-python-mode) |
| 2041 | (global-proc-name (python-shell-get-process-name nil)) | 2481 | (current-buffer) |
| 2042 | (global-proc-buffer-name (format "*%s*" global-proc-name)) | 2482 | (let* ((dedicated-proc-name (python-shell-get-process-name t)) |
| 2043 | (dedicated-running (comint-check-proc dedicated-proc-buffer-name)) | 2483 | (dedicated-proc-buffer-name (format "*%s*" dedicated-proc-name)) |
| 2044 | (global-running (comint-check-proc global-proc-buffer-name))) | 2484 | (global-proc-name (python-shell-get-process-name nil)) |
| 2045 | ;; Always prefer dedicated | 2485 | (global-proc-buffer-name (format "*%s*" global-proc-name)) |
| 2046 | (or (and dedicated-running dedicated-proc-buffer-name) | 2486 | (dedicated-running (comint-check-proc dedicated-proc-buffer-name)) |
| 2047 | (and global-running global-proc-buffer-name)))) | 2487 | (global-running (comint-check-proc global-proc-buffer-name))) |
| 2488 | ;; Always prefer dedicated | ||
| 2489 | (or (and dedicated-running dedicated-proc-buffer-name) | ||
| 2490 | (and global-running global-proc-buffer-name))))) | ||
| 2048 | 2491 | ||
| 2049 | (defun python-shell-get-process () | 2492 | (defun python-shell-get-process () |
| 2050 | "Return inferior Python process for current buffer." | 2493 | "Return inferior Python process for current buffer." |
| 2051 | (get-buffer-process (python-shell-get-buffer))) | 2494 | (get-buffer-process (python-shell-get-buffer))) |
| 2052 | 2495 | ||
| 2053 | (defun python-shell-get-or-create-process () | 2496 | (defun python-shell-get-or-create-process (&optional cmd dedicated show) |
| 2054 | "Get or create an inferior Python process for current buffer and return it." | 2497 | "Get or create an inferior Python process for current buffer and return it. |
| 2055 | (let* ((dedicated-proc-name (python-shell-get-process-name t)) | 2498 | Arguments CMD, DEDICATED and SHOW are those of `run-python' and |
| 2056 | (dedicated-proc-buffer-name (format "*%s*" dedicated-proc-name)) | 2499 | are used to start the shell. If those arguments are not |
| 2057 | (global-proc-name (python-shell-get-process-name nil)) | 2500 | provided, `run-python' is called interactively and the user will |
| 2058 | (global-proc-buffer-name (format "*%s*" global-proc-name)) | 2501 | be asked for their values." |
| 2059 | (dedicated-running (comint-check-proc dedicated-proc-buffer-name)) | 2502 | (let ((shell-process (python-shell-get-process))) |
| 2060 | (global-running (comint-check-proc global-proc-buffer-name))) | 2503 | (when (not shell-process) |
| 2061 | (when (and (not dedicated-running) (not global-running)) | 2504 | (if (not cmd) |
| 2062 | (if (call-interactively 'run-python) | 2505 | ;; XXX: Refactor code such that calling `run-python' |
| 2063 | (setq dedicated-running t) | 2506 | ;; interactively is not needed anymore. |
| 2064 | (setq global-running t))) | 2507 | (call-interactively 'run-python) |
| 2065 | ;; Always prefer dedicated | 2508 | (run-python cmd dedicated show))) |
| 2066 | (get-buffer-process (if dedicated-running | 2509 | (or shell-process (python-shell-get-process)))) |
| 2067 | dedicated-proc-buffer-name | ||
| 2068 | global-proc-buffer-name)))) | ||
| 2069 | 2510 | ||
| 2070 | (defvar python-shell-internal-buffer nil | 2511 | (defvar python-shell-internal-buffer nil |
| 2071 | "Current internal shell buffer for the current buffer. | 2512 | "Current internal shell buffer for the current buffer. |
| @@ -2083,13 +2524,7 @@ there for compatibility with CEDET.") | |||
| 2083 | (proc-buffer-name (format " *%s*" proc-name))) | 2524 | (proc-buffer-name (format " *%s*" proc-name))) |
| 2084 | (when (not (process-live-p proc-name)) | 2525 | (when (not (process-live-p proc-name)) |
| 2085 | (run-python-internal) | 2526 | (run-python-internal) |
| 2086 | (setq python-shell-internal-buffer proc-buffer-name) | 2527 | (setq python-shell-internal-buffer proc-buffer-name)) |
| 2087 | ;; XXX: Why is this `sit-for' needed? | ||
| 2088 | ;; `python-shell-make-comint' calls `accept-process-output' | ||
| 2089 | ;; already but it is not helping to get proper output on | ||
| 2090 | ;; 'gnu/linux when the internal shell process is not running and | ||
| 2091 | ;; a call to `python-shell-internal-send-string' is issued. | ||
| 2092 | (sit-for 0.1 t)) | ||
| 2093 | (get-buffer-process proc-buffer-name))) | 2528 | (get-buffer-process proc-buffer-name))) |
| 2094 | 2529 | ||
| 2095 | (define-obsolete-function-alias | 2530 | (define-obsolete-function-alias |
| @@ -2139,13 +2574,7 @@ detecting a prompt at the end of the buffer." | |||
| 2139 | string (ansi-color-filter-apply string) | 2574 | string (ansi-color-filter-apply string) |
| 2140 | python-shell-output-filter-buffer | 2575 | python-shell-output-filter-buffer |
| 2141 | (concat python-shell-output-filter-buffer string)) | 2576 | (concat python-shell-output-filter-buffer string)) |
| 2142 | (when (string-match | 2577 | (when (python-shell-comint-end-of-output-p |
| 2143 | ;; XXX: It seems on OSX an extra carriage return is attached | ||
| 2144 | ;; at the end of output, this handles that too. | ||
| 2145 | (format "\r?\n\\(?:%s\\|%s\\|%s\\)$" | ||
| 2146 | python-shell-prompt-regexp | ||
| 2147 | python-shell-prompt-block-regexp | ||
| 2148 | python-shell-prompt-pdb-regexp) | ||
| 2149 | python-shell-output-filter-buffer) | 2578 | python-shell-output-filter-buffer) |
| 2150 | ;; Output ends when `python-shell-output-filter-buffer' contains | 2579 | ;; Output ends when `python-shell-output-filter-buffer' contains |
| 2151 | ;; the prompt attached at the end of it. | 2580 | ;; the prompt attached at the end of it. |
| @@ -2153,10 +2582,10 @@ detecting a prompt at the end of the buffer." | |||
| 2153 | python-shell-output-filter-buffer | 2582 | python-shell-output-filter-buffer |
| 2154 | (substring python-shell-output-filter-buffer | 2583 | (substring python-shell-output-filter-buffer |
| 2155 | 0 (match-beginning 0))) | 2584 | 0 (match-beginning 0))) |
| 2156 | (when (and (> (length python-shell-prompt-output-regexp) 0) | 2585 | (when (string-match |
| 2157 | (string-match (concat "^" python-shell-prompt-output-regexp) | 2586 | python-shell--prompt-calculated-output-regexp |
| 2158 | python-shell-output-filter-buffer)) | 2587 | python-shell-output-filter-buffer) |
| 2159 | ;; Some shells, like iPython might append a prompt before the | 2588 | ;; Some shells, like IPython might append a prompt before the |
| 2160 | ;; output, clean that. | 2589 | ;; output, clean that. |
| 2161 | (setq python-shell-output-filter-buffer | 2590 | (setq python-shell-output-filter-buffer |
| 2162 | (substring python-shell-output-filter-buffer (match-end 0))))) | 2591 | (substring python-shell-output-filter-buffer (match-end 0))))) |
| @@ -2345,18 +2774,24 @@ If DELETE is non-nil, delete the file afterwards." | |||
| 2345 | (defun python-shell-switch-to-shell () | 2774 | (defun python-shell-switch-to-shell () |
| 2346 | "Switch to inferior Python process buffer." | 2775 | "Switch to inferior Python process buffer." |
| 2347 | (interactive) | 2776 | (interactive) |
| 2348 | (pop-to-buffer (process-buffer (python-shell-get-or-create-process)) t)) | 2777 | (process-buffer (python-shell-get-or-create-process)) t) |
| 2349 | 2778 | ||
| 2350 | (defun python-shell-send-setup-code () | 2779 | (defun python-shell-send-setup-code () |
| 2351 | "Send all setup code for shell. | 2780 | "Send all setup code for shell. |
| 2352 | This function takes the list of setup code to send from the | 2781 | This function takes the list of setup code to send from the |
| 2353 | `python-shell-setup-codes' list." | 2782 | `python-shell-setup-codes' list." |
| 2354 | (let ((process (get-buffer-process (current-buffer)))) | 2783 | (let ((process (python-shell-get-process)) |
| 2355 | (dolist (code python-shell-setup-codes) | 2784 | (code (concat |
| 2356 | (when code | 2785 | (mapconcat |
| 2357 | (message "Sent %s" code) | 2786 | (lambda (elt) |
| 2358 | (python-shell-send-string | 2787 | (cond ((stringp elt) elt) |
| 2359 | (symbol-value code) process))))) | 2788 | ((symbolp elt) (symbol-value elt)) |
| 2789 | (t ""))) | ||
| 2790 | python-shell-setup-codes | ||
| 2791 | "\n\n") | ||
| 2792 | "\n\nprint ('python.el: sent setup code')"))) | ||
| 2793 | (python-shell-send-string code) | ||
| 2794 | (accept-process-output process))) | ||
| 2360 | 2795 | ||
| 2361 | (add-hook 'inferior-python-mode-hook | 2796 | (add-hook 'inferior-python-mode-hook |
| 2362 | #'python-shell-send-setup-code) | 2797 | #'python-shell-send-setup-code) |
| @@ -2366,23 +2801,35 @@ This function takes the list of setup code to send from the | |||
| 2366 | 2801 | ||
| 2367 | (defcustom python-shell-completion-setup-code | 2802 | (defcustom python-shell-completion-setup-code |
| 2368 | "try: | 2803 | "try: |
| 2369 | import readline | 2804 | import readline, rlcompleter |
| 2370 | except ImportError: | 2805 | except ImportError: |
| 2371 | def __COMPLETER_all_completions(text): [] | 2806 | def __PYTHON_EL_get_completions(text): |
| 2807 | return [] | ||
| 2372 | else: | 2808 | else: |
| 2373 | import rlcompleter | 2809 | def __PYTHON_EL_get_completions(text): |
| 2374 | readline.set_completer(rlcompleter.Completer().complete) | ||
| 2375 | def __COMPLETER_all_completions(text): | ||
| 2376 | import sys | ||
| 2377 | completions = [] | 2810 | completions = [] |
| 2378 | try: | 2811 | try: |
| 2379 | i = 0 | 2812 | splits = text.split() |
| 2380 | while True: | 2813 | is_module = splits and splits[0] in ('from', 'import') |
| 2381 | res = readline.get_completer()(text, i) | 2814 | is_ipython = getattr( |
| 2382 | if not res: break | 2815 | __builtins__, '__IPYTHON__', |
| 2383 | i += 1 | 2816 | getattr(__builtins__, '__IPYTHON__active', False)) |
| 2384 | completions.append(res) | 2817 | if is_module: |
| 2385 | except NameError: | 2818 | from IPython.core.completerlib import module_completion |
| 2819 | completions = module_completion(text.strip()) | ||
| 2820 | elif is_ipython and getattr(__builtins__, '__IP', None): | ||
| 2821 | completions = __IP.complete(text) | ||
| 2822 | elif is_ipython and getattr(__builtins__, 'get_ipython', None): | ||
| 2823 | completions = get_ipython().Completer.all_completions(text) | ||
| 2824 | else: | ||
| 2825 | i = 0 | ||
| 2826 | while True: | ||
| 2827 | res = readline.get_completer()(text, i) | ||
| 2828 | if not res: | ||
| 2829 | break | ||
| 2830 | i += 1 | ||
| 2831 | completions.append(res) | ||
| 2832 | except: | ||
| 2386 | pass | 2833 | pass |
| 2387 | return completions" | 2834 | return completions" |
| 2388 | "Code used to setup completion in inferior Python processes." | 2835 | "Code used to setup completion in inferior Python processes." |
| @@ -2390,24 +2837,18 @@ else: | |||
| 2390 | :group 'python) | 2837 | :group 'python) |
| 2391 | 2838 | ||
| 2392 | (defcustom python-shell-completion-string-code | 2839 | (defcustom python-shell-completion-string-code |
| 2393 | "';'.join(__COMPLETER_all_completions('''%s'''))\n" | 2840 | "';'.join(__PYTHON_EL_get_completions('''%s'''))\n" |
| 2394 | "Python code used to get a string of completions separated by semicolons." | 2841 | "Python code used to get a string of completions separated by semicolons. |
| 2842 | The string passed to the function is the current python name or | ||
| 2843 | the full statement in the case of imports." | ||
| 2395 | :type 'string | 2844 | :type 'string |
| 2396 | :group 'python) | 2845 | :group 'python) |
| 2397 | 2846 | ||
| 2398 | (defcustom python-shell-completion-module-string-code "" | 2847 | (define-obsolete-variable-alias |
| 2399 | "Python code used to get completions separated by semicolons for imports. | 2848 | 'python-shell-completion-module-string-code |
| 2400 | 2849 | 'python-shell-completion-string-code | |
| 2401 | For IPython v0.11, add the following line to | 2850 | "24.4" |
| 2402 | `python-shell-completion-setup-code': | 2851 | "Completion string code must also autocomplete modules.") |
| 2403 | |||
| 2404 | from IPython.core.completerlib import module_completion | ||
| 2405 | |||
| 2406 | and use the following as the value of this variable: | ||
| 2407 | |||
| 2408 | ';'.join(module_completion('''%s'''))\n" | ||
| 2409 | :type 'string | ||
| 2410 | :group 'python) | ||
| 2411 | 2852 | ||
| 2412 | (defcustom python-shell-completion-pdb-string-code | 2853 | (defcustom python-shell-completion-pdb-string-code |
| 2413 | "';'.join(globals().keys() + locals().keys())" | 2854 | "';'.join(globals().keys() + locals().keys())" |
| @@ -2430,33 +2871,23 @@ LINE is used to detect the context on how to complete given INPUT." | |||
| 2430 | (re-search-backward "^") | 2871 | (re-search-backward "^") |
| 2431 | (python-util-forward-comment) | 2872 | (python-util-forward-comment) |
| 2432 | (point)))))) | 2873 | (point)))))) |
| 2433 | (completion-context | 2874 | (completion-code |
| 2434 | ;; Check whether a prompt matches a pdb string, an import | 2875 | ;; Check whether a prompt matches a pdb string, an import |
| 2435 | ;; statement or just the standard prompt and use the | 2876 | ;; statement or just the standard prompt and use the |
| 2436 | ;; correct python-shell-completion-*-code string | 2877 | ;; correct python-shell-completion-*-code string |
| 2437 | (cond ((and (> (length python-shell-completion-pdb-string-code) 0) | 2878 | (cond ((and (> (length python-shell-completion-pdb-string-code) 0) |
| 2438 | (string-match | 2879 | (string-match |
| 2439 | (concat "^" python-shell-prompt-pdb-regexp) prompt)) | 2880 | (concat "^" python-shell-prompt-pdb-regexp) prompt)) |
| 2440 | 'pdb) | 2881 | python-shell-completion-pdb-string-code) |
| 2441 | ((and (> | ||
| 2442 | (length python-shell-completion-module-string-code) 0) | ||
| 2443 | (string-match | ||
| 2444 | (concat "^" python-shell-prompt-regexp) prompt) | ||
| 2445 | (string-match "^[ \t]*\\(from\\|import\\)[ \t]" line)) | ||
| 2446 | 'import) | ||
| 2447 | ((string-match | 2882 | ((string-match |
| 2448 | (concat "^" python-shell-prompt-regexp) prompt) | 2883 | python-shell--prompt-calculated-input-regexp prompt) |
| 2449 | 'default) | 2884 | python-shell-completion-string-code) |
| 2450 | (t nil))) | 2885 | (t nil))) |
| 2451 | (completion-code | ||
| 2452 | (pcase completion-context | ||
| 2453 | (`pdb python-shell-completion-pdb-string-code) | ||
| 2454 | (`import python-shell-completion-module-string-code) | ||
| 2455 | (`default python-shell-completion-string-code) | ||
| 2456 | (_ nil))) | ||
| 2457 | (input | 2886 | (input |
| 2458 | (if (eq completion-context 'import) | 2887 | (if (string-match |
| 2459 | (replace-regexp-in-string "^[ \t]+" "" line) | 2888 | (python-rx (+ space) (or "from" "import") space) |
| 2889 | line) | ||
| 2890 | line | ||
| 2460 | input))) | 2891 | input))) |
| 2461 | (and completion-code | 2892 | (and completion-code |
| 2462 | (> (length input) 0) | 2893 | (> (length input) 0) |
| @@ -2469,32 +2900,21 @@ LINE is used to detect the context on how to complete given INPUT." | |||
| 2469 | (split-string completions | 2900 | (split-string completions |
| 2470 | "^'\\|^\"\\|;\\|'$\\|\"$" t))))))) | 2901 | "^'\\|^\"\\|;\\|'$\\|\"$" t))))))) |
| 2471 | 2902 | ||
| 2472 | (defun python-shell-completion-complete-at-point (&optional process) | 2903 | (defun python-shell-completion-at-point (&optional process) |
| 2473 | "Perform completion at point in inferior Python. | 2904 | "Function for `completion-at-point-functions' in `inferior-python-mode'. |
| 2474 | Optional argument PROCESS forces completions to be retrieved | 2905 | Optional argument PROCESS forces completions to be retrieved |
| 2475 | using that one instead of current buffer's process." | 2906 | using that one instead of current buffer's process." |
| 2476 | (setq process (or process (get-buffer-process (current-buffer)))) | 2907 | (setq process (or process (get-buffer-process (current-buffer)))) |
| 2477 | (let* ((start | 2908 | (let* ((start |
| 2478 | (save-excursion | 2909 | (save-excursion |
| 2479 | (with-syntax-table python-dotty-syntax-table | 2910 | (if (not (re-search-backward |
| 2480 | (let* ((paren-depth (car (syntax-ppss))) | 2911 | (python-rx |
| 2481 | (syntax-string "w_") | 2912 | (or whitespace open-paren close-paren string-delimiter)) |
| 2482 | (syntax-list (string-to-syntax syntax-string))) | 2913 | (cdr (python-util-comint-last-prompt)) |
| 2483 | ;; Stop scanning for the beginning of the completion | 2914 | t 1)) |
| 2484 | ;; subject after the char before point matches a | 2915 | (cdr (python-util-comint-last-prompt)) |
| 2485 | ;; delimiter | 2916 | (forward-char (length (match-string-no-properties 0))) |
| 2486 | (while (member | 2917 | (point)))) |
| 2487 | (car (syntax-after (1- (point)))) syntax-list) | ||
| 2488 | (skip-syntax-backward syntax-string) | ||
| 2489 | (when (or (equal (char-before) ?\)) | ||
| 2490 | (equal (char-before) ?\")) | ||
| 2491 | (forward-char -1)) | ||
| 2492 | (while (or | ||
| 2493 | ;; honor initial paren depth | ||
| 2494 | (> (car (syntax-ppss)) paren-depth) | ||
| 2495 | (python-syntax-context 'string)) | ||
| 2496 | (forward-char -1))) | ||
| 2497 | (point))))) | ||
| 2498 | (end (point))) | 2918 | (end (point))) |
| 2499 | (list start end | 2919 | (list start end |
| 2500 | (completion-table-dynamic | 2920 | (completion-table-dynamic |
| @@ -2503,6 +2923,11 @@ using that one instead of current buffer's process." | |||
| 2503 | process (buffer-substring-no-properties | 2923 | process (buffer-substring-no-properties |
| 2504 | (line-beginning-position) end)))))) | 2924 | (line-beginning-position) end)))))) |
| 2505 | 2925 | ||
| 2926 | (define-obsolete-function-alias | ||
| 2927 | 'python-shell-completion-complete-at-point | ||
| 2928 | 'python-shell-completion-at-point | ||
| 2929 | "24.5") | ||
| 2930 | |||
| 2506 | (defun python-shell-completion-complete-or-indent () | 2931 | (defun python-shell-completion-complete-or-indent () |
| 2507 | "Complete or indent depending on the context. | 2932 | "Complete or indent depending on the context. |
| 2508 | If content before pointer is all whitespace, indent. | 2933 | If content before pointer is all whitespace, indent. |
| @@ -2609,18 +3034,19 @@ Argument OUTPUT is a string with the output from the comint process." | |||
| 2609 | 3034 | ||
| 2610 | ;;; Symbol completion | 3035 | ;;; Symbol completion |
| 2611 | 3036 | ||
| 2612 | (defun python-completion-complete-at-point () | 3037 | (defun python-completion-at-point () |
| 2613 | "Complete current symbol at point. | 3038 | "Function for `completion-at-point-functions' in `python-mode'. |
| 2614 | For this to work as best as possible you should call | 3039 | For this to work as best as possible you should call |
| 2615 | `python-shell-send-buffer' from time to time so context in | 3040 | `python-shell-send-buffer' from time to time so context in |
| 2616 | inferior Python process is updated properly." | 3041 | inferior Python process is updated properly." |
| 2617 | (let ((process (python-shell-get-process))) | 3042 | (let ((process (python-shell-get-process))) |
| 2618 | (if (not process) | 3043 | (when process |
| 2619 | (error "Completion needs an inferior Python process running") | 3044 | (python-shell-completion-at-point process)))) |
| 2620 | (python-shell-completion-complete-at-point process)))) | ||
| 2621 | 3045 | ||
| 2622 | (add-to-list 'debug-ignored-errors | 3046 | (define-obsolete-function-alias |
| 2623 | "^Completion needs an inferior Python process running.") | 3047 | 'python-completion-complete-at-point |
| 3048 | 'python-completion-at-point | ||
| 3049 | "24.5") | ||
| 2624 | 3050 | ||
| 2625 | 3051 | ||
| 2626 | ;;; Fill paragraph | 3052 | ;;; Fill paragraph |
| @@ -3138,8 +3564,7 @@ If not FORCE-INPUT is passed then what `python-info-current-symbol' | |||
| 3138 | returns will be used. If not FORCE-PROCESS is passed what | 3564 | returns will be used. If not FORCE-PROCESS is passed what |
| 3139 | `python-shell-get-process' returns is used." | 3565 | `python-shell-get-process' returns is used." |
| 3140 | (let ((process (or force-process (python-shell-get-process)))) | 3566 | (let ((process (or force-process (python-shell-get-process)))) |
| 3141 | (if (not process) | 3567 | (when process |
| 3142 | (error "Eldoc needs an inferior Python process running") | ||
| 3143 | (let ((input (or force-input | 3568 | (let ((input (or force-input |
| 3144 | (python-info-current-symbol t)))) | 3569 | (python-info-current-symbol t)))) |
| 3145 | (and input | 3570 | (and input |
| @@ -3166,9 +3591,6 @@ Interactively, prompt for symbol." | |||
| 3166 | nil nil symbol)))) | 3591 | nil nil symbol)))) |
| 3167 | (message (python-eldoc--get-doc-at-point symbol))) | 3592 | (message (python-eldoc--get-doc-at-point symbol))) |
| 3168 | 3593 | ||
| 3169 | (add-to-list 'debug-ignored-errors | ||
| 3170 | "^Eldoc needs an inferior Python process running.") | ||
| 3171 | |||
| 3172 | 3594 | ||
| 3173 | ;;; Imenu | 3595 | ;;; Imenu |
| 3174 | 3596 | ||
| @@ -3442,49 +3864,88 @@ parent defun name." | |||
| 3442 | (and (python-info-end-of-statement-p) | 3864 | (and (python-info-end-of-statement-p) |
| 3443 | (python-info-statement-ends-block-p))) | 3865 | (python-info-statement-ends-block-p))) |
| 3444 | 3866 | ||
| 3445 | (defun python-info-closing-block () | 3867 | (define-obsolete-function-alias |
| 3446 | "Return the point of the block the current line closes." | 3868 | 'python-info-closing-block |
| 3447 | (let ((closing-word (save-excursion | 3869 | 'python-info-dedenter-opening-block-position "24.4") |
| 3448 | (back-to-indentation) | 3870 | |
| 3449 | (current-word))) | 3871 | (defun python-info-dedenter-opening-block-position () |
| 3450 | (indentation (current-indentation))) | 3872 | "Return the point of the closest block the current line closes. |
| 3451 | (when (member closing-word python-indent-dedenters) | 3873 | Returns nil if point is not on a dedenter statement or no opening |
| 3874 | block can be detected. The latter case meaning current file is | ||
| 3875 | likely an invalid python file." | ||
| 3876 | (let ((positions (python-info-dedenter-opening-block-positions)) | ||
| 3877 | (indentation (current-indentation)) | ||
| 3878 | (position)) | ||
| 3879 | (while (and (not position) | ||
| 3880 | positions) | ||
| 3452 | (save-excursion | 3881 | (save-excursion |
| 3453 | (forward-line -1) | 3882 | (goto-char (car positions)) |
| 3454 | (while (and (> (current-indentation) indentation) | 3883 | (if (<= (current-indentation) indentation) |
| 3455 | (not (bobp)) | 3884 | (setq position (car positions)) |
| 3456 | (not (back-to-indentation)) | 3885 | (setq positions (cdr positions))))) |
| 3457 | (forward-line -1))) | 3886 | position)) |
| 3458 | (back-to-indentation) | 3887 | |
| 3459 | (cond | 3888 | (defun python-info-dedenter-opening-block-positions () |
| 3460 | ((not (equal indentation (current-indentation))) nil) | 3889 | "Return points of blocks the current line may close sorted by closer. |
| 3461 | ((string= closing-word "elif") | 3890 | Returns nil if point is not on a dedenter statement or no opening |
| 3462 | (when (member (current-word) '("if" "elif")) | 3891 | block can be detected. The latter case meaning current file is |
| 3463 | (point-marker))) | 3892 | likely an invalid python file." |
| 3464 | ((string= closing-word "else") | 3893 | (save-excursion |
| 3465 | (when (member (current-word) '("if" "elif" "except" "for" "while")) | 3894 | (let ((dedenter-pos (python-info-dedenter-statement-p))) |
| 3466 | (point-marker))) | 3895 | (when dedenter-pos |
| 3467 | ((string= closing-word "except") | 3896 | (goto-char dedenter-pos) |
| 3468 | (when (member (current-word) '("try")) | 3897 | (let* ((pairs '(("elif" "elif" "if") |
| 3469 | (point-marker))) | 3898 | ("else" "if" "elif" "except" "for" "while") |
| 3470 | ((string= closing-word "finally") | 3899 | ("except" "except" "try") |
| 3471 | (when (member (current-word) '("except" "else")) | 3900 | ("finally" "else" "except" "try"))) |
| 3472 | (point-marker)))))))) | 3901 | (dedenter (match-string-no-properties 0)) |
| 3473 | 3902 | (possible-opening-blocks (cdr (assoc-string dedenter pairs))) | |
| 3474 | (defun python-info-closing-block-message (&optional closing-block-point) | 3903 | (collected-indentations) |
| 3475 | "Message the contents of the block the current line closes. | 3904 | (opening-blocks)) |
| 3476 | With optional argument CLOSING-BLOCK-POINT use that instead of | 3905 | (catch 'exit |
| 3477 | recalculating it calling `python-info-closing-block'." | 3906 | (while (python-nav--syntactically |
| 3478 | (let ((point (or closing-block-point (python-info-closing-block)))) | 3907 | (lambda () |
| 3908 | (re-search-backward (python-rx block-start) nil t)) | ||
| 3909 | #'<) | ||
| 3910 | (let ((indentation (current-indentation))) | ||
| 3911 | (when (and (not (memq indentation collected-indentations)) | ||
| 3912 | (or (not collected-indentations) | ||
| 3913 | (< indentation (apply #'min collected-indentations)))) | ||
| 3914 | (setq collected-indentations | ||
| 3915 | (cons indentation collected-indentations)) | ||
| 3916 | (when (member (match-string-no-properties 0) | ||
| 3917 | possible-opening-blocks) | ||
| 3918 | (setq opening-blocks (cons (point) opening-blocks)))) | ||
| 3919 | (when (zerop indentation) | ||
| 3920 | (throw 'exit nil))))) | ||
| 3921 | ;; sort by closer | ||
| 3922 | (nreverse opening-blocks)))))) | ||
| 3923 | |||
| 3924 | (define-obsolete-function-alias | ||
| 3925 | 'python-info-closing-block-message | ||
| 3926 | 'python-info-dedenter-opening-block-message "24.4") | ||
| 3927 | |||
| 3928 | (defun python-info-dedenter-opening-block-message () | ||
| 3929 | "Message the first line of the block the current statement closes." | ||
| 3930 | (let ((point (python-info-dedenter-opening-block-position))) | ||
| 3479 | (when point | 3931 | (when point |
| 3480 | (save-restriction | 3932 | (save-restriction |
| 3481 | (widen) | 3933 | (widen) |
| 3482 | (message "Closes %s" (save-excursion | 3934 | (message "Closes %s" (save-excursion |
| 3483 | (goto-char point) | 3935 | (goto-char point) |
| 3484 | (back-to-indentation) | ||
| 3485 | (buffer-substring | 3936 | (buffer-substring |
| 3486 | (point) (line-end-position)))))))) | 3937 | (point) (line-end-position)))))))) |
| 3487 | 3938 | ||
| 3939 | (defun python-info-dedenter-statement-p () | ||
| 3940 | "Return point if current statement is a dedenter. | ||
| 3941 | Sets `match-data' to the keyword that starts the dedenter | ||
| 3942 | statement." | ||
| 3943 | (save-excursion | ||
| 3944 | (python-nav-beginning-of-statement) | ||
| 3945 | (when (and (not (python-syntax-context-type)) | ||
| 3946 | (looking-at (python-rx dedenter))) | ||
| 3947 | (point)))) | ||
| 3948 | |||
| 3488 | (defun python-info-line-ends-backslash-p (&optional line-number) | 3949 | (defun python-info-line-ends-backslash-p (&optional line-number) |
| 3489 | "Return non-nil if current line ends with backslash. | 3950 | "Return non-nil if current line ends with backslash. |
| 3490 | With optional argument LINE-NUMBER, check that line instead." | 3951 | With optional argument LINE-NUMBER, check that line instead." |
| @@ -3623,6 +4084,18 @@ to \"^python-\"." | |||
| 3623 | (cdr pair)))) | 4084 | (cdr pair)))) |
| 3624 | (buffer-local-variables from-buffer))) | 4085 | (buffer-local-variables from-buffer))) |
| 3625 | 4086 | ||
| 4087 | (defvar comint-last-prompt-overlay) ; Shut up, bytecompiler | ||
| 4088 | |||
| 4089 | (defun python-util-comint-last-prompt () | ||
| 4090 | "Return comint last prompt overlay start and end. | ||
| 4091 | This is for compatibility with Emacs < 24.4." | ||
| 4092 | (cond ((bound-and-true-p comint-last-prompt-overlay) | ||
| 4093 | (cons (overlay-start comint-last-prompt-overlay) | ||
| 4094 | (overlay-end comint-last-prompt-overlay))) | ||
| 4095 | ((bound-and-true-p comint-last-prompt) | ||
| 4096 | comint-last-prompt) | ||
| 4097 | (t nil))) | ||
| 4098 | |||
| 3626 | (defun python-util-forward-comment (&optional direction) | 4099 | (defun python-util-forward-comment (&optional direction) |
| 3627 | "Python mode specific version of `forward-comment'. | 4100 | "Python mode specific version of `forward-comment'. |
| 3628 | Optional argument DIRECTION defines the direction to move to." | 4101 | Optional argument DIRECTION defines the direction to move to." |
| @@ -3634,6 +4107,68 @@ Optional argument DIRECTION defines the direction to move to." | |||
| 3634 | (goto-char comment-start)) | 4107 | (goto-char comment-start)) |
| 3635 | (forward-comment factor))) | 4108 | (forward-comment factor))) |
| 3636 | 4109 | ||
| 4110 | (defun python-util-list-directories (directory &optional predicate max-depth) | ||
| 4111 | "List DIRECTORY subdirs, filtered by PREDICATE and limited by MAX-DEPTH. | ||
| 4112 | Argument PREDICATE defaults to `identity' and must be a function | ||
| 4113 | that takes one argument (a full path) and returns non-nil for | ||
| 4114 | allowed files. When optional argument MAX-DEPTH is non-nil, stop | ||
| 4115 | searching when depth is reached, else don't limit." | ||
| 4116 | (let* ((dir (expand-file-name directory)) | ||
| 4117 | (dir-length (length dir)) | ||
| 4118 | (predicate (or predicate #'identity)) | ||
| 4119 | (to-scan (list dir)) | ||
| 4120 | (tally nil)) | ||
| 4121 | (while to-scan | ||
| 4122 | (let ((current-dir (car to-scan))) | ||
| 4123 | (when (funcall predicate current-dir) | ||
| 4124 | (setq tally (cons current-dir tally))) | ||
| 4125 | (setq to-scan (append (cdr to-scan) | ||
| 4126 | (python-util-list-files | ||
| 4127 | current-dir #'file-directory-p) | ||
| 4128 | nil)) | ||
| 4129 | (when (and max-depth | ||
| 4130 | (<= max-depth | ||
| 4131 | (length (split-string | ||
| 4132 | (substring current-dir dir-length) | ||
| 4133 | "/\\|\\\\" t)))) | ||
| 4134 | (setq to-scan nil)))) | ||
| 4135 | (nreverse tally))) | ||
| 4136 | |||
| 4137 | (defun python-util-list-files (dir &optional predicate) | ||
| 4138 | "List files in DIR, filtering with PREDICATE. | ||
| 4139 | Argument PREDICATE defaults to `identity' and must be a function | ||
| 4140 | that takes one argument (a full path) and returns non-nil for | ||
| 4141 | allowed files." | ||
| 4142 | (let ((dir-name (file-name-as-directory dir))) | ||
| 4143 | (apply #'nconc | ||
| 4144 | (mapcar (lambda (file-name) | ||
| 4145 | (let ((full-file-name (expand-file-name file-name dir-name))) | ||
| 4146 | (when (and | ||
| 4147 | (not (member file-name '("." ".."))) | ||
| 4148 | (funcall (or predicate #'identity) full-file-name)) | ||
| 4149 | (list full-file-name)))) | ||
| 4150 | (directory-files dir-name))))) | ||
| 4151 | |||
| 4152 | (defun python-util-list-packages (dir &optional max-depth) | ||
| 4153 | "List packages in DIR, limited by MAX-DEPTH. | ||
| 4154 | When optional argument MAX-DEPTH is non-nil, stop searching when | ||
| 4155 | depth is reached, else don't limit." | ||
| 4156 | (let* ((dir (expand-file-name dir)) | ||
| 4157 | (parent-dir (file-name-directory | ||
| 4158 | (directory-file-name | ||
| 4159 | (file-name-directory | ||
| 4160 | (file-name-as-directory dir))))) | ||
| 4161 | (subpath-length (length parent-dir))) | ||
| 4162 | (mapcar | ||
| 4163 | (lambda (file-name) | ||
| 4164 | (replace-regexp-in-string | ||
| 4165 | (rx (or ?\\ ?/)) "." (substring file-name subpath-length))) | ||
| 4166 | (python-util-list-directories | ||
| 4167 | (directory-file-name dir) | ||
| 4168 | (lambda (dir) | ||
| 4169 | (file-exists-p (expand-file-name "__init__.py" dir))) | ||
| 4170 | max-depth)))) | ||
| 4171 | |||
| 3637 | (defun python-util-popn (lst n) | 4172 | (defun python-util-popn (lst n) |
| 3638 | "Return LST first N elements. | 4173 | "Return LST first N elements. |
| 3639 | N should be an integer, when negative its opposite is used. | 4174 | N should be an integer, when negative its opposite is used. |
| @@ -3650,6 +4185,23 @@ returned as is." | |||
| 3650 | n (1- n))) | 4185 | n (1- n))) |
| 3651 | (reverse acc)))) | 4186 | (reverse acc)))) |
| 3652 | 4187 | ||
| 4188 | (defun python-util-text-properties-replace-name | ||
| 4189 | (from to &optional start end) | ||
| 4190 | "Replace properties named FROM to TO, keeping its value. | ||
| 4191 | Arguments START and END narrow the buffer region to work on." | ||
| 4192 | (save-excursion | ||
| 4193 | (goto-char (or start (point-min))) | ||
| 4194 | (while (not (eobp)) | ||
| 4195 | (let ((plist (text-properties-at (point))) | ||
| 4196 | (next-change (or (next-property-change (point) (current-buffer)) | ||
| 4197 | (or end (point-max))))) | ||
| 4198 | (when (plist-get plist from) | ||
| 4199 | (let* ((face (plist-get plist from)) | ||
| 4200 | (plist (plist-put plist from nil)) | ||
| 4201 | (plist (plist-put plist to face))) | ||
| 4202 | (set-text-properties (point) next-change plist (current-buffer)))) | ||
| 4203 | (goto-char next-change))))) | ||
| 4204 | |||
| 3653 | (defun python-util-strip-string (string) | 4205 | (defun python-util-strip-string (string) |
| 3654 | "Strip STRING whitespace and newlines from end and beginning." | 4206 | "Strip STRING whitespace and newlines from end and beginning." |
| 3655 | (replace-regexp-in-string | 4207 | (replace-regexp-in-string |
| @@ -3658,6 +4210,10 @@ returned as is." | |||
| 3658 | "" | 4210 | "" |
| 3659 | string)) | 4211 | string)) |
| 3660 | 4212 | ||
| 4213 | (defun python-util-valid-regexp-p (regexp) | ||
| 4214 | "Return non-nil if REGEXP is valid." | ||
| 4215 | (ignore-errors (string-match regexp "") t)) | ||
| 4216 | |||
| 3661 | 4217 | ||
| 3662 | (defun python-electric-pair-string-delimiter () | 4218 | (defun python-electric-pair-string-delimiter () |
| 3663 | (when (and electric-pair-mode | 4219 | (when (and electric-pair-mode |
| @@ -3715,7 +4271,7 @@ returned as is." | |||
| 3715 | #'python-nav-end-of-defun) | 4271 | #'python-nav-end-of-defun) |
| 3716 | 4272 | ||
| 3717 | (add-hook 'completion-at-point-functions | 4273 | (add-hook 'completion-at-point-functions |
| 3718 | #'python-completion-complete-at-point nil 'local) | 4274 | #'python-completion-at-point nil 'local) |
| 3719 | 4275 | ||
| 3720 | (add-hook 'post-self-insert-hook | 4276 | (add-hook 'post-self-insert-hook |
| 3721 | #'python-indent-post-self-insert-function 'append 'local) | 4277 | #'python-indent-post-self-insert-function 'append 'local) |
| @@ -3742,8 +4298,6 @@ returned as is." | |||
| 3742 | ,(lambda (_arg) | 4298 | ,(lambda (_arg) |
| 3743 | (python-nav-end-of-defun)) nil)) | 4299 | (python-nav-end-of-defun)) nil)) |
| 3744 | 4300 | ||
| 3745 | (set (make-local-variable 'mode-require-final-newline) t) | ||
| 3746 | |||
| 3747 | (set (make-local-variable 'outline-regexp) | 4301 | (set (make-local-variable 'outline-regexp) |
| 3748 | (python-rx (* space) block-start)) | 4302 | (python-rx (* space) block-start)) |
| 3749 | (set (make-local-variable 'outline-heading-end-regexp) ":[^\n]*\n") | 4303 | (set (make-local-variable 'outline-heading-end-regexp) ":[^\n]*\n") |