aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el288
1 files changed, 165 insertions, 123 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index d340550a017..303c36c3932 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -1068,7 +1068,9 @@ minimum."
1068 (levels (python-indent--calculate-levels indentation))) 1068 (levels (python-indent--calculate-levels indentation)))
1069 (if previous 1069 (if previous
1070 (python-indent--previous-level levels (current-indentation)) 1070 (python-indent--previous-level levels (current-indentation))
1071 (apply #'max levels)))) 1071 (if levels
1072 (apply #'max levels)
1073 0))))
1072 1074
1073(defun python-indent-line (&optional previous) 1075(defun python-indent-line (&optional previous)
1074 "Internal implementation of `python-indent-line-function'. 1076 "Internal implementation of `python-indent-line-function'.
@@ -2331,57 +2333,57 @@ goes wrong and syntax highlighting in the shell gets messed up."
2331 (interactive) 2333 (interactive)
2332 (python-shell-with-shell-buffer 2334 (python-shell-with-shell-buffer
2333 (python-shell-font-lock-with-font-lock-buffer 2335 (python-shell-font-lock-with-font-lock-buffer
2334 (delete-region (point-min) (point-max))))) 2336 (erase-buffer))))
2335 2337
2336(defun python-shell-font-lock-comint-output-filter-function (output) 2338(defun python-shell-font-lock-comint-output-filter-function (output)
2337 "Clean up the font-lock buffer after any OUTPUT." 2339 "Clean up the font-lock buffer after any OUTPUT."
2338 (when (and (not (string= "" output)) 2340 (if (and (not (string= "" output))
2339 ;; Is end of output and is not just a prompt. 2341 ;; Is end of output and is not just a prompt.
2340 (not (member 2342 (not (member
2341 (python-shell-comint-end-of-output-p 2343 (python-shell-comint-end-of-output-p
2342 (ansi-color-filter-apply output)) 2344 (ansi-color-filter-apply output))
2343 '(nil 0)))) 2345 '(nil 0))))
2344 ;; If output is other than an input prompt then "real" output has 2346 ;; If output is other than an input prompt then "real" output has
2345 ;; been received and the font-lock buffer must be cleaned up. 2347 ;; been received and the font-lock buffer must be cleaned up.
2346 (python-shell-font-lock-cleanup-buffer)) 2348 (python-shell-font-lock-cleanup-buffer)
2349 ;; Otherwise just add a newline.
2350 (python-shell-font-lock-with-font-lock-buffer
2351 (goto-char (point-max))
2352 (newline)))
2347 output) 2353 output)
2348 2354
2349(defun python-shell-font-lock-post-command-hook () 2355(defun python-shell-font-lock-post-command-hook ()
2350 "Fontifies current line in shell buffer." 2356 "Fontifies current line in shell buffer."
2351 (if (eq this-command 'comint-send-input) 2357 (when (and (python-util-comint-last-prompt)
2352 ;; Add a newline when user sends input as this may be a block. 2358 (> (point) (cdr (python-util-comint-last-prompt))))
2353 (python-shell-font-lock-with-font-lock-buffer 2359 (let ((input (buffer-substring-no-properties
2354 (goto-char (line-end-position)) 2360 (cdr (python-util-comint-last-prompt)) (point-max)))
2355 (newline)) 2361 (pos (point))
2356 (when (and (python-util-comint-last-prompt) 2362 (buffer-undo-list t)
2357 (> (point) (cdr (python-util-comint-last-prompt)))) 2363 (font-lock-buffer-pos nil))
2358 (let ((input (buffer-substring-no-properties 2364 ;; Keep all markers untouched, this prevents `hippie-expand' and
2359 (cdr (python-util-comint-last-prompt)) (point-max))) 2365 ;; others from getting confused. Bug#19650.
2360 (old-input (python-shell-font-lock-with-font-lock-buffer 2366 (insert-before-markers
2361 (buffer-substring-no-properties 2367 (python-shell-font-lock-with-font-lock-buffer
2362 (line-beginning-position) (point-max)))) 2368 (delete-region (line-beginning-position)
2363 (current-point (point)) 2369 (point-max))
2364 (buffer-undo-list t)) 2370 (setq font-lock-buffer-pos (point))
2365 ;; When input hasn't changed, do nothing. 2371 (insert input)
2366 (when (not (string= input old-input)) 2372 ;; Ensure buffer is fontified, keeping it
2367 (delete-region (cdr (python-util-comint-last-prompt)) (point-max)) 2373 ;; compatible with Emacs < 24.4.
2368 (insert 2374 (if (fboundp 'font-lock-ensure)
2369 (python-shell-font-lock-with-font-lock-buffer 2375 (funcall 'font-lock-ensure)
2370 (delete-region (line-beginning-position) 2376 (font-lock-default-fontify-buffer))
2371 (line-end-position)) 2377 ;; Replace FACE text properties with FONT-LOCK-FACE so
2372 (insert input) 2378 ;; they are not overwritten by comint buffer's font lock.
2373 ;; Ensure buffer is fontified, keeping it 2379 (python-util-text-properties-replace-name
2374 ;; compatible with Emacs < 24.4. 2380 'face 'font-lock-face)
2375 (if (fboundp 'font-lock-ensure) 2381 (buffer-substring font-lock-buffer-pos
2376 (funcall 'font-lock-ensure) 2382 (point-max))))
2377 (font-lock-default-fontify-buffer)) 2383 ;; Remove non-fontified original text.
2378 ;; Replace FACE text properties with FONT-LOCK-FACE so 2384 (delete-region pos (cdr (python-util-comint-last-prompt)))
2379 ;; they are not overwritten by comint buffer's font lock. 2385 ;; Point should be already at pos, this is for extra safety.
2380 (python-util-text-properties-replace-name 2386 (goto-char pos))))
2381 'face 'font-lock-face)
2382 (buffer-substring (line-beginning-position)
2383 (line-end-position))))
2384 (goto-char current-point))))))
2385 2387
2386(defun python-shell-font-lock-turn-on (&optional msg) 2388(defun python-shell-font-lock-turn-on (&optional msg)
2387 "Turn on shell font-lock. 2389 "Turn on shell font-lock.
@@ -3148,67 +3150,68 @@ With argument MSG show activation/deactivation message."
3148 "Get completions using native readline for PROCESS. 3150 "Get completions using native readline for PROCESS.
3149When IMPORT is non-nil takes precedence over INPUT for 3151When IMPORT is non-nil takes precedence over INPUT for
3150completion." 3152completion."
3151 (when (and python-shell-completion-native-enable 3153 (with-current-buffer (process-buffer process)
3152 (python-util-comint-last-prompt) 3154 (when (and python-shell-completion-native-enable
3153 (>= (point) (cdr (python-util-comint-last-prompt)))) 3155 (python-util-comint-last-prompt)
3154 (let* ((input (or import input)) 3156 (>= (point) (cdr (python-util-comint-last-prompt))))
3155 (original-filter-fn (process-filter process)) 3157 (let* ((input (or import input))
3156 (redirect-buffer (get-buffer-create 3158 (original-filter-fn (process-filter process))
3157 python-shell-completion-native-redirect-buffer)) 3159 (redirect-buffer (get-buffer-create
3158 (separators (python-rx 3160 python-shell-completion-native-redirect-buffer))
3159 (or whitespace open-paren close-paren))) 3161 (separators (python-rx
3160 (trigger "\t\t\t") 3162 (or whitespace open-paren close-paren)))
3161 (new-input (concat input trigger)) 3163 (trigger "\t\t\t")
3162 (input-length 3164 (new-input (concat input trigger))
3163 (save-excursion 3165 (input-length
3164 (+ (- (point-max) (comint-bol)) (length new-input)))) 3166 (save-excursion
3165 (delete-line-command (make-string input-length ?\b)) 3167 (+ (- (point-max) (comint-bol)) (length new-input))))
3166 (input-to-send (concat new-input delete-line-command))) 3168 (delete-line-command (make-string input-length ?\b))
3167 ;; Ensure restoring the process filter, even if the user quits 3169 (input-to-send (concat new-input delete-line-command)))
3168 ;; or there's some other error. 3170 ;; Ensure restoring the process filter, even if the user quits
3169 (unwind-protect 3171 ;; or there's some other error.
3170 (with-current-buffer redirect-buffer 3172 (unwind-protect
3171 ;; Cleanup the redirect buffer 3173 (with-current-buffer redirect-buffer
3172 (delete-region (point-min) (point-max)) 3174 ;; Cleanup the redirect buffer
3173 ;; Mimic `comint-redirect-send-command', unfortunately it 3175 (delete-region (point-min) (point-max))
3174 ;; can't be used here because it expects a newline in the 3176 ;; Mimic `comint-redirect-send-command', unfortunately it
3175 ;; command and that's exactly what we are trying to avoid. 3177 ;; can't be used here because it expects a newline in the
3176 (let ((comint-redirect-echo-input nil) 3178 ;; command and that's exactly what we are trying to avoid.
3177 (comint-redirect-verbose nil) 3179 (let ((comint-redirect-echo-input nil)
3178 (comint-redirect-perform-sanity-check nil) 3180 (comint-redirect-verbose nil)
3179 (comint-redirect-insert-matching-regexp nil) 3181 (comint-redirect-perform-sanity-check nil)
3180 ;; Feed it some regex that will never match. 3182 (comint-redirect-insert-matching-regexp nil)
3181 (comint-redirect-finished-regexp "^\\'$") 3183 ;; Feed it some regex that will never match.
3182 (comint-redirect-output-buffer redirect-buffer)) 3184 (comint-redirect-finished-regexp "^\\'$")
3183 ;; Compatibility with Emacs 24.x. Comint changed and 3185 (comint-redirect-output-buffer redirect-buffer))
3184 ;; now `comint-redirect-filter' gets 3 args. This 3186 ;; Compatibility with Emacs 24.x. Comint changed and
3185 ;; checks which version of `comint-redirect-filter' is 3187 ;; now `comint-redirect-filter' gets 3 args. This
3186 ;; in use based on its args and uses `apply-partially' 3188 ;; checks which version of `comint-redirect-filter' is
3187 ;; to make it up for the 3 args case. 3189 ;; in use based on its args and uses `apply-partially'
3188 (if (= (length 3190 ;; to make it up for the 3 args case.
3189 (help-function-arglist 'comint-redirect-filter)) 3) 3191 (if (= (length
3190 (set-process-filter 3192 (help-function-arglist 'comint-redirect-filter)) 3)
3191 process (apply-partially 3193 (set-process-filter
3192 #'comint-redirect-filter original-filter-fn)) 3194 process (apply-partially
3193 (set-process-filter process #'comint-redirect-filter)) 3195 #'comint-redirect-filter original-filter-fn))
3194 (process-send-string process input-to-send) 3196 (set-process-filter process #'comint-redirect-filter))
3195 (accept-process-output 3197 (process-send-string process input-to-send)
3196 process 3198 (accept-process-output
3197 python-shell-completion-native-output-timeout) 3199 process
3198 ;; XXX: can't use `python-shell-accept-process-output' 3200 python-shell-completion-native-output-timeout)
3199 ;; here because there are no guarantees on how output 3201 ;; XXX: can't use `python-shell-accept-process-output'
3200 ;; ends. The workaround here is to call 3202 ;; here because there are no guarantees on how output
3201 ;; `accept-process-output' until we don't find anything 3203 ;; ends. The workaround here is to call
3202 ;; else to accept. 3204 ;; `accept-process-output' until we don't find anything
3203 (while (accept-process-output 3205 ;; else to accept.
3204 process 3206 (while (accept-process-output
3205 python-shell-completion-native-output-timeout)) 3207 process
3206 (cl-remove-duplicates 3208 python-shell-completion-native-output-timeout))
3207 (split-string 3209 (cl-remove-duplicates
3208 (buffer-substring-no-properties 3210 (split-string
3209 (point-min) (point-max)) 3211 (buffer-substring-no-properties
3210 separators t)))) 3212 (point-min) (point-max))
3211 (set-process-filter process original-filter-fn))))) 3213 separators t))))
3214 (set-process-filter process original-filter-fn))))))
3212 3215
3213(defun python-shell-completion-get-completions (process import input) 3216(defun python-shell-completion-get-completions (process import input)
3214 "Do completion at point using PROCESS for IMPORT or INPUT. 3217 "Do completion at point using PROCESS for IMPORT or INPUT.
@@ -3251,20 +3254,23 @@ completion."
3251Optional argument PROCESS forces completions to be retrieved 3254Optional argument PROCESS forces completions to be retrieved
3252using that one instead of current buffer's process." 3255using that one instead of current buffer's process."
3253 (setq process (or process (get-buffer-process (current-buffer)))) 3256 (setq process (or process (get-buffer-process (current-buffer))))
3254 (let* ((last-prompt-end (cdr (python-util-comint-last-prompt))) 3257 (let* ((line-start (if (derived-mode-p 'inferior-python-mode)
3258 ;; Working on a shell buffer: use prompt end.
3259 (cdr (python-util-comint-last-prompt))
3260 (line-beginning-position)))
3255 (import-statement 3261 (import-statement
3256 (when (string-match-p 3262 (when (string-match-p
3257 (rx (* space) word-start (or "from" "import") word-end space) 3263 (rx (* space) word-start (or "from" "import") word-end space)
3258 (buffer-substring-no-properties last-prompt-end (point))) 3264 (buffer-substring-no-properties line-start (point)))
3259 (buffer-substring-no-properties last-prompt-end (point)))) 3265 (buffer-substring-no-properties line-start (point))))
3260 (start 3266 (start
3261 (save-excursion 3267 (save-excursion
3262 (if (not (re-search-backward 3268 (if (not (re-search-backward
3263 (python-rx 3269 (python-rx
3264 (or whitespace open-paren close-paren string-delimiter)) 3270 (or whitespace open-paren close-paren string-delimiter))
3265 last-prompt-end 3271 line-start
3266 t 1)) 3272 t 1))
3267 last-prompt-end 3273 line-start
3268 (forward-char (length (match-string-no-properties 0))) 3274 (forward-char (length (match-string-no-properties 0)))
3269 (point)))) 3275 (point))))
3270 (end (point)) 3276 (end (point))
@@ -3847,8 +3853,10 @@ The skeleton will be bound to python-skeleton-NAME."
3847 :type 'string 3853 :type 'string
3848 :group 'python) 3854 :group 'python)
3849 3855
3850(defvar-local python-check-custom-command nil 3856(defvar python-check-custom-command nil
3851 "Internal use.") 3857 "Internal use.")
3858;; XXX: Avoid `defvar-local' for compat with Emacs<24.3
3859(make-variable-buffer-local 'python-check-custom-command)
3852 3860
3853(defun python-check (command) 3861(defun python-check (command)
3854 "Check a Python file (default current buffer's file). 3862 "Check a Python file (default current buffer's file).
@@ -3917,15 +3925,29 @@ See `python-check-command' for the default."
3917 :type 'string 3925 :type 'string
3918 :group 'python) 3926 :group 'python)
3919 3927
3928(defun python-eldoc--get-symbol-at-point ()
3929 "Get the current symbol for eldoc.
3930Returns the current symbol handling point within arguments."
3931 (save-excursion
3932 (let ((start (python-syntax-context 'paren)))
3933 (when start
3934 (goto-char start))
3935 (when (or start
3936 (eobp)
3937 (memq (char-syntax (char-after)) '(?\ ?-)))
3938 ;; Try to adjust to closest symbol if not in one.
3939 (python-util-forward-comment -1)))
3940 (python-info-current-symbol t)))
3941
3920(defun python-eldoc--get-doc-at-point (&optional force-input force-process) 3942(defun python-eldoc--get-doc-at-point (&optional force-input force-process)
3921 "Internal implementation to get documentation at point. 3943 "Internal implementation to get documentation at point.
3922If not FORCE-INPUT is passed then what `python-info-current-symbol' 3944If not FORCE-INPUT is passed then what `python-eldoc--get-symbol-at-point'
3923returns will be used. If not FORCE-PROCESS is passed what 3945returns will be used. If not FORCE-PROCESS is passed what
3924`python-shell-get-process' returns is used." 3946`python-shell-get-process' returns is used."
3925 (let ((process (or force-process (python-shell-get-process)))) 3947 (let ((process (or force-process (python-shell-get-process))))
3926 (when process 3948 (when process
3927 (let ((input (or force-input 3949 (let ((input (or force-input
3928 (python-info-current-symbol t)))) 3950 (python-eldoc--get-symbol-at-point))))
3929 (and input 3951 (and input
3930 ;; Prevent resizing the echo area when iPython is 3952 ;; Prevent resizing the echo area when iPython is
3931 ;; enabled. Bug#18794. 3953 ;; enabled. Bug#18794.
@@ -3945,7 +3967,7 @@ inferior Python process is updated properly."
3945 "Get help on SYMBOL using `help'. 3967 "Get help on SYMBOL using `help'.
3946Interactively, prompt for symbol." 3968Interactively, prompt for symbol."
3947 (interactive 3969 (interactive
3948 (let ((symbol (python-info-current-symbol t)) 3970 (let ((symbol (python-eldoc--get-symbol-at-point))
3949 (enable-recursive-minibuffers t)) 3971 (enable-recursive-minibuffers t))
3950 (list (read-string (if symbol 3972 (list (read-string (if symbol
3951 (format "Describe symbol (default %s): " symbol) 3973 (format "Describe symbol (default %s): " symbol)
@@ -3954,6 +3976,17 @@ Interactively, prompt for symbol."
3954 (message (python-eldoc--get-doc-at-point symbol))) 3976 (message (python-eldoc--get-doc-at-point symbol)))
3955 3977
3956 3978
3979;;; Hideshow
3980
3981(defun python-hideshow-forward-sexp-function (arg)
3982 "Python specific `forward-sexp' function for `hs-minor-mode'.
3983Argument ARG is ignored."
3984 arg ; Shut up, byte compiler.
3985 (python-nav-end-of-defun)
3986 (unless (python-info-current-line-empty-p)
3987 (backward-char)))
3988
3989
3957;;; Imenu 3990;;; Imenu
3958 3991
3959(defvar python-imenu-format-item-label-function 3992(defvar python-imenu-format-item-label-function
@@ -4682,14 +4715,23 @@ Arguments START and END narrow the buffer region to work on."
4682 (current-column)))) 4715 (current-column))))
4683 (^ '(- (1+ (current-indentation)))))) 4716 (^ '(- (1+ (current-indentation))))))
4684 4717
4685 (add-function :before-until (local 'eldoc-documentation-function) 4718 (if (null eldoc-documentation-function)
4686 #'python-eldoc-function) 4719 ;; Emacs<25
4687 4720 (setq (make-local-variable 'eldoc-documentation-function)
4688 (add-to-list 'hs-special-modes-alist 4721 #'python-eldoc-function)
4689 `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#" 4722 (add-function :before-until (local 'eldoc-documentation-function)
4690 ,(lambda (_arg) 4723 #'python-eldoc-function))
4691 (python-nav-end-of-defun)) 4724
4692 nil)) 4725 (add-to-list
4726 'hs-special-modes-alist
4727 `(python-mode
4728 "\\s-*\\(?:def\\|class\\)\\>"
4729 ;; Use the empty string as end regexp so it doesn't default to
4730 ;; "\\s)". This way parens at end of defun are properly hidden.
4731 ""
4732 "#"
4733 python-hideshow-forward-sexp-function
4734 nil))
4693 4735
4694 (set (make-local-variable 'outline-regexp) 4736 (set (make-local-variable 'outline-regexp)
4695 (python-rx (* space) block-start)) 4737 (python-rx (* space) block-start))