;;; python.el --- silly walks for Python -*- coding: iso-8859-1 -*-
-;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-;; Free Software Foundation, Inc.
+;; Copyright (C) 2003-2011 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Maintainer: FSF
"import" "in" "is" "lambda" "not" "or" "pass" "print"
"raise" "return" "try" "while" "with" "yield"
;; Not real keywords, but close enough to be fontified as such
- "self" "True" "False")
+ "self" "True" "False"
+ ;; Python 3
+ "nonlocal")
symbol-end)
(,(rx symbol-start "None" symbol-end) ; see § Keywords in 2.7 manual
. font-lock-constant-face)
(,(rx symbol-start (group "def") (1+ space) (group (1+ (or word ?_))))
(1 font-lock-keyword-face) (2 font-lock-function-name-face))
;; Top-level assignments are worth highlighting.
- (,(rx line-start (group (1+ (or word ?_))) (0+ space) "=")
+ (,(rx line-start (group (1+ (or word ?_))) (0+ space)
+ (opt (or "+" "-" "*" "**" "/" "//" "&" "%" "|" "^" "<<" ">>")) "=")
(1 font-lock-variable-name-face))
;; Decorators.
(,(rx line-start (* (any " \t")) (group "@" (1+ (or word ?_))
symbol-end)
. font-lock-builtin-face)))
-(defconst python-font-lock-syntactic-keywords
+(defconst python-syntax-propertize-function
;; Make outer chars of matching triple-quote sequences into generic
;; string delimiters. Fixme: Is there a better way?
;; First avoid a sequence preceded by an odd number of backslashes.
- `((,(concat "\\(?:\\([RUru]\\)[Rr]?\\|^\\|[^\\]\\(?:\\\\.\\)*\\)" ;Prefix.
+ (syntax-propertize-rules
+ (;; ¡Backrefs don't work in syntax-propertize-rules!
+ (concat "\\(?:\\([RUru]\\)[Rr]?\\|^\\|[^\\]\\(?:\\\\.\\)*\\)" ;Prefix.
"\\(?:\\('\\)'\\('\\)\\|\\(?2:\"\\)\"\\(?3:\"\\)\\)")
- (1 (python-quote-syntax 1) nil lax)
- (2 (python-quote-syntax 2))
- (3 (python-quote-syntax 3)))
- ;; This doesn't really help.
-;;; (,(rx (and ?\\ (group ?\n))) (1 " "))
- ))
-
-(defun python-quote-syntax (n)
+ (3 (ignore (python-quote-syntax))))
+ ;; This doesn't really help.
+ ;;((rx (and ?\\ (group ?\n))) (1 " "))
+ ))
+
+(defun python-quote-syntax ()
"Put `syntax-table' property correctly on triple quote.
Used for syntactic keywords. N is the match number (1, 2 or 3)."
;; Given a triple quote, we have to check the context to know
;; x '"""' x """ \"""" x
(save-excursion
(goto-char (match-beginning 0))
- (cond
- ;; Consider property for the last char if in a fenced string.
- ((= n 3)
- (let* ((font-lock-syntactic-keywords nil)
- (syntax (syntax-ppss)))
- (when (eq t (nth 3 syntax)) ; after unclosed fence
- (goto-char (nth 8 syntax)) ; fence position
- (skip-chars-forward "uUrR") ; skip any prefix
- ;; Is it a matching sequence?
- (if (eq (char-after) (char-after (match-beginning 2)))
- (eval-when-compile (string-to-syntax "|"))))))
- ;; Consider property for initial char, accounting for prefixes.
- ((or (and (= n 2) ; leading quote (not prefix)
- (not (match-end 1))) ; prefix is null
- (and (= n 1) ; prefix
- (match-end 1))) ; non-empty
- (let ((font-lock-syntactic-keywords nil))
- (unless (eq 'string (syntax-ppss-context (syntax-ppss)))
- (eval-when-compile (string-to-syntax "|")))))
- ;; Otherwise (we're in a non-matching string) the property is
- ;; nil, which is OK.
- )))
+ (let ((syntax (save-match-data (syntax-ppss))))
+ (cond
+ ((eq t (nth 3 syntax)) ; after unclosed fence
+ ;; Consider property for the last char if in a fenced string.
+ (goto-char (nth 8 syntax)) ; fence position
+ (skip-chars-forward "uUrR") ; skip any prefix
+ ;; Is it a matching sequence?
+ (if (eq (char-after) (char-after (match-beginning 2)))
+ (put-text-property (match-beginning 3) (match-end 3)
+ 'syntax-table (string-to-syntax "|"))))
+ ((match-end 1)
+ ;; Consider property for initial char, accounting for prefixes.
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'syntax-table (string-to-syntax "|")))
+ (t
+ ;; Consider property for initial char, accounting for prefixes.
+ (put-text-property (match-beginning 2) (match-end 2)
+ 'syntax-table (string-to-syntax "|"))))
+ )))
;; This isn't currently in `font-lock-defaults' as probably not worth
;; it -- we basically only mess with a few normally-symbol characters.
:type 'integer)
-(defcustom python-default-interpreter 'cpython
- "*Which Python interpreter is used by default.
-The value for this variable can be either `cpython' or `jpython'.
-
-When the value is `cpython', the variables `python-python-command' and
-`python-python-command-args' are consulted to determine the interpreter
-and arguments to use.
-
-When the value is `jpython', the variables `python-jpython-command' and
-`python-jpython-command-args' are consulted to determine the interpreter
-and arguments to use.
-
-Note that this variable is consulted only the first time that a Python
-mode buffer is visited during an Emacs session. After that, use
-\\[python-toggle-shells] to change the interpreter shell."
- :type '(choice (const :tag "Python (a.k.a. CPython)" cpython)
- (const :tag "JPython" jpython))
- :group 'python)
-
-(defcustom python-python-command-args '("-i")
- "*List of string arguments to be used when starting a Python shell."
- :type '(repeat string)
- :group 'python)
-
-(defcustom python-jython-command-args '("-i")
- "*List of string arguments to be used when starting a Jython shell."
- :type '(repeat string)
- :group 'python
- :tag "JPython Command Args")
-
-;; for toggling between CPython and JPython
-(defvar python-which-shell nil)
-(defvar python-which-args python-python-command-args)
-(defvar python-which-bufname "Python")
-(make-variable-buffer-local 'python-which-shell)
-(make-variable-buffer-local 'python-which-args)
-(make-variable-buffer-local 'python-which-bufname)
-
(defcustom python-pdbtrack-do-tracking-p t
"*Controls whether the pdbtrack feature is enabled or not.
(push '(python-pdbtrack-is-tracking-p python-pdbtrack-minor-mode-string)
minor-mode-alist))
-;; Bind python-file-queue before installing the kill-emacs-hook.
-(defvar python-file-queue nil
- "Queue of Python temp files awaiting execution.
-Currently-active file is at the head of the list.")
-
(defcustom python-shell-prompt-alist
'(("ipython" . "^In \\[[0-9]+\\]: *")
(t . "^>>> "))
(let ((name (buffer-file-name)))
(if name
(file-name-nondirectory name))))))))
- (setq python-saved-check-command command)
+ (set (make-local-variable 'python-saved-check-command) command)
(require 'compile) ;To define compilation-* variables.
(save-some-buffers (not compilation-ask-about-save) nil)
(let ((compilation-error-regexp-alist
(eval-when-compile
;; Define a user-level skeleton and add it to the abbrev table.
(defmacro def-python-skeleton (name &rest elements)
+ (declare (indent 2))
(let* ((name (symbol-name name))
(function (intern (concat "python-insert-" name))))
`(progn
(define-skeleton ,function
,(format "Insert Python \"%s\" template." name)
,@elements)))))
-(put 'def-python-skeleton 'lisp-indent-function 2)
;; From `skeleton-further-elements' set below:
;; `<': outdent a level;
:group 'python
(set (make-local-variable 'font-lock-defaults)
'(python-font-lock-keywords nil nil nil nil
- (font-lock-syntactic-keywords
- . python-font-lock-syntactic-keywords)
- ;; This probably isn't worth it.
- ;; (font-lock-syntactic-face-function
- ;; . python-font-lock-syntactic-face-function)
- ))
+ ;; This probably isn't worth it.
+ ;; (font-lock-syntactic-face-function
+ ;; . python-font-lock-syntactic-face-function)
+ ))
+ (set (make-local-variable 'syntax-propertize-function)
+ python-syntax-propertize-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 'outline-heading-end-regexp) ":\\s-*\n")
(set (make-local-variable 'outline-level) #'python-outline-level)
(set (make-local-variable 'open-paren-in-column-0-is-defun-start) nil)
- (make-local-variable 'python-saved-check-command)
(set (make-local-variable 'beginning-of-defun-function)
'python-beginning-of-defun)
(set (make-local-variable 'end-of-defun-function) 'python-end-of-defun)
;; doesn't seem to work properly.
(add-to-list 'hs-special-modes-alist
`(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#"
- ,(lambda (arg)
+ ,(lambda (_arg)
(python-end-of-defun)
(skip-chars-backward " \t\n"))
nil))
(^ '(- (1+ (current-indentation))))))
;; Python defines TABs as being 8-char wide.
(set (make-local-variable 'tab-width) 8)
- (unless font-lock-mode (font-lock-mode 1))
(when python-guess-indent (python-guess-indent))
;; Let's make it harder for the user to shoot himself in the foot.
(unless (= tab-width python-indent)
;; pdbtrack features
-(defun python-comint-output-filter-function (string)
- "Watch output for Python prompt and exec next file waiting in queue.
-This function is appropriate for `comint-output-filter-functions'."
- ;; TBD: this should probably use split-string
- (when (and (string-match python--prompt-regexp string)
- python-file-queue)
- (condition-case nil
- (delete-file (car python-file-queue))
- (error nil))
- (setq python-file-queue (cdr python-file-queue))
- (if python-file-queue
- (let ((pyproc (get-buffer-process (current-buffer))))
- (python-execute-file pyproc (car python-file-queue))))))
-
(defun python-pdbtrack-overlay-arrow (activation)
"Activate or deactivate arrow at beginning-of-line in current buffer."
(if activation
overlay-arrow-string "=>"
python-pdbtrack-is-tracking-p t)
(set-marker overlay-arrow-position
- (save-excursion (beginning-of-line) (point))
+ (line-beginning-position)
(current-buffer)))
(setq overlay-arrow-position nil
python-pdbtrack-is-tracking-p nil)))
-(defun python-pdbtrack-track-stack-file (text)
+(defun python-pdbtrack-track-stack-file (_text)
"Show the file indicated by the pdb stack entry line, in a separate window.
Activity is disabled if the buffer-local variable
)
)
-(defun python-pdbtrack-grub-for-buffer (funcname lineno)
- "Find recent python-mode buffer named, or having function named funcname."
+(defun python-pdbtrack-grub-for-buffer (funcname _lineno)
+ "Find recent Python mode buffer named, or having function named FUNCNAME."
(let ((buffers (buffer-list))
buf
got)
(setq got buf)))
got))
-(defun python-toggle-shells (arg)
- "Toggles between the CPython and JPython shells.
-
-With positive argument ARG (interactively \\[universal-argument]),
-uses the CPython shell, with negative ARG uses the JPython shell, and
-with a zero argument, toggles the shell.
-
-Programmatically, ARG can also be one of the symbols `cpython' or
-`jpython', equivalent to positive arg and negative arg respectively."
- (interactive "P")
- ;; default is to toggle
- (if (null arg)
- (setq arg 0))
- ;; preprocess arg
- (cond
- ((equal arg 0)
- ;; toggle
- (if (string-equal python-which-bufname "Python")
- (setq arg -1)
- (setq arg 1)))
- ((equal arg 'cpython) (setq arg 1))
- ((equal arg 'jpython) (setq arg -1)))
- (let (msg)
- (cond
- ((< 0 arg)
- ;; set to CPython
- (setq python-which-shell python-python-command
- python-which-args python-python-command-args
- python-which-bufname "Python"
- msg "CPython"
- mode-name "Python"))
- ((> 0 arg)
- (setq python-which-shell python-jython-command
- python-which-args python-jython-command-args
- python-which-bufname "JPython"
- msg "JPython"
- mode-name "JPython")))
- (message "Using the %s shell" msg)))
-
;; Python subprocess utilities and filters
(defun python-execute-file (proc filename)
"Send to Python interpreter process PROC \"execfile('FILENAME')\".
(set-buffer curbuf))
(process-send-string proc cmd)))
-;;;###autoload
-(defun python-shell (&optional argprompt)
- "Start an interactive Python interpreter in another window.
-This is like Shell mode, except that Python is running in the window
-instead of a shell. See the `Interactive Shell' and `Shell Mode'
-sections of the Emacs manual for details, especially for the key
-bindings active in the `*Python*' buffer.
-
-With optional \\[universal-argument], the user is prompted for the
-flags to pass to the Python interpreter. This has no effect when this
-command is used to switch to an existing process, only when a new
-process is started. If you use this, you will probably want to ensure
-that the current arguments are retained (they will be included in the
-prompt). This argument is ignored when this function is called
-programmatically.
-
-Note: You can toggle between using the CPython interpreter and the
-JPython interpreter by hitting \\[python-toggle-shells]. This toggles
-buffer local variables which control whether all your subshell
-interactions happen to the `*JPython*' or `*Python*' buffers (the
-latter is the name used for the CPython buffer).
-
-Warning: Don't use an interactive Python if you change sys.ps1 or
-sys.ps2 from their default values, or if you're running code that
-prints `>>> ' or `... ' at the start of a line. `python-mode' can't
-distinguish your output from Python's output, and assumes that `>>> '
-at the start of a line is a prompt from Python. Similarly, the Emacs
-Shell mode code assumes that both `>>> ' and `... ' at the start of a
-line are Python prompts. Bad things can happen if you fool either
-mode.
-
-Warning: If you do any editing *in* the process buffer *while* the
-buffer is accepting output from Python, do NOT attempt to `undo' the
-changes. Some of the output (nowhere near the parts you changed!) may
-be lost if you do. This appears to be an Emacs bug, an unfortunate
-interaction between undo and process filters; the same problem exists in
-non-Python process buffers using the default (Emacs-supplied) process
-filter."
- (interactive "P")
- (require 'ansi-color) ; For ipython
- ;; Set the default shell if not already set
- (when (null python-which-shell)
- (python-toggle-shells python-default-interpreter))
- (let ((args python-which-args))
- (when (and argprompt
- (called-interactively-p 'interactive)
- (fboundp 'split-string))
- ;; TBD: Perhaps force "-i" in the final list?
- (setq args (split-string
- (read-string (concat python-which-bufname
- " arguments: ")
- (concat
- (mapconcat 'identity python-which-args " ") " ")
- ))))
- (switch-to-buffer-other-window
- (apply 'make-comint python-which-bufname python-which-shell nil args))
- (set-process-sentinel (get-buffer-process (current-buffer))
- 'python-sentinel)
- (python--set-prompt-regexp)
- (add-hook 'comint-output-filter-functions
- 'python-comint-output-filter-function nil t)
- ;; pdbtrack
- (set-syntax-table python-mode-syntax-table)
- (use-local-map python-shell-map)))
-
(defun python-pdbtrack-toggle-stack-tracking (arg)
(interactive "P")
(if (not (get-buffer-process (current-buffer)))
(interactive)
(python-pdbtrack-toggle-stack-tracking 0))
-(defun python-sentinel (proc msg)
+(defun python-sentinel (_proc _msg)
(setq overlay-arrow-position nil))
(provide 'python)