;;; python.el -- Python's flying circus support for Emacs
-;; Copyright (C) 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2010, 2011 Free Software Foundation, Inc.
;; Author: Fabián E. Gallina <fabian@anue.biz>
;; Maintainer: FSF
;; Implements Syntax highlighting, Indentation, Movement, Shell
;; interaction, Shell completion, Pdb tracking, Symbol completion,
-;; Eldoc.
+;; Skeletons, FFAP, Code Check, Eldoc.
;; Syntax highlighting: Fontification of code is provided and supports
;; python's triple quoted strings properly.
"=" "%" "**" "//" "<<" ">>" "<=" "!="
"==" ">=" "is" "not")))
`(assignment-operator . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**="
- ">>=" "<<=" "&=" "^=" "|="))))))
+ ">>=" "<<=" "&=" "^=" "|="))))
+ "Additional Python specific sexps for `python-rx'"))
(defmacro python-rx (&rest regexps)
"Python mode especialized rx macro which supports common python named REGEXPS."
(when (> indent-offset 0)
(setq python-indent-offset indent-offset))))))))
-(defun python-indent-context (&optional stop)
- "Return information on indentation context.
-Optional argument STOP serves to stop recursive calls.
-
-Returns a cons with the form:
-
-\(STATUS . START)
+(defun python-indent-context ()
+ "Get information on indentation context.
+Context information is returned with a cons with the form:
+ \(STATUS . START)
Where status can be any of the following symbols:
-
* inside-paren: If point in between (), {} or []
* inside-string: If point is inside a string
* after-backslash: Previous line ends in a backslash
* after-beginning-of-block: Point is after beginning of block
* after-line: Point is after normal line
* no-indent: Point is at beginning of buffer or other special case
-
START is the buffer position where the sexp starts."
(save-restriction
(widen)
(defun python-indent-line (&optional force-toggle)
"Internal implementation of `python-indent-line-function'.
-
Uses the offset calculated in
`python-indent-calculate-indentation' and available levels
-indicated by the variable `python-indent-levels'.
+indicated by the variable `python-indent-levels' to set the
+current indentation.
When the variable `last-command' is equal to
-`indent-for-tab-command' or FORCE-TOGGLE is non-nil:
-
-* Cycles levels indicated in the variable `python-indent-levels'
- by setting the current level in the variable
- `python-indent-current-level'.
+`indent-for-tab-command' or FORCE-TOGGLE is non-nil it cycles
+levels indicated in the variable `python-indent-levels' by
+setting the current level in the variable
+`python-indent-current-level'.
When the variable `last-command' is not equal to
-`indent-for-tab-command' and FORCE-TOGGLE is nil:
-
-* calculates possible indentation levels and saves it in the
- variable `python-indent-levels'.
-
-* sets the variable `python-indent-current-level' correctly so
- offset is equal to (`nth' `python-indent-current-level'
- `python-indent-levels')"
+`indent-for-tab-command' and FORCE-TOGGLE is nil it calculates
+possible indentation levels and saves it in the variable
+`python-indent-levels'. Afterwards it sets the variable
+`python-indent-current-level' correctly so offset is equal
+to (`nth' `python-indent-current-level' `python-indent-levels')"
(if (or (and (eq this-command 'indent-for-tab-command)
(eq last-command this-command))
force-toggle)
(defun python-indent-line-function ()
"`indent-line-function' for Python mode.
-Internally just calls `python-indent-line'."
+See `python-indent-line' for details."
(python-indent-line))
(defun python-indent-dedent-line ()
- "Dedent current line."
+ "De-indent current line."
(interactive "*")
(when (and (not (or (python-info-ppss-context 'string)
(python-info-ppss-context 'comment)))
t))
(defun python-indent-dedent-line-backspace (arg)
- "Dedent current line.
+ "De-indent current line.
Argument ARG is passed to `backward-delete-char-untabify' when
-point is not in between the indentation."
+point is not in between the indentation."
(interactive "*p")
(when (not (python-indent-dedent-line))
(backward-delete-char-untabify arg)))
(defun python-indent-shift-left (start end &optional count)
"Shift lines contained in region START END by COUNT columns to the left.
-
-COUNT defaults to `python-indent-offset'.
-
-If region isn't active, the current line is shifted.
-
-The shifted region includes the lines in which START and END lie.
-
-An error is signaled if any lines in the region are indented less
-than COUNT columns."
+COUNT defaults to `python-indent-offset'. If region isn't
+active, the current line is shifted. The shifted region includes
+the lines in which START and END lie. An error is signaled if
+any lines in the region are indented less than COUNT columns."
(interactive
(if mark-active
(list (region-beginning) (region-end) current-prefix-arg)
(defun python-indent-shift-right (start end &optional count)
"Shift lines contained in region START END by COUNT columns to the left.
-
-COUNT defaults to `python-indent-offset'.
-
-If region isn't active, the current line is shifted.
-
-The shifted region includes the lines in which START and END
-lie."
+COUNT defaults to `python-indent-offset'. If region isn't
+active, the current line is shifted. The shifted region includes
+the lines in which START and END lie."
(interactive
(if mark-active
(list (region-beginning) (region-end) current-prefix-arg)
(indent-rigidly start end count)))
(defun python-indent-electric-colon (arg)
- "Insert a colon and maybe outdent the line if it is a statement like `else'.
-With numeric ARG, just insert that many colons. With \\[universal-argument],
-just insert a single colon."
+ "Insert a colon and maybe de-indent the current line.
+With numeric ARG, just insert that many colons. With
+\\[universal-argument], just insert a single colon."
(interactive "*P")
(self-insert-command (if (not (integerp arg)) 1 arg))
(when (and (not arg)
:safe 'stringp)
(defcustom python-shell-prompt-regexp ">>> "
- "Regex matching top\-level input prompt of python shell.
-The regex should not contain a caret (^) at the beginning."
+ "Regular Expression matching top\-level input prompt of python shell.
+It should not contain a caret (^) at the beginning."
:type 'string
:group 'python
:safe 'stringp)
(defcustom python-shell-prompt-block-regexp "[.][.][.] "
- "Regex matching block input prompt of python shell.
-The regex should not contain a caret (^) at the beginning."
+ "Regular Expression matching block input prompt of python shell.
+It should not contain a caret (^) at the beginning."
:type 'string
:group 'python
:safe 'stringp)
(defcustom python-shell-prompt-output-regexp nil
- "Regex matching output prompt of python shell.
-The regex should not contain a caret (^) at the beginning."
+ "Regular Expression matching output prompt of python shell.
+It should not contain a caret (^) at the beginning."
:type 'string
:group 'python
:safe 'stringp)
(defcustom python-shell-prompt-pdb-regexp "[(<]*[Ii]?[Pp]db[>)]+ "
- "Regex matching pdb input prompt of python shell.
-The regex should not contain a caret (^) at the beginning."
+ "Regular Expression matching pdb input prompt of python shell.
+It should not contain a caret (^) at the beginning."
:type 'string
:group 'python
:safe 'stringp)
python-ffap-setup-code
python-eldoc-setup-code)
"List of code run by `python-shell-send-setup-codes'.
-Each variable can be either a simple string with the code to
+Each variable can contain either a simple string with the code to
execute or a cons with the form (CODE . DESCRIPTION), where CODE
is a string with the code to execute and DESCRIPTION is the
description of it."
(defun python-shell-get-process-name (dedicated)
"Calculate the appropiate process name for inferior Python process.
-
If DEDICATED is t and the variable `buffer-file-name' is non-nil
returns a string with the form
`python-shell-buffer-name'[variable `buffer-file-name'] else
-returns the value of `python-shell-buffer-name'.
-
-After calculating the process name add the buffer name for the
-process in the `same-window-buffer-names' list"
+returns the value of `python-shell-buffer-name'. After
+calculating the process name adds the buffer name for the process
+in the `same-window-buffer-names' list."
(let ((process-name
(if (and dedicated
buffer-file-name)
process-name))
(defun python-shell-parse-command ()
- "Calculates the string used to execute the inferior Python process."
+ "Calculate the string used to execute the inferior Python process."
(format "%s %s" python-shell-interpreter python-shell-interpreter-args))
(defun python-comint-output-filter-function (output)
(define-derived-mode inferior-python-mode comint-mode "Inferior Python"
"Major mode for Python inferior process.
-Adds `python-shell-completion-complete-at-point' to the
-`comint-dynamic-complete-functions' list. Also binds <tab> to
-`python-shell-complete-or-indent' in the
-`inferior-python-mode-map'."
+Runs a Python interpreter as a subprocess of Emacs, with Python
+I/O through an Emacs buffer. Variables
+`python-shell-interpreter' and `python-shell-interpreter-args'
+controls which Python interpreter is run. Variables
+`python-shell-prompt-regexp',
+`python-shell-prompt-output-regexp',
+`python-shell-prompt-block-regexp',
+`python-shell-completion-setup-code',
+`python-shell-completion-string-code', `python-eldoc-setup-code',
+`python-eldoc-string-code', `python-ffap-setup-code' and
+`python-ffap-string-code' can customize this mode for different
+Python interpreters.
+
+You can also add additional setup code to be run at
+initialization of the interpreter via `python-shell-setup-codes'
+variable.
+
+\(Type \\[describe-mode] in the process buffer for a list of commands.)"
(set-syntax-table python-mode-syntax-table)
(setq mode-line-process '(":%s"))
(setq comint-prompt-regexp (format "^\\(?:%s\\|%s\\|%s\\)"
(defun run-python (dedicated cmd)
"Run an inferior Python process.
-
-Input and output via buffer *\\[python-shell-buffer-name]*.
-
-If there is a process already running in
-*\\[python-shell-buffer-name]*, switch to that buffer.
-
-With argument, allows you to:
-
- * Define DEDICATED so a dedicated process for the current buffer
- is open.
-
- * Define CMD so you can edit the command used to call the
-interpreter (default is value of `python-shell-interpreter' and
-arguments defined in `python-shell-interpreter-args').
-
-Runs the hook `inferior-python-mode-hook' (after the
-`comint-mode-hook' is run).
-
-\(Type \\[describe-mode] in the process buffer for a list of
-commands.)"
+Input and output via buffer named after
+`python-shell-buffer-name'. If there is a process already
+running in that buffer, just switch to it.
+With argument, allows you to define DEDICATED, so a dedicated
+process for the current buffer is open, and define CMD so you can
+edit the command used to call the interpreter (default is value
+of `python-shell-interpreter' and arguments defined in
+`python-shell-interpreter-args'). Runs the hook
+`inferior-python-mode-hook' (after the `comint-mode-hook' is
+run).
+\(Type \\[describe-mode] in the process buffer for a list of commands.)"
(interactive
(if current-prefix-arg
(list
(defun python-shell-send-string-no-output (string &optional process msg)
"Send STRING to PROCESS and inhibit output.
-When MSG is non-nil messages the first line of STRING.
-Return the output."
+When MSG is non-nil messages the first line of STRING. Return
+the output."
(let* ((output-buffer)
(process (or process (python-shell-get-or-create-process)))
(comint-preoutput-filter-functions
(defun python-shell-completion-complete-or-indent ()
"Complete or indent depending on the context.
-If content before pointer is all whitespace indent. If not try to
-complete."
+If content before pointer is all whitespace indent. If not try
+to complete."
(interactive)
(if (string-match "^[[:space:]]*$"
(buffer-substring (comint-line-beginning-position)
(defvar python-pdbtrack-stacktrace-info-regexp
"> %s(\\([0-9]+\\))\\([?a-zA-Z0-9_<>]+\\)()"
- "Regexp matching stacktrace information.
-It is used to extract the current line and module beign
-inspected.
-The regexp should not start with a caret (^) and can contain a
-string placeholder (\%s) which is replaced with the filename
-beign inspected (so other files in the debugging process are not
+ "Regular Expression matching stacktrace information.
+Used to extract the current line and module beign inspected. The
+regexp should not start with a caret (^) and can contain a string
+placeholder (\%s) which is replaced with the filename beign
+inspected (so other files in the debugging process are not
opened)")
(defvar python-pdbtrack-tracking-buffers '()
(mapconcat (lambda (string) string) names "."))))
(defun python-info-closing-block ()
- "Return the point of the block that the current line closes."
+ "Return the point of the block the current line closes."
(let ((closing-word (save-excursion
(back-to-indentation)
(current-word)))
\f
;;;###autoload
(define-derived-mode python-mode fundamental-mode "Python"
- "A major mode for editing Python files."
+ "Major mode for editing Python files.
+
+\\{python-mode-map}
+Entry to this mode calls the value of `python-mode-hook'
+if that value is non-nil."
(set (make-local-variable 'tab-width) 8)
(set (make-local-variable 'indent-tabs-mode) nil)