X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/974b73e83842d63b14512aa225cc53983a9b5d14..8d9cc0b7ea1893059df8788129998e9a71ec07f3:/lisp/progmodes/python.el diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 24e9f65f18..462445f3d7 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -1,6 +1,6 @@ ;;; python.el --- silly walks for Python -;; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +;; Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. ;; Author: Dave Love ;; Maintainer: FSF @@ -11,7 +11,7 @@ ;; GNU Emacs is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) +;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; GNU Emacs is distributed in the hope that it will be useful, @@ -96,7 +96,7 @@ "import" "in" "is" "lambda" "not" "or" "pass" "print" "raise" "return" "try" "while" "yield" ;; Future keywords - "as" "None" + "as" "None" "with" ;; Not real keywords, but close enough to be fontified as such "self" "True" "False") symbol-end) @@ -163,7 +163,7 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)." (= (match-beginning 1) (match-end 1))) ; prefix is null (and (= n 1) ; prefix (/= (match-beginning 1) (match-end 1)))) ; non-empty - (unless (eq 'string (syntax-ppss-context (syntax-ppss))) + (unless (nth 3 (syntax-ppss)) (eval-when-compile (string-to-syntax "|")))) ;; Otherwise (we're in a non-matching string) the property is ;; nil, which is OK. @@ -348,7 +348,7 @@ comments and strings, or that point is within brackets/parens." (error nil)))))))) (defun python-comment-line-p () - "Return non-nil iff current line has only a comment." + "Return non-nil if current line has only a comment." (save-excursion (end-of-line) (when (eq 'comment (syntax-ppss-context (syntax-ppss))) @@ -356,7 +356,7 @@ comments and strings, or that point is within brackets/parens." (looking-at (rx (or (syntax comment-start) line-end)))))) (defun python-blank-line-p () - "Return non-nil iff current line is blank." + "Return non-nil if current line is blank." (save-excursion (beginning-of-line) (looking-at "\\s-*$"))) @@ -374,7 +374,7 @@ BOS non-nil means point is known to be at beginning of statement." (save-excursion (unless bos (python-beginning-of-statement)) (looking-at (rx (and (or "if" "else" "elif" "while" "for" "def" - "class" "try" "except" "finally") + "class" "try" "except" "finally" "with") symbol-end))))) (defun python-close-block-statement-p (&optional bos) @@ -408,6 +408,7 @@ The criteria are that the line isn't a comment or in string and See also `\\[python-guess-indent]'" :group 'python :type 'integer) +(put 'python-indent 'safe-local-variable 'integerp) (defcustom python-guess-indent t "Non-nil means Python mode guesses `python-indent' for the buffer." @@ -460,7 +461,7 @@ Set `python-indent' locally to the value guessed." (let ((initial (current-indentation))) (if (zerop (python-next-statement)) (setq indent (- (current-indentation) initial))) - (if (and (>= indent 2) (<= indent 8)) ; sanity check + (if (and indent (>= indent 2) (<= indent 8)) ; sanity check (setq done t)))))) (when done (when (/= indent (default-value 'python-indent)) @@ -849,7 +850,7 @@ multi-line bracketed expressions." "Skip out of any nested brackets. Skip forward if FORWARD is non-nil, else backward. If SYNTAX is non-nil it is the state returned by `syntax-ppss' at point. -Return non-nil iff skipping was done." +Return non-nil if skipping was done." (let ((depth (syntax-ppss-depth (or syntax (syntax-ppss)))) (forward (if forward -1 1))) (unless (zerop depth) @@ -882,10 +883,13 @@ On a comment line, go to end of line." nil) ((eq 'string (syntax-ppss-context s)) ;; Go to start of string and skip it. - (goto-char (nth 8 s)) - (condition-case () ; beware invalid syntax - (progn (forward-sexp) t) - (error (end-of-line)))) + (let ((pos (point))) + (goto-char (nth 8 s)) + (condition-case () ; beware invalid syntax + (progn (forward-sexp) t) + ;; If there's a mismatched string, make sure + ;; we still overall move *forward*. + (error (goto-char pos) (end-of-line))))) ((python-skip-out t s)))) (end-of-line)) (unless comment @@ -984,7 +988,7 @@ don't move and return nil. Otherwise return t." (if (and (zerop ci) (not open)) (not (goto-char point)) (catch 'done - (while (zerop (python-next-statement)) + (while (zerop (python-next-statement)) (when (or (and open (<= (current-indentation) ci)) (< (current-indentation) ci)) (python-skip-comments/blanks t) @@ -992,7 +996,16 @@ don't move and return nil. Otherwise return t." (throw 'done t))))))) (setq arg (1- arg))) (zerop arg))) - + +(defvar python-which-func-length-limit 40 + "Non-strict length limit for `python-which-func' output.") + +(defun python-which-func () + (let ((function-name (python-current-defun python-which-func-length-limit))) + (set-text-properties 0 (length function-name) nil function-name) + function-name)) + + ;;;; Imenu. (defvar python-recursing) @@ -1149,7 +1162,7 @@ modified by the user. Additional arguments are added when the command is used by `run-python' et al.") (defvar python-buffer nil - "*The current python process buffer. + "*The current Python process buffer. Commands that send text from source buffers to Python processes have to choose a process to send to. This is determined by buffer-local @@ -1186,7 +1199,7 @@ local value.") (define-key map "\C-c\C-l" 'python-load-file) (define-key map "\C-c\C-v" 'python-check) ;; Note that we _can_ still use these commands which send to the - ;; Python process even at the prompt iff we have a normal prompt, + ;; Python process even at the prompt provided we have a normal prompt, ;; i.e. '>>> ' and not '... '. See the comment before ;; python-send-region. Fixme: uncomment these if we address that. @@ -1346,7 +1359,7 @@ buffer for a list of commands.)" (path (getenv "PYTHONPATH")) (process-environment ; to import emacs.py (cons (concat "PYTHONPATH=" data-directory - (if path (concat ":" path))) + (if path (concat path-separator path))) process-environment))) (apply 'make-comint-in-buffer "Python" (if new (generate-new-buffer "*Python*") "*Python*") @@ -1382,11 +1395,11 @@ buffer for a list of commands.)" COMMAND should be a single statement." ;; (assert (not (string-match "\n" command))) ;; (let ((end (marker-position (process-mark (python-proc))))) - (with-current-buffer python-buffer (goto-char (point-max))) + (with-current-buffer (process-buffer (python-proc)) + (goto-char (point-max)) (compilation-forget-errors) (python-send-string command) - (with-current-buffer python-buffer - (setq compilation-last-buffer (current-buffer))) + (setq compilation-last-buffer (current-buffer))) ;; No idea what this is for but it breaks the call to ;; compilation-fake-loc in python-send-region. -- Stef ;; Must wait until this has completed before re-setting variables below. @@ -1516,9 +1529,9 @@ See variable `python-buffer'. Starts a new process if necessary." ;; isn't one for `python-buffer'. (unless (comint-check-proc python-buffer) (run-python nil t)) - (get-buffer-process (or (if (derived-mode-p 'inferior-python-mode) - (current-buffer) - python-buffer)))) + (get-buffer-process (if (derived-mode-p 'inferior-python-mode) + (current-buffer) + python-buffer))) (defun python-set-proc () "Set the default value of `python-buffer' to correspond to this buffer. @@ -1742,12 +1755,11 @@ Otherwise, do nothing." (orig (point)) (start (nth 8 syntax)) end) - (cond ((eq t (nth 3 syntax)) ; in fenced string - (goto-char (nth 8 syntax)) ; string start - (condition-case () ; for unbalanced quotes - (progn (forward-sexp) - (setq end (point))) - (error (setq end (point-max))))) + (cond ((eq t (nth 3 syntax)) ; in fenced string + (goto-char (nth 8 syntax)) ; string start + (setq end (condition-case () ; for unbalanced quotes + (progn (forward-sexp) (point)) + (error (point-max))))) ((re-search-backward "\\s|\\s-*\\=" nil t) ; end of fenced ; string (forward-char) @@ -1755,13 +1767,17 @@ Otherwise, do nothing." (condition-case () (progn (backward-sexp) (setq start (point))) - (error nil)))) + (error (setq end nil))))) (when end (save-restriction (narrow-to-region start end) (goto-char orig) - (fill-paragraph justify)))))) - t) + (let ((paragraph-separate + ;; Make sure that fenced-string delimiters that stand + ;; on their own line stay there. + (concat "[ \t]*['\"]+[ \t]*$\\|" paragraph-separate))) + (fill-paragraph justify)))))) + t)) (defun python-shift-left (start end &optional count) "Shift lines in region COUNT (the prefix arg) columns to the left. @@ -1807,22 +1823,34 @@ of current line." (1+ (/ (current-indentation) python-indent))) ;; Fixme: Consider top-level assignments, imports, &c. -(defun python-current-defun () +(defun python-current-defun (&optional length-limit) "`add-log-current-defun-function' for Python." (save-excursion ;; Move up the tree of nested `class' and `def' blocks until we ;; get to zero indentation, accumulating the defined names. - (let ((start t) - accum) - (while (or start (> (current-indentation) 0)) - (setq start nil) - (python-beginning-of-block) - (end-of-line) - (beginning-of-defun) - (if (looking-at (rx (0+ space) (or "def" "class") (1+ space) - (group (1+ (or word (syntax symbol)))))) - (push (match-string 1) accum))) - (if accum (mapconcat 'identity accum "."))))) + (let ((accum) + (length -1)) + (catch 'done + (while (or (null length-limit) + (null (cdr accum)) + (< length length-limit)) + (setq start nil) + (let ((started-from (point))) + (python-beginning-of-block) + (end-of-line) + (beginning-of-defun) + (when (= (point) started-from) + (throw 'done nil))) + (when (looking-at (rx (0+ space) (or "def" "class") (1+ space) + (group (1+ (or word (syntax symbol)))))) + (push (match-string 1) accum) + (setq length (+ length 1 (length (car accum))))) + (when (= (current-indentation) 0) + (throw 'done nil)))) + (when accum + (when (and length-limit (> length length-limit)) + (setcar accum "..")) + (mapconcat 'identity accum "."))))) (defun python-mark-block () "Mark the block around point. @@ -1918,7 +1946,7 @@ Repeating the command scrolls the completion window." (interactive) (let ((window (get-buffer-window "*Completions*"))) (if (and (eq last-command this-command) - window (window-live-p window) (window-buffer window) + (window-live-p window) (window-buffer window) (buffer-name (window-buffer window))) (with-current-buffer (window-buffer window) (if (pos-visible-in-window-p (point-max) window) @@ -2084,7 +2112,7 @@ The default contents correspond to the elements of `python-skeletons'.") > _ \n) (defvar python-default-template "if" - "Default template to expand by `python-insert-template'. + "Default template to expand by `python-expand-template'. Updated on each expansion.") (defun python-expand-template (name) @@ -2221,6 +2249,7 @@ with skeleton expansions for compound statement templates. ;; . python-font-lock-syntactic-face-function) )) (set (make-local-variable 'parse-sexp-lookup-properties) t) + (set (make-local-variable 'parse-sexp-ignore-comments) t) (set (make-local-variable 'comment-start) "# ") (set (make-local-variable 'indent-line-function) #'python-indent-line) (set (make-local-variable 'indent-region-function) #'python-indent-region) @@ -2231,7 +2260,7 @@ with skeleton expansions for compound statement templates. #'python-current-defun) (set (make-local-variable 'outline-regexp) (rx (* space) (or "class" "def" "elif" "else" "except" "finally" - "for" "if" "try" "while") + "for" "if" "try" "while" "with") symbol-end)) (set (make-local-variable 'outline-heading-end-regexp) ":\\s-*\n") (set (make-local-variable 'outline-level) #'python-outline-level) @@ -2240,6 +2269,7 @@ with skeleton expansions for compound statement templates. (set (make-local-variable 'beginning-of-defun-function) 'python-beginning-of-defun) (set (make-local-variable 'end-of-defun-function) 'python-end-of-defun) + (add-hook 'which-func-functions 'python-which-func nil t) (setq imenu-create-index-function #'python-imenu-create-index) (set (make-local-variable 'eldoc-documentation-function) #'python-eldoc-function)