summaryrefslogtreecommitdiff
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorJoakim Verona <joakim@verona.se>2015-02-08 21:55:28 +0100
committerJoakim Verona <joakim@verona.se>2015-02-08 21:55:28 +0100
commit5e1d5ef39ca0d2fbff26d659f2ec6ce863b14529 (patch)
tree860e0d53399626aee6249ebb5f972879f403b228 /lisp/progmodes/python.el
parent148262ce3db990ed16989341345e232570b3a338 (diff)
parent7d631aa0ffab875e4979727f632703ad5b4100a2 (diff)
downloademacs-xwidget.tar.gz
merge masterxwidget
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."
(levels (python-indent--calculate-levels indentation)))
(if previous
(python-indent--previous-level levels (current-indentation))
- (apply #'max levels))))
+ (if levels
+ (apply #'max levels)
+ 0))))
(defun python-indent-line (&optional previous)
"Internal implementation of `python-indent-line-function'.
@@ -2331,57 +2333,57 @@ goes wrong and syntax highlighting in the shell gets messed up."
(interactive)
(python-shell-with-shell-buffer
(python-shell-font-lock-with-font-lock-buffer
- (delete-region (point-min) (point-max)))))
+ (erase-buffer))))
(defun python-shell-font-lock-comint-output-filter-function (output)
"Clean up the font-lock buffer after any OUTPUT."
- (when (and (not (string= "" output))
- ;; Is end of output and is not just a prompt.
- (not (member
- (python-shell-comint-end-of-output-p
- (ansi-color-filter-apply output))
- '(nil 0))))
- ;; If output is other than an input prompt then "real" output has
- ;; been received and the font-lock buffer must be cleaned up.
- (python-shell-font-lock-cleanup-buffer))
+ (if (and (not (string= "" output))
+ ;; Is end of output and is not just a prompt.
+ (not (member
+ (python-shell-comint-end-of-output-p
+ (ansi-color-filter-apply output))
+ '(nil 0))))
+ ;; If output is other than an input prompt then "real" output has
+ ;; been received and the font-lock buffer must be cleaned up.
+ (python-shell-font-lock-cleanup-buffer)
+ ;; Otherwise just add a newline.
+ (python-shell-font-lock-with-font-lock-buffer
+ (goto-char (point-max))
+ (newline)))
output)
(defun python-shell-font-lock-post-command-hook ()
"Fontifies current line in shell buffer."
- (if (eq this-command 'comint-send-input)
- ;; Add a newline when user sends input as this may be a block.
- (python-shell-font-lock-with-font-lock-buffer
- (goto-char (line-end-position))
- (newline))
- (when (and (python-util-comint-last-prompt)
- (> (point) (cdr (python-util-comint-last-prompt))))
- (let ((input (buffer-substring-no-properties
- (cdr (python-util-comint-last-prompt)) (point-max)))
- (old-input (python-shell-font-lock-with-font-lock-buffer
- (buffer-substring-no-properties
- (line-beginning-position) (point-max))))
- (current-point (point))
- (buffer-undo-list t))
- ;; When input hasn't changed, do nothing.
- (when (not (string= input old-input))
- (delete-region (cdr (python-util-comint-last-prompt)) (point-max))
- (insert
- (python-shell-font-lock-with-font-lock-buffer
- (delete-region (line-beginning-position)
- (line-end-position))
- (insert input)
- ;; Ensure buffer is fontified, keeping it
- ;; compatible with Emacs < 24.4.
- (if (fboundp 'font-lock-ensure)
- (funcall 'font-lock-ensure)
- (font-lock-default-fontify-buffer))
- ;; Replace FACE text properties with FONT-LOCK-FACE so
- ;; they are not overwritten by comint buffer's font lock.
- (python-util-text-properties-replace-name
- 'face 'font-lock-face)
- (buffer-substring (line-beginning-position)
- (line-end-position))))
- (goto-char current-point))))))
+ (when (and (python-util-comint-last-prompt)
+ (> (point) (cdr (python-util-comint-last-prompt))))
+ (let ((input (buffer-substring-no-properties
+ (cdr (python-util-comint-last-prompt)) (point-max)))
+ (pos (point))
+ (buffer-undo-list t)
+ (font-lock-buffer-pos nil))
+ ;; Keep all markers untouched, this prevents `hippie-expand' and
+ ;; others from getting confused. Bug#19650.
+ (insert-before-markers
+ (python-shell-font-lock-with-font-lock-buffer
+ (delete-region (line-beginning-position)
+ (point-max))
+ (setq font-lock-buffer-pos (point))
+ (insert input)
+ ;; Ensure buffer is fontified, keeping it
+ ;; compatible with Emacs < 24.4.
+ (if (fboundp 'font-lock-ensure)
+ (funcall 'font-lock-ensure)
+ (font-lock-default-fontify-buffer))
+ ;; Replace FACE text properties with FONT-LOCK-FACE so
+ ;; they are not overwritten by comint buffer's font lock.
+ (python-util-text-properties-replace-name
+ 'face 'font-lock-face)
+ (buffer-substring font-lock-buffer-pos
+ (point-max))))
+ ;; Remove non-fontified original text.
+ (delete-region pos (cdr (python-util-comint-last-prompt)))
+ ;; Point should be already at pos, this is for extra safety.
+ (goto-char pos))))
(defun python-shell-font-lock-turn-on (&optional msg)
"Turn on shell font-lock.
@@ -3148,67 +3150,68 @@ With argument MSG show activation/deactivation message."
"Get completions using native readline for PROCESS.
When IMPORT is non-nil takes precedence over INPUT for
completion."
- (when (and python-shell-completion-native-enable
- (python-util-comint-last-prompt)
- (>= (point) (cdr (python-util-comint-last-prompt))))
- (let* ((input (or import input))
- (original-filter-fn (process-filter process))
- (redirect-buffer (get-buffer-create
- python-shell-completion-native-redirect-buffer))
- (separators (python-rx
- (or whitespace open-paren close-paren)))
- (trigger "\t\t\t")
- (new-input (concat input trigger))
- (input-length
- (save-excursion
- (+ (- (point-max) (comint-bol)) (length new-input))))
- (delete-line-command (make-string input-length ?\b))
- (input-to-send (concat new-input delete-line-command)))
- ;; Ensure restoring the process filter, even if the user quits
- ;; or there's some other error.
- (unwind-protect
- (with-current-buffer redirect-buffer
- ;; Cleanup the redirect buffer
- (delete-region (point-min) (point-max))
- ;; Mimic `comint-redirect-send-command', unfortunately it
- ;; can't be used here because it expects a newline in the
- ;; command and that's exactly what we are trying to avoid.
- (let ((comint-redirect-echo-input nil)
- (comint-redirect-verbose nil)
- (comint-redirect-perform-sanity-check nil)
- (comint-redirect-insert-matching-regexp nil)
- ;; Feed it some regex that will never match.
- (comint-redirect-finished-regexp "^\\'$")
- (comint-redirect-output-buffer redirect-buffer))
- ;; Compatibility with Emacs 24.x. Comint changed and
- ;; now `comint-redirect-filter' gets 3 args. This
- ;; checks which version of `comint-redirect-filter' is
- ;; in use based on its args and uses `apply-partially'
- ;; to make it up for the 3 args case.
- (if (= (length
- (help-function-arglist 'comint-redirect-filter)) 3)
- (set-process-filter
- process (apply-partially
- #'comint-redirect-filter original-filter-fn))
- (set-process-filter process #'comint-redirect-filter))
- (process-send-string process input-to-send)
- (accept-process-output
- process
- python-shell-completion-native-output-timeout)
- ;; XXX: can't use `python-shell-accept-process-output'
- ;; here because there are no guarantees on how output
- ;; ends. The workaround here is to call
- ;; `accept-process-output' until we don't find anything
- ;; else to accept.
- (while (accept-process-output
- process
- python-shell-completion-native-output-timeout))
- (cl-remove-duplicates
- (split-string
- (buffer-substring-no-properties
- (point-min) (point-max))
- separators t))))
- (set-process-filter process original-filter-fn)))))
+ (with-current-buffer (process-buffer process)
+ (when (and python-shell-completion-native-enable
+ (python-util-comint-last-prompt)
+ (>= (point) (cdr (python-util-comint-last-prompt))))
+ (let* ((input (or import input))
+ (original-filter-fn (process-filter process))
+ (redirect-buffer (get-buffer-create
+ python-shell-completion-native-redirect-buffer))
+ (separators (python-rx
+ (or whitespace open-paren close-paren)))
+ (trigger "\t\t\t")
+ (new-input (concat input trigger))
+ (input-length
+ (save-excursion
+ (+ (- (point-max) (comint-bol)) (length new-input))))
+ (delete-line-command (make-string input-length ?\b))
+ (input-to-send (concat new-input delete-line-command)))
+ ;; Ensure restoring the process filter, even if the user quits
+ ;; or there's some other error.
+ (unwind-protect
+ (with-current-buffer redirect-buffer
+ ;; Cleanup the redirect buffer
+ (delete-region (point-min) (point-max))
+ ;; Mimic `comint-redirect-send-command', unfortunately it
+ ;; can't be used here because it expects a newline in the
+ ;; command and that's exactly what we are trying to avoid.
+ (let ((comint-redirect-echo-input nil)
+ (comint-redirect-verbose nil)
+ (comint-redirect-perform-sanity-check nil)
+ (comint-redirect-insert-matching-regexp nil)
+ ;; Feed it some regex that will never match.
+ (comint-redirect-finished-regexp "^\\'$")
+ (comint-redirect-output-buffer redirect-buffer))
+ ;; Compatibility with Emacs 24.x. Comint changed and
+ ;; now `comint-redirect-filter' gets 3 args. This
+ ;; checks which version of `comint-redirect-filter' is
+ ;; in use based on its args and uses `apply-partially'
+ ;; to make it up for the 3 args case.
+ (if (= (length
+ (help-function-arglist 'comint-redirect-filter)) 3)
+ (set-process-filter
+ process (apply-partially
+ #'comint-redirect-filter original-filter-fn))
+ (set-process-filter process #'comint-redirect-filter))
+ (process-send-string process input-to-send)
+ (accept-process-output
+ process
+ python-shell-completion-native-output-timeout)
+ ;; XXX: can't use `python-shell-accept-process-output'
+ ;; here because there are no guarantees on how output
+ ;; ends. The workaround here is to call
+ ;; `accept-process-output' until we don't find anything
+ ;; else to accept.
+ (while (accept-process-output
+ process
+ python-shell-completion-native-output-timeout))
+ (cl-remove-duplicates
+ (split-string
+ (buffer-substring-no-properties
+ (point-min) (point-max))
+ separators t))))
+ (set-process-filter process original-filter-fn))))))
(defun python-shell-completion-get-completions (process import input)
"Do completion at point using PROCESS for IMPORT or INPUT.
@@ -3251,20 +3254,23 @@ completion."
Optional argument PROCESS forces completions to be retrieved
using that one instead of current buffer's process."
(setq process (or process (get-buffer-process (current-buffer))))
- (let* ((last-prompt-end (cdr (python-util-comint-last-prompt)))
+ (let* ((line-start (if (derived-mode-p 'inferior-python-mode)
+ ;; Working on a shell buffer: use prompt end.
+ (cdr (python-util-comint-last-prompt))
+ (line-beginning-position)))
(import-statement
(when (string-match-p
(rx (* space) word-start (or "from" "import") word-end space)
- (buffer-substring-no-properties last-prompt-end (point)))
- (buffer-substring-no-properties last-prompt-end (point))))
+ (buffer-substring-no-properties line-start (point)))
+ (buffer-substring-no-properties line-start (point))))
(start
(save-excursion
(if (not (re-search-backward
(python-rx
(or whitespace open-paren close-paren string-delimiter))
- last-prompt-end
+ line-start
t 1))
- last-prompt-end
+ line-start
(forward-char (length (match-string-no-properties 0)))
(point))))
(end (point))
@@ -3847,8 +3853,10 @@ The skeleton will be bound to python-skeleton-NAME."
:type 'string
:group 'python)
-(defvar-local python-check-custom-command nil
+(defvar python-check-custom-command nil
"Internal use.")
+;; XXX: Avoid `defvar-local' for compat with Emacs<24.3
+(make-variable-buffer-local 'python-check-custom-command)
(defun python-check (command)
"Check a Python file (default current buffer's file).
@@ -3917,15 +3925,29 @@ See `python-check-command' for the default."
:type 'string
:group 'python)
+(defun python-eldoc--get-symbol-at-point ()
+ "Get the current symbol for eldoc.
+Returns the current symbol handling point within arguments."
+ (save-excursion
+ (let ((start (python-syntax-context 'paren)))
+ (when start
+ (goto-char start))
+ (when (or start
+ (eobp)
+ (memq (char-syntax (char-after)) '(?\ ?-)))
+ ;; Try to adjust to closest symbol if not in one.
+ (python-util-forward-comment -1)))
+ (python-info-current-symbol t)))
+
(defun python-eldoc--get-doc-at-point (&optional force-input force-process)
"Internal implementation to get documentation at point.
-If not FORCE-INPUT is passed then what `python-info-current-symbol'
+If not FORCE-INPUT is passed then what `python-eldoc--get-symbol-at-point'
returns will be used. If not FORCE-PROCESS is passed what
`python-shell-get-process' returns is used."
(let ((process (or force-process (python-shell-get-process))))
(when process
(let ((input (or force-input
- (python-info-current-symbol t))))
+ (python-eldoc--get-symbol-at-point))))
(and input
;; Prevent resizing the echo area when iPython is
;; enabled. Bug#18794.
@@ -3945,7 +3967,7 @@ inferior Python process is updated properly."
"Get help on SYMBOL using `help'.
Interactively, prompt for symbol."
(interactive
- (let ((symbol (python-info-current-symbol t))
+ (let ((symbol (python-eldoc--get-symbol-at-point))
(enable-recursive-minibuffers t))
(list (read-string (if symbol
(format "Describe symbol (default %s): " symbol)
@@ -3954,6 +3976,17 @@ Interactively, prompt for symbol."
(message (python-eldoc--get-doc-at-point symbol)))
+;;; Hideshow
+
+(defun python-hideshow-forward-sexp-function (arg)
+ "Python specific `forward-sexp' function for `hs-minor-mode'.
+Argument ARG is ignored."
+ arg ; Shut up, byte compiler.
+ (python-nav-end-of-defun)
+ (unless (python-info-current-line-empty-p)
+ (backward-char)))
+
+
;;; Imenu
(defvar python-imenu-format-item-label-function
@@ -4682,14 +4715,23 @@ Arguments START and END narrow the buffer region to work on."
(current-column))))
(^ '(- (1+ (current-indentation))))))
- (add-function :before-until (local 'eldoc-documentation-function)
- #'python-eldoc-function)
-
- (add-to-list 'hs-special-modes-alist
- `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#"
- ,(lambda (_arg)
- (python-nav-end-of-defun))
- nil))
+ (if (null eldoc-documentation-function)
+ ;; Emacs<25
+ (setq (make-local-variable 'eldoc-documentation-function)
+ #'python-eldoc-function)
+ (add-function :before-until (local 'eldoc-documentation-function)
+ #'python-eldoc-function))
+
+ (add-to-list
+ 'hs-special-modes-alist
+ `(python-mode
+ "\\s-*\\(?:def\\|class\\)\\>"
+ ;; Use the empty string as end regexp so it doesn't default to
+ ;; "\\s)". This way parens at end of defun are properly hidden.
+ ""
+ "#"
+ python-hideshow-forward-sexp-function
+ nil))
(set (make-local-variable 'outline-regexp)
(python-rx (* space) block-start))