From 63dae8e97d343fd4ebfe3dc08f0e8dc932630a4c Mon Sep 17 00:00:00 2001 From: Joakim Verona Date: Tue, 10 Sep 2013 23:52:26 +0200 Subject: merge upstream --- lisp/progmodes/python.el | 141 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 99 insertions(+), 42 deletions(-) (limited to 'lisp/progmodes/python.el') diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 7004836e69f..5eecc347f03 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -52,12 +52,12 @@ ;; Extra functions `python-nav-forward-statement', ;; `python-nav-backward-statement', ;; `python-nav-beginning-of-statement', `python-nav-end-of-statement', -;; `python-nav-beginning-of-block' and `python-nav-end-of-block' are -;; included but no bound to any key. At last but not least the -;; specialized `python-nav-forward-sexp' allows easy navigation -;; between code blocks. If you prefer `cc-mode'-like `forward-sexp' -;; movement, setting `forward-sexp-function' to nil is enough, You can -;; do that using the `python-mode-hook': +;; `python-nav-beginning-of-block', `python-nav-end-of-block' and +;; `python-nav-if-name-main' are included but no bound to any key. At +;; last but not least the specialized `python-nav-forward-sexp' allows +;; easy navigation between code blocks. If you prefer `cc-mode'-like +;; `forward-sexp' movement, setting `forward-sexp-function' to nil is +;; enough, You can do that using the `python-mode-hook': ;; (add-hook 'python-mode-hook ;; (lambda () (setq forward-sexp-function nil))) @@ -225,7 +225,7 @@ ;;;###autoload (add-to-list 'auto-mode-alist (cons (purecopy "\\.py\\'") 'python-mode)) ;;;###autoload -(add-to-list 'interpreter-mode-alist (cons (purecopy "python") 'python-mode)) +(add-to-list 'interpreter-mode-alist (cons (purecopy "\\`python[0-9.]*\\'") 'python-mode)) (defgroup python nil "Python Language's flying circus support for Emacs." @@ -1327,9 +1327,7 @@ backward to previous statement." (defun python-nav-beginning-of-block () "Move to start of current block." (interactive "^") - (let ((starting-pos (point)) - (block-regexp (python-rx - line-start (* whitespace) block-start))) + (let ((starting-pos (point))) (if (progn (python-nav-beginning-of-statement) (looking-at (python-rx block-start))) @@ -1422,9 +1420,6 @@ backwards." (let* ((forward-p (if (> dir 0) (and (setq dir 1) t) (and (setq dir -1) nil))) - (re-search-fn (if forward-p - 're-search-forward - 're-search-backward)) (context-type (python-syntax-context-type))) (cond ((memq context-type '(string comment)) @@ -1583,6 +1578,29 @@ This command assumes point is not in a string or comment." (or arg (setq arg 1)) (python-nav-up-list (- arg))) +(defun python-nav-if-name-main () + "Move point at the beginning the __main__ block. +When \"if __name__ == '__main__':\" is found returns its +position, else returns nil." + (interactive) + (let ((point (point)) + (found (catch 'found + (goto-char (point-min)) + (while (re-search-forward + (python-rx line-start + "if" (+ space) + "__name__" (+ space) + "==" (+ space) + (group-n 1 (or ?\" ?\')) + "__main__" (backref 1) (* space) ":") + nil t) + (when (not (python-syntax-context-type)) + (beginning-of-line) + (throw 'found t)))))) + (if found + (point) + (ignore (goto-char point))))) + ;;; Shell integration @@ -2114,17 +2132,58 @@ Returns the output. See `python-shell-send-string-no-output'." (define-obsolete-function-alias 'python-send-string 'python-shell-internal-send-string "24.3") +(defun python-shell-buffer-substring (start end &optional nomain) + "Send buffer substring from START to END formatted for shell. +This is a wrapper over `buffer-substring' that takes care of +different transformations for the code sent to be evaluated in +the python shell: + 1. When Optional Argument NOMAIN is non-nil everything under an + \"if __name__ == '__main__'\" block will be removed. + 2. When a subregion of the buffer is sent, it takes care of + appending extra empty lines so tracebacks are correct. + 3. Wraps indented regions under an \"if True:\" block so the + interpreter evaluates them correctly." + (let ((substring (buffer-substring-no-properties start end)) + (fillstr (make-string (1- (line-number-at-pos start)) ?\n)) + (toplevel-block-p (save-excursion + (goto-char start) + (or (zerop (line-number-at-pos start)) + (progn + (python-util-forward-comment 1) + (zerop (current-indentation))))))) + (with-temp-buffer + (python-mode) + (insert fillstr) + (insert substring) + (goto-char (point-min)) + (when (not toplevel-block-p) + (insert "if True:") + (delete-region (point) (line-end-position))) + (when nomain + (let* ((if-name-main-start-end + (and nomain + (save-excursion + (when (python-nav-if-name-main) + (cons (point) + (progn (python-nav-forward-sexp) + (point))))))) + ;; Oh destructuring bind, how I miss you. + (if-name-main-start (car if-name-main-start-end)) + (if-name-main-end (cdr if-name-main-start-end))) + (when if-name-main-start-end + (goto-char if-name-main-start) + (delete-region if-name-main-start if-name-main-end) + (insert + (make-string + (- (line-number-at-pos if-name-main-end) + (line-number-at-pos if-name-main-start)) ?\n))))) + (buffer-substring-no-properties (point-min) (point-max))))) + (defun python-shell-send-region (start end) "Send the region delimited by START and END to inferior Python process." (interactive "r") (python-shell-send-string - (concat - (let ((line-num (line-number-at-pos start))) - ;; When sending a region, add blank lines for non sent code so - ;; backtraces remain correct. - (make-string (1- line-num) ?\n)) - (buffer-substring start end)) - nil t)) + (python-shell-buffer-substring start end) nil t)) (defun python-shell-send-buffer (&optional arg) "Send the entire buffer to inferior Python process. @@ -2133,13 +2192,9 @@ by \"if __name__== '__main__':\"" (interactive "P") (save-restriction (widen) - (let ((str (buffer-substring (point-min) (point-max)))) - (and - (not arg) - (setq str (replace-regexp-in-string - (python-rx if-name-main) - "if __name__ == '__main__ ':" str))) - (python-shell-send-string str)))) + (python-shell-send-string + (python-shell-buffer-substring + (point-min) (point-max) (not arg))))) (defun python-shell-send-defun (arg) "Send the current defun to inferior Python process. @@ -2266,13 +2321,17 @@ and use the following as the value of this variable: LINE is used to detect the context on how to complete given INPUT." (let* ((prompt - ;; Get the last prompt for the inferior process - ;; buffer. This is used for the completion code selection - ;; heuristic. + ;; Get last prompt of the inferior process buffer (this + ;; intentionally avoids using `comint-last-prompt' because + ;; of incompatibilities with Emacs 24.x). (with-current-buffer (process-buffer process) - (buffer-substring-no-properties - (overlay-start comint-last-prompt-overlay) - (overlay-end comint-last-prompt-overlay)))) + (save-excursion + (buffer-substring-no-properties + (- (point) (length line)) + (progn + (re-search-backward "^") + (python-util-forward-comment) + (point)))))) (completion-context ;; Check whether a prompt matches a pdb string, an import ;; statement or just the standard prompt and use the @@ -2602,8 +2661,7 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'." (defun python-fill-string (&optional justify) "String fill function for `python-fill-paragraph'. JUSTIFY should be used (if applicable) as in `fill-paragraph'." - (let* ((marker (point-marker)) - (str-start-pos + (let* ((str-start-pos (set-marker (make-marker) (or (python-syntax-context 'string) @@ -2669,7 +2727,7 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'." ;; Again indent only if a newline is added. (indent-according-to-mode))))) t) -(defun python-fill-decorator (&optional justify) +(defun python-fill-decorator (&optional _justify) "Decorator fill function for `python-fill-paragraph'. JUSTIFY should be used (if applicable) as in `fill-paragraph'." t) @@ -2831,8 +2889,7 @@ The skeleton will be bound to python-skeleton-NAME." (defun python-skeleton-add-menu-items () "Add menu items to Python->Skeletons menu." - (let ((skeletons (sort python-skeleton-available 'string<)) - (items)) + (let ((skeletons (sort python-skeleton-available 'string<))) (dolist (skeleton skeletons) (easy-menu-add-item nil '("Python" "Skeletons") @@ -2920,7 +2977,7 @@ Runs COMMAND, a shell command, as if by `compile'. See (let ((process-environment (python-shell-calculate-process-environment)) (exec-path (python-shell-calculate-exec-path))) (compilation-start command nil - (lambda (mode-name) + (lambda (_modename) (format python-check-buffer-name command))))) @@ -3031,7 +3088,7 @@ It must be a function with two arguments: TYPE and NAME.") "Return imenu label for parent node using TYPE and NAME." (format "%s..." (python-imenu-format-item-label type name))) -(defun python-imenu-format-parent-item-jump-label (type name) +(defun python-imenu-format-parent-item-jump-label (type _name) "Return imenu label for parent node jump using TYPE and NAME." (if (string= type "class") "*class definition*" @@ -3145,7 +3202,7 @@ To this: (cons name (cdar pos)) (python-imenu-create-flat-index (cddr item) name)))))) (or alist - (let* ((fn (lambda (type name) name)) + (let* ((fn (lambda (_type name) name)) (python-imenu-format-item-label-function fn) (python-imenu-format-parent-item-label-function fn) (python-imenu-format-parent-item-jump-label-function fn)) @@ -3550,7 +3607,7 @@ if that value is non-nil." (add-to-list 'hs-special-modes-alist `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#" - ,(lambda (arg) + ,(lambda (_arg) (python-nav-end-of-defun)) nil)) (set (make-local-variable 'mode-require-final-newline) t) -- cgit v1.2.1