1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-01-15 17:00:26 +00:00

Merge from origin/emacs-24

9664def Signal a file-error from directory-files on MS-Windows  (Bug#19701)
fd4e65e Added missing test for previous commit
5485e3e5 python.el: New non-global state dependent indentation engine.
3b23e6a Fix the description of --insert command-line option  (Bug#19694)
7a7e594 Add a cross-reference in ELisp manual.  (Bug#19668)
b4f4075 Fixes: debbugs:19660
83b3c31 * test/automated/regexp-tests.el: Require regexp-opt

Conflicts:
	lisp/progmodes/python.el
This commit is contained in:
Fabián Ezequiel Gallina 2015-01-28 01:08:18 -03:00
commit 95a2cb24b0
13 changed files with 914 additions and 486 deletions

View File

@ -1,3 +1,8 @@
2015-01-26 Eli Zaretskii <eliz@gnu.org>
* cmdargs.texi (Action Arguments): Clarify into which buffer
'--insert' inserts. (Bug#19694)
2015-01-21 Eli Zaretskii <eliz@gnu.org>
* programs.texi (Custom C Indent): Fix a typo. (Bug#19647)

View File

@ -165,9 +165,12 @@ Evaluate Lisp expression @var{expression}.
@item --insert=@var{file}
@opindex --insert
@cindex insert file contents, command-line argument
Insert the contents of @var{file} into the @file{*scratch*} buffer
(@pxref{Lisp Interaction}). This is like what @kbd{M-x insert-file}
does (@pxref{Misc File Ops}).
Insert the contents of @var{file} into the buffer that is current when
this command-line argument is processed. Usually, this is the
@file{*scratch*} buffer (@pxref{Lisp Interaction}), but if arguments
earlier on the command line visit files or switch buffers, that might
be a different buffer. The effect of this command-line argument is
like what @kbd{M-x insert-file} does (@pxref{Misc File Ops}).
@item --kill
@opindex --kill

View File

@ -1,3 +1,8 @@
2015-01-24 Eli Zaretskii <eliz@gnu.org>
* searching.texi (Regexp Search): Add a cross-reference to "Syntax
of Regexps". (Bug#19668)
2015-01-21 Daniel Koning <dk@danielkoning.com> (tiny change)
* commands.texi (Drag Events, Motion Events, Event Examples)

View File

@ -988,10 +988,11 @@ list of characters @var{chars}.
@cindex searching for regexp
In GNU Emacs, you can search for the next match for a regular
expression either incrementally or not. For incremental search
commands, see @ref{Regexp Search, , Regular Expression Search, emacs,
The GNU Emacs Manual}. Here we describe only the search functions
useful in programs. The principal one is @code{re-search-forward}.
expression (@pxref{Syntax of Regexps}) either incrementally or not.
For incremental search commands, see @ref{Regexp Search, , Regular
Expression Search, emacs, The GNU Emacs Manual}. Here we describe
only the search functions useful in programs. The principal one is
@code{re-search-forward}.
These search functions convert the regular expression to multibyte if
the buffer is multibyte; they convert the regular expression to unibyte

View File

@ -1,3 +1,23 @@
2015-01-26 Fabián Ezequiel Gallina <fgallina@gnu.org>
python.el: New non-global state dependent indentation engine.
(Bug#18319, Bug#19595)
* progmodes/python.el (python-syntax-comment-or-string-p): Accept
PPSS as argument.
(python-syntax-closing-paren-p): New function.
(python-indent-current-level)
(python-indent-levels): Mark obsolete.
(python-indent-context): Return more context cases.
(python-indent--calculate-indentation)
(python-indent--calculate-levels): New functions.
(python-indent-calculate-levels): Use them.
(python-indent-calculate-indentation, python-indent-line):
(python-indent-line-function): Rewritten to use new API.
(python-indent-dedent-line): Simplify logic.
(python-indent-dedent-line-backspace): Use `unless`.
(python-indent-toggle-levels): Delete function.
2015-01-21 Daniel Koning <dk@danielkoning.com> (tiny change)
* subr.el (posnp): Correct docstring of `posnp'.

View File

@ -463,9 +463,14 @@ The type returned can be `comment', `string' or `paren'."
((nth 8 ppss) (if (nth 4 ppss) 'comment 'string))
((nth 1 ppss) 'paren))))
(defsubst python-syntax-comment-or-string-p ()
"Return non-nil if point is inside 'comment or 'string."
(nth 8 (syntax-ppss)))
(defsubst python-syntax-comment-or-string-p (&optional ppss)
"Return non-nil if PPSS is inside 'comment or 'string."
(nth 8 (or ppss (syntax-ppss))))
(defsubst python-syntax-closing-paren-p ()
"Return non-nil if char after point is a closing paren."
(= (syntax-class (syntax-after (point)))
(syntax-class (string-to-syntax ")"))))
(define-obsolete-function-alias
'python-info-ppss-context #'python-syntax-context "24.3")
@ -704,11 +709,28 @@ It makes underscores and dots word constituent chars.")
'python-guess-indent 'python-indent-guess-indent-offset "24.3")
(defvar python-indent-current-level 0
"Current indentation level `python-indent-line-function' is using.")
"Deprecated var available for compatibility.")
(defvar python-indent-levels '(0)
"Levels of indentation available for `python-indent-line-function'.
Can also be `noindent' if automatic indentation can't be used.")
"Deprecated var available for compatibility.")
(make-obsolete-variable
'python-indent-current-level
"The indentation API changed to avoid global state.
The function `python-indent-calculate-levels' does not use it
anymore. If you were defadvising it and or depended on this
variable for indentation customizations, refactor your code to
work on `python-indent-calculate-indentation' instead."
"24.5")
(make-obsolete-variable
'python-indent-levels
"The indentation API changed to avoid global state.
The function `python-indent-calculate-levels' does not use it
anymore. If you were defadvising it and or depended on this
variable for indentation customizations, refactor your code to
work on `python-indent-calculate-indentation' instead."
"24.5")
(defun python-indent-guess-indent-offset ()
"Guess and set `python-indent-offset' for the current buffer."
@ -748,362 +770,358 @@ Can also be `noindent' if automatic indentation can't be used.")
python-indent-offset)))))))
(defun python-indent-context ()
"Get information on indentation context.
Context information is returned with a cons with the form:
(STATUS . START)
"Get information about the current indentation context.
Context is returned in a cons with the form (STATUS . START).
Where status can be any of the following symbols:
STATUS can be one of the following:
* after-comment: When current line might continue a comment block
* 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
* dedenter-statement: Point is on a dedenter statement.
* no-indent: Point is at beginning of buffer or other special case
START is the buffer position where the sexp starts."
keyword
-------
:after-comment
- Point is after a comment line.
- START is the position of the \"#\" character.
:inside-string
- Point is inside string.
- START is the position of the first quote that starts it.
:no-indent
- No possible indentation case matches.
- START is always zero.
:inside-paren
- Fallback case when point is inside paren.
- START is the first non space char position *after* the open paren.
:inside-paren-at-closing-nested-paren
- Point is on a line that contains a nested paren closer.
- START is the position of the open paren it closes.
:inside-paren-at-closing-paren
- Point is on a line that contains a paren closer.
- START is the position of the open paren.
:inside-paren-newline-start
- Point is inside a paren with items starting in their own line.
- START is the position of the open paren.
:inside-paren-newline-start-from-block
- Point is inside a paren with items starting in their own line
from a block start.
- START is the position of the open paren.
:after-backslash
- Fallback case when point is after backslash.
- START is the char after the position of the backslash.
:after-backslash-assignment-continuation
- Point is after a backslashed assignment.
- START is the char after the position of the backslash.
:after-backslash-block-continuation
- Point is after a backslashed block continuation.
- START is the char after the position of the backslash.
:after-backslash-dotted-continuation
- Point is after a backslashed dotted continuation. Previous
line must contain a dot to align with.
- START is the char after the position of the backslash.
:after-backslash-first-line
- First line following a backslashed continuation.
- START is the char after the position of the backslash.
:after-block-end
- Point is after a line containing a block ender.
- START is the position where the ender starts.
:after-block-start
- Point is after a line starting a block.
- START is the position where the block starts.
:after-line
- Point is after a simple line.
- START is the position where the previous line starts.
:at-dedenter-block-start
- Point is on a line starting a dedenter block.
- START is the position where the dedenter block starts."
(save-restriction
(widen)
(let ((ppss (save-excursion (beginning-of-line) (syntax-ppss)))
(start))
(cons
(cond
;; Beginning of buffer
((save-excursion
(goto-char (line-beginning-position))
(bobp))
'no-indent)
;; Comment continuation
((save-excursion
(when (and
(or
(python-info-current-line-comment-p)
(python-info-current-line-empty-p))
(progn
(forward-comment -1)
(python-info-current-line-comment-p)))
(setq start (point))
'after-comment)))
;; Inside string
((setq start (python-syntax-context 'string ppss))
'inside-string)
;; Inside a paren
((setq start (python-syntax-context 'paren ppss))
'inside-paren)
;; After backslash
((setq start (when (not (or (python-syntax-context 'string ppss)
(python-syntax-context 'comment ppss)))
(let ((line-beg-pos (line-number-at-pos)))
(python-info-line-ends-backslash-p
(1- line-beg-pos)))))
'after-backslash)
;; After beginning of block
((setq start (save-excursion
(when (progn
(back-to-indentation)
(python-util-forward-comment -1)
(equal (char-before) ?:))
;; Move to the first block start that's not in within
;; a string, comment or paren and that's not a
;; continuation line.
(while (and (re-search-backward
(python-rx block-start) nil t)
(or
(python-syntax-context-type)
(python-info-continuation-line-p))))
(when (looking-at (python-rx block-start))
(point-marker)))))
'after-beginning-of-block)
((when (setq start (python-info-dedenter-statement-p))
'dedenter-statement))
;; After normal line
((setq start (save-excursion
(let ((ppss (save-excursion
(beginning-of-line)
(syntax-ppss))))
(cond
;; Beginning of buffer.
((= (line-number-at-pos) 1)
(cons :no-indent 0))
;; Comment continuation (maybe).
((save-excursion
(when (and
(or
(python-info-current-line-comment-p)
(python-info-current-line-empty-p))
(forward-comment -1)
(python-info-current-line-comment-p))
(cons :after-comment (point)))))
;; Inside a string.
((let ((start (python-syntax-context 'string ppss)))
(when start
(cons :inside-string start))))
;; Inside a paren.
((let* ((start (python-syntax-context 'paren ppss))
(starts-in-newline
(when start
(save-excursion
(goto-char start)
(forward-char)
(not
(= (line-number-at-pos)
(progn
(python-util-forward-comment)
(line-number-at-pos))))))))
(when start
(cond
;; Current line only holds the closing paren.
((save-excursion
(skip-syntax-forward " ")
(when (and (python-syntax-closing-paren-p)
(progn
(forward-char 1)
(not (python-syntax-context 'paren))))
(cons :inside-paren-at-closing-paren start))))
;; Current line only holds a closing paren for nested.
((save-excursion
(back-to-indentation)
(python-syntax-closing-paren-p))
(cons :inside-paren-at-closing-nested-paren start))
;; This line starts from a opening block in its own line.
((save-excursion
(goto-char start)
(when (and
starts-in-newline
(save-excursion
(back-to-indentation)
(looking-at (python-rx block-start))))
(cons
:inside-paren-newline-start-from-block start))))
(starts-in-newline
(cons :inside-paren-newline-start start))
;; General case.
(t (cons :inside-paren
(save-excursion
(goto-char (1+ start))
(skip-syntax-forward "(" 1)
(skip-syntax-forward " ")
(point))))))))
;; After backslash.
((let ((start (when (not (python-syntax-comment-or-string-p ppss))
(python-info-line-ends-backslash-p
(1- (line-number-at-pos))))))
(when start
(cond
;; Continuation of dotted expression.
((save-excursion
(back-to-indentation)
(when (eq (char-after) ?\.)
;; Move point back until it's not inside a paren.
(while (prog2
(forward-line -1)
(and (not (bobp))
(python-syntax-context 'paren))))
(goto-char (line-end-position))
(while (and (search-backward
"." (line-beginning-position) t)
(python-syntax-context-type)))
;; Ensure previous statement has dot to align with.
(when (and (eq (char-after) ?\.)
(not (python-syntax-context-type)))
(cons :after-backslash-dotted-continuation (point))))))
;; Continuation of block definition.
((let ((block-continuation-start
(python-info-block-continuation-line-p)))
(when block-continuation-start
(save-excursion
(goto-char block-continuation-start)
(re-search-forward
(python-rx block-start (* space))
(line-end-position) t)
(cons :after-backslash-block-continuation (point))))))
;; Continuation of assignment.
((let ((assignment-continuation-start
(python-info-assignment-continuation-line-p)))
(when assignment-continuation-start
(save-excursion
(goto-char assignment-continuation-start)
(cons :after-backslash-assignment-continuation (point))))))
;; First line after backslash continuation start.
((save-excursion
(goto-char start)
(when (or (= (line-number-at-pos) 1)
(not (python-info-beginning-of-backslash
(1- (line-number-at-pos)))))
(cons :after-backslash-first-line start))))
;; General case.
(t (cons :after-backslash start))))))
;; After beginning of block.
((let ((start (save-excursion
(back-to-indentation)
(skip-chars-backward (rx (or whitespace ?\n)))
(python-util-forward-comment -1)
(when (equal (char-before) ?:)
(python-nav-beginning-of-block)))))
(when start
(cons :after-block-start start))))
;; At dedenter statement.
((let ((start (python-info-dedenter-statement-p)))
(when start
(cons :at-dedenter-block-start start))))
;; After normal line.
((let ((start (save-excursion
(back-to-indentation)
(skip-chars-backward " \t\n")
(python-nav-beginning-of-statement)
(point-marker)))
'after-line)
;; Do not indent
(t 'no-indent))
start))))
(point))))
(when start
(if (save-excursion
(python-util-forward-comment -1)
(python-nav-beginning-of-statement)
(looking-at (python-rx block-ender)))
(cons :after-block-end start)
(cons :after-line start)))))
;; Default case: do not indent.
(t (cons :no-indent 0))))))
(defun python-indent-calculate-indentation ()
"Calculate correct indentation offset for the current line.
Returns `noindent' if the indentation does not depend on Python syntax,
such as in strings."
(let* ((indentation-context (python-indent-context))
(context-status (car indentation-context))
(context-start (cdr indentation-context)))
(save-restriction
(widen)
(save-excursion
(pcase context-status
(`no-indent 0)
(`after-comment
(goto-char context-start)
(current-indentation))
;; When point is after beginning of block just add one level
;; of indentation relative to the context-start
(`after-beginning-of-block
(goto-char context-start)
(+ (current-indentation) python-indent-offset))
;; When after a simple line just use previous line
;; indentation.
(`after-line
(let* ((pair (save-excursion
(goto-char context-start)
(cons
(current-indentation)
(python-info-beginning-of-block-p))))
(context-indentation (car pair))
;; TODO: Separate block enders into its own case.
(adjustment
(if (save-excursion
(python-util-forward-comment -1)
(python-nav-beginning-of-statement)
(looking-at (python-rx block-ender)))
python-indent-offset
0)))
(- context-indentation adjustment)))
;; When point is on a dedenter statement, search for the
;; opening block that corresponds to it and use its
;; indentation. If no opening block is found just remove
;; indentation as this is an invalid python file.
(`dedenter-statement
(let ((block-start-point
(python-info-dedenter-opening-block-position)))
(save-excursion
(if (not block-start-point)
0
(goto-char block-start-point)
(current-indentation)))))
;; When inside of a string, do nothing. just use the current
;; indentation. XXX: perhaps it would be a good idea to
;; invoke standard text indentation here
(`inside-string 'noindent)
;; After backslash we have several possibilities.
(`after-backslash
(cond
;; Check if current line is a dot continuation. For this
;; the current line must start with a dot and previous
;; line must contain a dot too.
((save-excursion
(back-to-indentation)
(when (looking-at "\\.")
;; If after moving one line back point is inside a paren it
;; needs to move back until it's not anymore
(while (prog2
(forward-line -1)
(and (not (bobp))
(python-syntax-context 'paren))))
(goto-char (line-end-position))
(while (and (re-search-backward
"\\." (line-beginning-position) t)
(python-syntax-context-type)))
(if (and (looking-at "\\.")
(not (python-syntax-context-type)))
;; The indentation is the same column of the
;; first matching dot that's not inside a
;; comment, a string or a paren
(current-column)
;; No dot found on previous line, just add another
;; indentation level.
(+ (current-indentation) python-indent-offset)))))
;; Check if prev line is a block continuation
((let ((block-continuation-start
(python-info-block-continuation-line-p)))
(when block-continuation-start
;; If block-continuation-start is set jump to that
;; marker and use first column after the block start
;; as indentation value.
(goto-char block-continuation-start)
(re-search-forward
(python-rx block-start (* space))
(line-end-position) t)
(current-column))))
;; Check if current line is an assignment continuation
((let ((assignment-continuation-start
(python-info-assignment-continuation-line-p)))
(when assignment-continuation-start
;; If assignment-continuation is set jump to that
;; marker and use first column after the assignment
;; operator as indentation value.
(goto-char assignment-continuation-start)
(current-column))))
(t
(forward-line -1)
(goto-char (python-info-beginning-of-backslash))
(if (save-excursion
(and
(forward-line -1)
(goto-char
(or (python-info-beginning-of-backslash) (point)))
(python-info-line-ends-backslash-p)))
;; The two previous lines ended in a backslash so we must
;; respect previous line indentation.
(current-indentation)
;; What happens here is that we are dealing with the second
;; line of a backslash continuation, in that case we just going
;; to add one indentation level.
(+ (current-indentation) python-indent-offset)))))
;; When inside a paren there's a need to handle nesting
;; correctly
(`inside-paren
(cond
;; If current line closes the outermost open paren use the
;; current indentation of the context-start line.
((save-excursion
(skip-syntax-forward "\s" (line-end-position))
(when (and (looking-at (regexp-opt '(")" "]" "}")))
(progn
(forward-char 1)
(not (python-syntax-context 'paren))))
(goto-char context-start)
(current-indentation))))
;; If open paren is contained on a line by itself add another
;; indentation level, else look for the first word after the
;; opening paren and use it's column position as indentation
;; level.
((let* ((content-starts-in-newline)
(indent
(save-excursion
(if (setq content-starts-in-newline
(progn
(goto-char context-start)
(forward-char)
(save-restriction
(narrow-to-region
(line-beginning-position)
(line-end-position))
(python-util-forward-comment))
(looking-at "$")))
(+ (current-indentation) python-indent-offset)
(current-column)))))
;; Adjustments
(cond
;; If current line closes a nested open paren de-indent one
;; level.
((progn
(back-to-indentation)
(looking-at (regexp-opt '(")" "]" "}"))))
(- indent python-indent-offset))
;; If the line of the opening paren that wraps the current
;; line starts a block add another level of indentation to
;; follow new pep8 recommendation. See: http://ur1.ca/5rojx
((save-excursion
(when (and content-starts-in-newline
(progn
(goto-char context-start)
(back-to-indentation)
(looking-at (python-rx block-start))))
(+ indent python-indent-offset))))
(t indent)))))))))))
(defun python-indent--calculate-indentation ()
"Internal implementation of `python-indent-calculate-indentation'.
May return an integer for the maximum possible indentation at
current context or a list of integers. The latter case is only
happening for :at-dedenter-block-start context since the
possibilities can be narrowed to especific indentation points."
(save-restriction
(widen)
(save-excursion
(pcase (python-indent-context)
(`(:no-indent . ,_) 0)
(`(,(or :after-line
:after-comment
:inside-string
:after-backslash
:inside-paren-at-closing-paren
:inside-paren-at-closing-nested-paren) . ,start)
;; Copy previous indentation.
(goto-char start)
(current-indentation))
(`(,(or :after-block-start
:after-backslash-first-line
:inside-paren-newline-start) . ,start)
;; Add one indentation level.
(goto-char start)
(+ (current-indentation) python-indent-offset))
(`(,(or :inside-paren
:after-backslash-block-continuation
:after-backslash-assignment-continuation
:after-backslash-dotted-continuation) . ,start)
;; Use the column given by the context.
(goto-char start)
(current-column))
(`(:after-block-end . ,start)
;; Subtract one indentation level.
(goto-char start)
(- (current-indentation) python-indent-offset))
(`(:at-dedenter-block-start . ,_)
;; List all possible indentation levels from opening blocks.
(let ((opening-block-start-points
(python-info-dedenter-opening-block-positions)))
(if (not opening-block-start-points)
0 ; if not found default to first column
(mapcar (lambda (pos)
(save-excursion
(goto-char pos)
(current-indentation)))
opening-block-start-points))))
(`(,(or :inside-paren-newline-start-from-block) . ,start)
;; Add two indentation levels to make the suite stand out.
(goto-char start)
(+ (current-indentation) (* python-indent-offset 2)))))))
(defun python-indent--calculate-levels (indentation)
"Calculate levels list given INDENTATION.
Argument INDENTATION can either be an integer or a list of
integers. Levels are returned in ascending order, and in the
case INDENTATION is a list, this order is enforced."
(if (listp indentation)
(sort (copy-sequence indentation) #'<)
(let* ((remainder (% indentation python-indent-offset))
(steps (/ (- indentation remainder) python-indent-offset))
(levels (mapcar (lambda (step)
(* python-indent-offset step))
(number-sequence steps 0 -1))))
(reverse
(if (not (zerop remainder))
(cons indentation levels)
levels)))))
(defun python-indent--previous-level (levels indentation)
"Return previous level from LEVELS relative to INDENTATION."
(let* ((levels (sort (copy-sequence levels) #'>))
(default (car levels)))
(catch 'return
(dolist (level levels)
(when (funcall #'< level indentation)
(throw 'return level)))
default)))
(defun python-indent-calculate-indentation (&optional previous)
"Calculate indentation.
Get indentation of PREVIOUS level when argument is non-nil.
Return the max level of the cycle when indentation reaches the
minimum."
(let* ((indentation (python-indent--calculate-indentation))
(levels (python-indent--calculate-levels indentation)))
(if previous
(python-indent--previous-level levels (current-indentation))
(apply #'max levels))))
(defun python-indent-line (&optional previous)
"Internal implementation of `python-indent-line-function'.
Use the PREVIOUS level when argument is non-nil, otherwise indent
to the maxium available level. When indentation is the minimum
possible and PREVIOUS is non-nil, cycle back to the maximum
level."
(let ((follow-indentation-p
;; Check if point is within indentation.
(and (<= (line-beginning-position) (point))
(>= (+ (line-beginning-position)
(current-indentation))
(point)))))
(save-excursion
(indent-line-to
(python-indent-calculate-indentation previous))
(python-info-dedenter-opening-block-message))
(when follow-indentation-p
(back-to-indentation))))
(defun python-indent-calculate-levels ()
"Calculate `python-indent-levels' and reset `python-indent-current-level'."
(if (or (python-info-continuation-line-p)
(not (python-info-dedenter-statement-p)))
;; XXX: This asks for a refactor. Even if point is on a
;; dedenter statement, it could be multiline and in that case
;; the continuation lines should be indented with normal rules.
(let* ((indentation (python-indent-calculate-indentation)))
(if (not (numberp indentation))
(setq python-indent-levels indentation)
(let* ((remainder (% indentation python-indent-offset))
(steps (/ (- indentation remainder) python-indent-offset)))
(setq python-indent-levels (list 0))
(dotimes (step steps)
(push (* python-indent-offset (1+ step)) python-indent-levels))
(when (not (eq 0 remainder))
(push (+ (* python-indent-offset steps) remainder)
python-indent-levels)))))
(setq python-indent-levels
(or
(mapcar (lambda (pos)
(save-excursion
(goto-char pos)
(current-indentation)))
(python-info-dedenter-opening-block-positions))
(list 0))))
(when (listp python-indent-levels)
(setq python-indent-current-level (1- (length python-indent-levels))
python-indent-levels (nreverse python-indent-levels))))
(defun python-indent-toggle-levels ()
"Toggle `python-indent-current-level' over `python-indent-levels'."
(setq python-indent-current-level (1- python-indent-current-level))
(when (< python-indent-current-level 0)
(setq python-indent-current-level (1- (length python-indent-levels)))))
(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' to set the
current indentation.
When the variable `last-command' is equal to one of the symbols
inside `python-indent-trigger-commands' 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 one of the
symbols inside `python-indent-trigger-commands' and FORCE-TOGGLE
is nil it calculates possible indentation levels and saves them
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 (and (or (and (memq this-command python-indent-trigger-commands)
(eq last-command this-command))
force-toggle)
(not (equal python-indent-levels '(0))))
(if (listp python-indent-levels)
(python-indent-toggle-levels))
(python-indent-calculate-levels))
(if (eq python-indent-levels 'noindent)
python-indent-levels
(let* ((starting-pos (point-marker))
(indent-ending-position
(+ (line-beginning-position) (current-indentation)))
(follow-indentation-p
(or (bolp)
(and (<= (line-beginning-position) starting-pos)
(>= indent-ending-position starting-pos))))
(next-indent (nth python-indent-current-level python-indent-levels)))
(unless (= next-indent (current-indentation))
(beginning-of-line)
(delete-horizontal-space)
(indent-to next-indent)
(goto-char starting-pos))
(and follow-indentation-p (back-to-indentation)))
(python-info-dedenter-opening-block-message)))
"Return possible indentation levels."
(python-indent--calculate-levels
(python-indent--calculate-indentation)))
(defun python-indent-line-function ()
"`indent-line-function' for Python mode.
See `python-indent-line' for details."
(python-indent-line))
When the variable `last-command' is equal to one of the symbols
inside `python-indent-trigger-commands' it cycles possible
indentation levels from right to left."
(python-indent-line
(and (memq this-command python-indent-trigger-commands)
(eq last-command this-command))))
(defun python-indent-dedent-line ()
"De-indent current line."
(interactive "*")
(when (and (not (python-syntax-comment-or-string-p))
(<= (point) (save-excursion
(back-to-indentation)
(point)))
(> (current-column) 0))
(python-indent-line t)
t))
(when (and (not (bolp))
(not (python-syntax-comment-or-string-p))
(= (+ (line-beginning-position)
(current-indentation))
(point)))
(python-indent-line t)
t))
(defun python-indent-dedent-line-backspace (arg)
"De-indent current line.
Argument ARG is passed to `backward-delete-char-untabify' when
point is not in between the indentation."
(interactive "*p")
(when (not (python-indent-dedent-line))
(unless (python-indent-dedent-line)
(backward-delete-char-untabify arg)))
(put 'python-indent-dedent-line-backspace 'delete-selection 'supersede)
(defun python-indent-region (start end)

View File

@ -1,3 +1,16 @@
2015-01-27 Eli Zaretskii <eliz@gnu.org>
* dired.c (directory_files_internal) [WINDOWSNT]: If readdir
returns NULL and errno is ENOTDIR, behave as if opendir failed to
open the directory. (Bug#19701)
* w32.c (sys_readdir): If FindFirstFile fails because the
directory doesn't exist, set errno to ENOTDIR.
2015-01-24 Jan Djärv <jan.h.d@swipnet.se>
* nsterm.m (drawRect:): Add block/unblock_input (Bug#19660).
2015-01-21 Paul Eggert <eggert@cs.ucla.edu>
Fix coding.c subscript error

View File

@ -238,6 +238,19 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
QUIT;
continue;
}
#ifdef WINDOWSNT
/* The MS-Windows implementation of 'opendir' doesn't
actually open a directory until the first call to
'readdir'. If 'readdir' fails to open the directory, it
sets errno to ENOTDIR; we convert it here to ENOENT so
that the error message is similar to what happens on
Posix hosts in such cases. */
if (errno == ENOTDIR)
{
errno = ENOENT;
report_file_error ("Opening directory", directory);
}
#endif
break;
}

View File

@ -6773,7 +6773,9 @@ - (void)drawRect: (NSRect)rect
return;
ns_clear_frame_area (emacsframe, x, y, width, height);
block_input ();
expose_frame (emacsframe, x, y, width, height);
unblock_input ();
/*
drawRect: may be called (at least in OS X 10.5) for invisible

View File

@ -3433,7 +3433,22 @@ sys_readdir (DIR *dirp)
}
if (dir_find_handle == INVALID_HANDLE_VALUE)
return NULL;
{
switch (GetLastError ())
{
case ERROR_PATH_NOT_FOUND:
case ERROR_ACCESS_DENIED:
case ERROR_INVALID_DRIVE:
case ERROR_BAD_NETPATH:
/* This special value will be noticed by
directory_files_internal, which see. */
errno = ENOTDIR;
break;
default:
break;
}
return NULL;
}
}
else if (w32_unicode_filenames)
{

View File

@ -1,3 +1,30 @@
2015-01-26 Fabián Ezequiel Gallina <fgallina@gnu.org>
* automated/python-tests.el (python-indent-pep8-1)
(python-indent-pep8-2, python-indent-pep8-3)
(python-indent-after-comment-1, python-indent-after-comment-2)
(python-indent-inside-paren-1, python-indent-inside-paren-2)
(python-indent-after-block-1, python-indent-after-block-2)
(python-indent-after-backslash-1, python-indent-after-backslash-2)
(python-indent-after-backslash-3, python-indent-block-enders-1)
(python-indent-block-enders-2, python-indent-block-enders-3)
(python-indent-block-enders-4, python-indent-block-enders-5)
(python-indent-dedenters-1, python-indent-dedenters-2)
(python-indent-dedenters-3, python-indent-dedenters-4)
(python-indent-dedenters-5, python-indent-dedenters-6)
(python-indent-dedenters-7, python-indent-dedenters-8): Fix tests.
(python-indent-base-case, python-indent-after-block-3)
(python-indent-after-backslash-5, python-indent-inside-paren-3)
(python-indent-inside-paren-4, python-indent-inside-paren-5)
(python-indent-inside-paren-6, python-indent-inside-string-1)
(python-indent-inside-string-2, python-indent-inside-string-3)
(python-indent-dedent-line-backspace-1): New Tests.
2015-01-24 Glenn Morris <rgm@gnu.org>
* automated/regexp-tests.el: Require regexp-opt, which is
not preloaded --without-x.
2015-01-26 Stefan Monnier <monnier@iro.umontreal.ca>
* automated/cl-generic-tests.el: Try and make sure cl-lib is not

View File

@ -174,13 +174,13 @@ aliqua."
foo = long_function_name(var_one, var_two,
var_three, var_four)
"
(should (eq (car (python-indent-context)) 'no-indent))
(should (eq (car (python-indent-context)) :no-indent))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "foo = long_function_name(var_one, var_two,")
(should (eq (car (python-indent-context)) 'after-line))
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "var_three, var_four)")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren))
(should (= (python-indent-calculate-indentation) 25))))
(ert-deftest python-indent-pep8-2 ()
@ -192,19 +192,22 @@ def long_function_name(
var_four):
print (var_one)
"
(should (eq (car (python-indent-context)) 'no-indent))
(should (eq (car (python-indent-context)) :no-indent))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "def long_function_name(")
(should (eq (car (python-indent-context)) 'after-line))
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "var_one, var_two, var_three,")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context))
:inside-paren-newline-start-from-block))
(should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at "var_four):")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context))
:inside-paren-newline-start-from-block))
(should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at "print (var_one)")
(should (eq (car (python-indent-context)) 'after-beginning-of-block))
(should (eq (car (python-indent-context))
:after-block-start))
(should (= (python-indent-calculate-indentation) 4))))
(ert-deftest python-indent-pep8-3 ()
@ -215,18 +218,34 @@ foo = long_function_name(
var_one, var_two,
var_three, var_four)
"
(should (eq (car (python-indent-context)) 'no-indent))
(should (eq (car (python-indent-context)) :no-indent))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "foo = long_function_name(")
(should (eq (car (python-indent-context)) 'after-line))
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "var_one, var_two,")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "var_three, var_four)")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 4))))
(ert-deftest python-indent-base-case ()
"Check base case does not trigger errors."
(python-tests-with-temp-buffer
"
"
(goto-char (point-min))
(should (eq (car (python-indent-context)) :no-indent))
(should (= (python-indent-calculate-indentation) 0))
(forward-line 1)
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(forward-line 1)
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))))
(ert-deftest python-indent-after-comment-1 ()
"The most simple after-comment case that shouldn't fail."
(python-tests-with-temp-buffer
@ -240,23 +259,23 @@ class Blag(object):
# with the exception with which the first child failed.
"
(python-tests-look-at "# We only complete")
(should (eq (car (python-indent-context)) 'after-line))
(should (eq (car (python-indent-context)) :after-block-end))
(should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at "# terminal state")
(should (eq (car (python-indent-context)) 'after-comment))
(should (eq (car (python-indent-context)) :after-comment))
(should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at "# with the exception")
(should (eq (car (python-indent-context)) 'after-comment))
(should (eq (car (python-indent-context)) :after-comment))
;; This one indents relative to previous block, even given the fact
;; that it was under-indented.
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "# terminal state" -1)
;; It doesn't hurt to check again.
(should (eq (car (python-indent-context)) 'after-comment))
(should (eq (car (python-indent-context)) :after-comment))
(python-indent-line)
(should (= (current-indentation) 8))
(python-tests-look-at "# with the exception")
(should (eq (car (python-indent-context)) 'after-comment))
(should (eq (car (python-indent-context)) :after-comment))
;; Now everything should be lined up.
(should (= (python-indent-calculate-indentation) 8))))
@ -275,33 +294,33 @@ now_we_do_mess_cause_this_is_not_a_comment = 1
# yeah, that.
"
(python-tests-look-at "# I don't do much")
(should (eq (car (python-indent-context)) 'after-beginning-of-block))
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "return arg")
;; Comment here just gets ignored, this line is not a comment so
;; the rules won't apply here.
(should (eq (car (python-indent-context)) 'after-beginning-of-block))
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "# This comment is badly")
(should (eq (car (python-indent-context)) 'after-line))
(should (eq (car (python-indent-context)) :after-block-end))
;; The return keyword moves indentation backwards 4 spaces, but
;; let's assume this comment was placed there because the user
;; wanted to (manually adding spaces or whatever).
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "# but we won't mess")
(should (eq (car (python-indent-context)) 'after-comment))
(should (eq (car (python-indent-context)) :after-comment))
(should (= (python-indent-calculate-indentation) 4))
;; Behave the same for blank lines: potentially a comment.
(forward-line 1)
(should (eq (car (python-indent-context)) 'after-comment))
(should (eq (car (python-indent-context)) :after-comment))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "now_we_do_mess")
;; Here is where comment indentation starts to get ignored and
;; where the user can't freely indent anymore.
(should (eq (car (python-indent-context)) 'after-line))
(should (eq (car (python-indent-context)) :after-block-end))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "# yeah, that.")
(should (eq (car (python-indent-context)) 'after-line))
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))))
(ert-deftest python-indent-inside-paren-1 ()
@ -325,49 +344,53 @@ data = {
}
"
(python-tests-look-at "data = {")
(should (eq (car (python-indent-context)) 'after-line))
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "'key':")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "{")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "'objlist': [")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at "{")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 12))
(python-tests-look-at "'pk': 1,")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 16))
(python-tests-look-at "'name': 'first',")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 16))
(python-tests-look-at "},")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context))
:inside-paren-at-closing-nested-paren))
(should (= (python-indent-calculate-indentation) 12))
(python-tests-look-at "{")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 12))
(python-tests-look-at "'pk': 2,")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 16))
(python-tests-look-at "'name': 'second',")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 16))
(python-tests-look-at "}")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context))
:inside-paren-at-closing-nested-paren))
(should (= (python-indent-calculate-indentation) 12))
(python-tests-look-at "]")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context))
:inside-paren-at-closing-nested-paren))
(should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at "}")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context))
:inside-paren-at-closing-nested-paren))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "}")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-at-closing-paren))
(should (= (python-indent-calculate-indentation) 0))))
(ert-deftest python-indent-inside-paren-2 ()
@ -384,43 +407,121 @@ data = {'key': {
}}
"
(python-tests-look-at "data = {")
(should (eq (car (python-indent-context)) 'after-line))
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "'objlist': [")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "{'pk': 1,")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at "'name': 'first'},")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren))
(should (= (python-indent-calculate-indentation) 9))
(python-tests-look-at "{'pk': 2,")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at "'name': 'second'}")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren))
(should (= (python-indent-calculate-indentation) 9))
(python-tests-look-at "]")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context))
:inside-paren-at-closing-nested-paren))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "}}")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context))
:inside-paren-at-closing-nested-paren))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "}")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-at-closing-paren))
(should (= (python-indent-calculate-indentation) 0))))
(ert-deftest python-indent-inside-paren-3 ()
"The simplest case possible."
(python-tests-with-temp-buffer
"
data = ('these',
'are',
'the',
'tokens')
"
(python-tests-look-at "data = ('these',")
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren))
(should (= (python-indent-calculate-indentation) 8))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren))
(should (= (python-indent-calculate-indentation) 8))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren))
(should (= (python-indent-calculate-indentation) 8))))
(ert-deftest python-indent-inside-paren-4 ()
"Respect indentation of first column."
(python-tests-with-temp-buffer
"
data = [ [ 'these', 'are'],
['the', 'tokens' ] ]
"
(python-tests-look-at "data = [ [ 'these', 'are'],")
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren))
(should (= (python-indent-calculate-indentation) 9))))
(ert-deftest python-indent-inside-paren-5 ()
"Test when :inside-paren initial parens are skipped in context start."
(python-tests-with-temp-buffer
"
while ((not some_condition) and
another_condition):
do_something_interesting(
with_some_arg)
"
(python-tests-look-at "while ((not some_condition) and")
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren))
(should (= (python-indent-calculate-indentation) 7))
(forward-line 1)
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 8))))
(ert-deftest python-indent-inside-paren-6 ()
"This should be aligned.."
(python-tests-with-temp-buffer
"
CHOICES = (('some', 'choice'),
('another', 'choice'),
('more', 'choices'))
"
(python-tests-look-at "CHOICES = (('some', 'choice'),")
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren))
(should (= (python-indent-calculate-indentation) 11))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren))
(should (= (python-indent-calculate-indentation) 11))))
(ert-deftest python-indent-after-block-1 ()
"The most simple after-block case that shouldn't fail."
(python-tests-with-temp-buffer
"
def foo(a, b, c=True):
"
(should (eq (car (python-indent-context)) 'no-indent))
(should (eq (car (python-indent-context)) :no-indent))
(should (= (python-indent-calculate-indentation) 0))
(goto-char (point-max))
(should (eq (car (python-indent-context)) 'after-beginning-of-block))
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))))
(ert-deftest python-indent-after-block-2 ()
@ -432,9 +533,28 @@ def foo(a, b, c={
}):
"
(goto-char (point-max))
(should (eq (car (python-indent-context)) 'after-beginning-of-block))
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))))
(ert-deftest python-indent-after-block-3 ()
"A weird (malformed) sample, usually found in python shells."
(python-tests-with-temp-buffer
"
In [1]:
def func():
pass
In [2]:
something
"
(python-tests-look-at "pass")
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "something")
(end-of-line)
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))))
(ert-deftest python-indent-after-backslash-1 ()
"The most common case."
(python-tests-with-temp-buffer
@ -444,16 +564,16 @@ from foo.bar.baz import something, something_1 \\\\
something_4, something_5
"
(python-tests-look-at "from foo.bar.baz import something, something_1")
(should (eq (car (python-indent-context)) 'after-line))
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "something_2 something_3,")
(should (eq (car (python-indent-context)) 'after-backslash))
(should (eq (car (python-indent-context)) :after-backslash-first-line))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "something_4, something_5")
(should (eq (car (python-indent-context)) 'after-backslash))
(should (eq (car (python-indent-context)) :after-backslash))
(should (= (python-indent-calculate-indentation) 4))
(goto-char (point-max))
(should (eq (car (python-indent-context)) 'after-line))
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))))
(ert-deftest python-indent-after-backslash-2 ()
@ -471,40 +591,104 @@ objects = Thing.objects.all() \\\\
.values_list()
"
(python-tests-look-at "objects = Thing.objects.all()")
(should (eq (car (python-indent-context)) 'after-line))
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at ".filter(")
(should (eq (car (python-indent-context)) 'after-backslash))
(should (eq (car (python-indent-context))
:after-backslash-dotted-continuation))
(should (= (python-indent-calculate-indentation) 23))
(python-tests-look-at "type='toy',")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 27))
(python-tests-look-at "status='bought'")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 27))
(python-tests-look-at ") \\\\")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-at-closing-paren))
(should (= (python-indent-calculate-indentation) 23))
(python-tests-look-at ".aggregate(")
(should (eq (car (python-indent-context)) 'after-backslash))
(should (eq (car (python-indent-context))
:after-backslash-dotted-continuation))
(should (= (python-indent-calculate-indentation) 23))
(python-tests-look-at "Sum('amount')")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 27))
(python-tests-look-at ") \\\\")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-at-closing-paren))
(should (= (python-indent-calculate-indentation) 23))
(python-tests-look-at ".values_list()")
(should (eq (car (python-indent-context)) 'after-backslash))
(should (eq (car (python-indent-context))
:after-backslash-dotted-continuation))
(should (= (python-indent-calculate-indentation) 23))
(forward-line 1)
(should (eq (car (python-indent-context)) 'after-line))
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))))
(ert-deftest python-indent-after-backslash-3 ()
"Backslash continuation from block start."
(python-tests-with-temp-buffer
"
with open('/path/to/some/file/you/want/to/read') as file_1, \\\\
open('/path/to/some/file/being/written', 'w') as file_2:
file_2.write(file_1.read())
"
(python-tests-look-at
"with open('/path/to/some/file/you/want/to/read') as file_1, \\\\")
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at
"open('/path/to/some/file/being/written', 'w') as file_2")
(should (eq (car (python-indent-context))
:after-backslash-block-continuation))
(should (= (python-indent-calculate-indentation) 5))
(python-tests-look-at "file_2.write(file_1.read())")
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))))
(ert-deftest python-indent-after-backslash-4 ()
"Backslash continuation from assignment."
(python-tests-with-temp-buffer
"
super_awful_assignment = some_calculation() and \\\\
another_calculation() and \\\\
some_final_calculation()
"
(python-tests-look-at
"super_awful_assignment = some_calculation() and \\\\")
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "another_calculation() and \\\\")
(should (eq (car (python-indent-context))
:after-backslash-assignment-continuation))
(should (= (python-indent-calculate-indentation) 25))
(python-tests-look-at "some_final_calculation()")
(should (eq (car (python-indent-context)) :after-backslash))
(should (= (python-indent-calculate-indentation) 25))))
(ert-deftest python-indent-after-backslash-5 ()
"Dotted continuation bizarre example."
(python-tests-with-temp-buffer
"
def delete_all_things():
Thing \\\\
.objects.all() \\\\
.delete()
"
(python-tests-look-at "Thing \\\\")
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at ".objects.all() \\\\")
(should (eq (car (python-indent-context)) :after-backslash-first-line))
(should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at ".delete()")
(should (eq (car (python-indent-context))
:after-backslash-dotted-continuation))
(should (= (python-indent-calculate-indentation) 16))))
(ert-deftest python-indent-block-enders-1 ()
"Test de-indentation for pass keyword."
(python-tests-with-temp-buffer
"
"
Class foo(object):
def bar(self):
@ -516,17 +700,18 @@ Class foo(object):
else:
pass
"
(python-tests-look-at "3)")
(forward-line 1)
(should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at "pass")
(forward-line 1)
(should (= (python-indent-calculate-indentation) 8))))
(python-tests-look-at "3)")
(forward-line 1)
(should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at "pass")
(forward-line 1)
(should (eq (car (python-indent-context)) :after-block-end))
(should (= (python-indent-calculate-indentation) 8))))
(ert-deftest python-indent-block-enders-2 ()
"Test de-indentation for return keyword."
(python-tests-with-temp-buffer
"
"
Class foo(object):
'''raise lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
@ -539,64 +724,68 @@ Class foo(object):
2,
3)
"
(python-tests-look-at "def")
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "if")
(should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at "return")
(should (= (python-indent-calculate-indentation) 12))
(goto-char (point-max))
(should (= (python-indent-calculate-indentation) 8))))
(python-tests-look-at "def")
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "if")
(should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at "return")
(should (= (python-indent-calculate-indentation) 12))
(goto-char (point-max))
(should (eq (car (python-indent-context)) :after-block-end))
(should (= (python-indent-calculate-indentation) 8))))
(ert-deftest python-indent-block-enders-3 ()
"Test de-indentation for continue keyword."
(python-tests-with-temp-buffer
"
"
for element in lst:
if element is None:
continue
"
(python-tests-look-at "if")
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "continue")
(should (= (python-indent-calculate-indentation) 8))
(forward-line 1)
(should (= (python-indent-calculate-indentation) 4))))
(python-tests-look-at "if")
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "continue")
(should (= (python-indent-calculate-indentation) 8))
(forward-line 1)
(should (eq (car (python-indent-context)) :after-block-end))
(should (= (python-indent-calculate-indentation) 4))))
(ert-deftest python-indent-block-enders-4 ()
"Test de-indentation for break keyword."
(python-tests-with-temp-buffer
"
"
for element in lst:
if element is None:
break
"
(python-tests-look-at "if")
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "break")
(should (= (python-indent-calculate-indentation) 8))
(forward-line 1)
(should (= (python-indent-calculate-indentation) 4))))
(python-tests-look-at "if")
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "break")
(should (= (python-indent-calculate-indentation) 8))
(forward-line 1)
(should (eq (car (python-indent-context)) :after-block-end))
(should (= (python-indent-calculate-indentation) 4))))
(ert-deftest python-indent-block-enders-5 ()
"Test de-indentation for raise keyword."
(python-tests-with-temp-buffer
"
"
for element in lst:
if element is None:
raise ValueError('Element cannot be None')
"
(python-tests-look-at "if")
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "raise")
(should (= (python-indent-calculate-indentation) 8))
(forward-line 1)
(should (= (python-indent-calculate-indentation) 4))))
(python-tests-look-at "if")
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "raise")
(should (= (python-indent-calculate-indentation) 8))
(forward-line 1)
(should (eq (car (python-indent-context)) :after-block-end))
(should (= (python-indent-calculate-indentation) 4))))
(ert-deftest python-indent-dedenters-1 ()
"Test de-indentation for the elif keyword."
(python-tests-with-temp-buffer
"
"
if save:
try:
write_to_disk(data)
@ -604,15 +793,15 @@ if save:
cleanup()
elif
"
(python-tests-look-at "elif\n")
(should (eq (car (python-indent-context)) 'dedenter-statement))
(should (= (python-indent-calculate-indentation) 0))
(should (equal (python-indent-calculate-levels) '(0)))))
(python-tests-look-at "elif\n")
(should (eq (car (python-indent-context)) :at-dedenter-block-start))
(should (= (python-indent-calculate-indentation) 0))
(should (= (python-indent-calculate-indentation t) 0))))
(ert-deftest python-indent-dedenters-2 ()
"Test de-indentation for the else keyword."
(python-tests-with-temp-buffer
"
"
if save:
try:
write_to_disk(data)
@ -627,43 +816,50 @@ if save:
finally:
data.free()
"
(python-tests-look-at "else\n")
(should (eq (car (python-indent-context)) 'dedenter-statement))
(should (= (python-indent-calculate-indentation) 8))
(should (equal (python-indent-calculate-levels) '(0 4 8)))))
(python-tests-look-at "else\n")
(should (eq (car (python-indent-context)) :at-dedenter-block-start))
(should (= (python-indent-calculate-indentation) 8))
(python-indent-line t)
(should (= (python-indent-calculate-indentation t) 4))
(python-indent-line t)
(should (= (python-indent-calculate-indentation t) 0))
(python-indent-line t)
(should (= (python-indent-calculate-indentation t) 8))))
(ert-deftest python-indent-dedenters-3 ()
"Test de-indentation for the except keyword."
(python-tests-with-temp-buffer
"
"
if save:
try:
write_to_disk(data)
except
"
(python-tests-look-at "except\n")
(should (eq (car (python-indent-context)) 'dedenter-statement))
(should (= (python-indent-calculate-indentation) 4))
(should (equal (python-indent-calculate-levels) '(4)))))
(python-tests-look-at "except\n")
(should (eq (car (python-indent-context)) :at-dedenter-block-start))
(should (= (python-indent-calculate-indentation) 4))
(python-indent-line t)
(should (= (python-indent-calculate-indentation t) 4))))
(ert-deftest python-indent-dedenters-4 ()
"Test de-indentation for the finally keyword."
(python-tests-with-temp-buffer
"
"
if save:
try:
write_to_disk(data)
finally
"
(python-tests-look-at "finally\n")
(should (eq (car (python-indent-context)) 'dedenter-statement))
(should (= (python-indent-calculate-indentation) 4))
(should (equal (python-indent-calculate-levels) '(4)))))
(python-tests-look-at "finally\n")
(should (eq (car (python-indent-context)) :at-dedenter-block-start))
(should (= (python-indent-calculate-indentation) 4))
(python-indent-line t)
(should (= (python-indent-calculate-indentation) 4))))
(ert-deftest python-indent-dedenters-5 ()
"Test invalid levels are skipped in a complex example."
(python-tests-with-temp-buffer
"
"
if save:
try:
write_to_disk(data)
@ -676,29 +872,31 @@ if save:
do_cleanup()
else
"
(python-tests-look-at "else\n")
(should (eq (car (python-indent-context)) 'dedenter-statement))
(should (= (python-indent-calculate-indentation) 8))
(should (equal (python-indent-calculate-levels) '(0 8)))))
(python-tests-look-at "else\n")
(should (eq (car (python-indent-context)) :at-dedenter-block-start))
(should (= (python-indent-calculate-indentation) 8))
(should (= (python-indent-calculate-indentation t) 0))
(python-indent-line t)
(should (= (python-indent-calculate-indentation t) 8))))
(ert-deftest python-indent-dedenters-6 ()
"Test indentation is zero when no opening block for dedenter."
(python-tests-with-temp-buffer
"
"
try:
# if save:
write_to_disk(data)
else
"
(python-tests-look-at "else\n")
(should (eq (car (python-indent-context)) 'dedenter-statement))
(should (= (python-indent-calculate-indentation) 0))
(should (equal (python-indent-calculate-levels) '(0)))))
(python-tests-look-at "else\n")
(should (eq (car (python-indent-context)) :at-dedenter-block-start))
(should (= (python-indent-calculate-indentation) 0))
(should (= (python-indent-calculate-indentation t) 0))))
(ert-deftest python-indent-dedenters-7 ()
"Test indentation case from Bug#15163."
(python-tests-with-temp-buffer
"
"
if a:
if b:
pass
@ -706,10 +904,10 @@ if a:
pass
else:
"
(python-tests-look-at "else:" 2)
(should (eq (car (python-indent-context)) 'dedenter-statement))
(should (= (python-indent-calculate-indentation) 0))
(should (equal (python-indent-calculate-levels) '(0)))))
(python-tests-look-at "else:" 2)
(should (eq (car (python-indent-context)) :at-dedenter-block-start))
(should (= (python-indent-calculate-indentation) 0))
(should (= (python-indent-calculate-indentation t) 0))))
(ert-deftest python-indent-dedenters-8 ()
"Test indentation for Bug#18432."
@ -721,10 +919,99 @@ if (a == 1 or
elif (a == 3 or
a == 4):
"
(python-tests-look-at "elif (a == 3 or")
(should (eq (car (python-indent-context)) :at-dedenter-block-start))
(should (= (python-indent-calculate-indentation) 0))
(should (= (python-indent-calculate-indentation t) 0))
(python-tests-look-at "a == 4):\n")
(should (eq (car (python-indent-context)) 'inside-paren))
(should (eq (car (python-indent-context)) :inside-paren))
(should (= (python-indent-calculate-indentation) 6))
(should (equal (python-indent-calculate-levels) '(0 4 6)))))
(python-indent-line)
(should (= (python-indent-calculate-indentation t) 4))
(python-indent-line t)
(should (= (python-indent-calculate-indentation t) 0))
(python-indent-line t)
(should (= (python-indent-calculate-indentation t) 6))))
(ert-deftest python-indent-inside-string-1 ()
"Test indentation for strings."
(python-tests-with-temp-buffer
"
multiline = '''
bunch
of
lines
'''
"
(python-tests-look-at "multiline = '''")
(should (eq (car (python-indent-context)) :after-line))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "bunch")
(should (eq (car (python-indent-context)) :inside-string))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "of")
(should (eq (car (python-indent-context)) :inside-string))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "lines")
(should (eq (car (python-indent-context)) :inside-string))
(should (= (python-indent-calculate-indentation) 0))
(python-tests-look-at "'''")
(should (eq (car (python-indent-context)) :inside-string))
(should (= (python-indent-calculate-indentation) 0))))
(ert-deftest python-indent-inside-string-2 ()
"Test indentation for docstrings."
(python-tests-with-temp-buffer
"
def fn(a, b, c=True):
'''docstring
bunch
of
lines
'''
"
(python-tests-look-at "'''docstring")
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "bunch")
(should (eq (car (python-indent-context)) :inside-string))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "of")
(should (eq (car (python-indent-context)) :inside-string))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "lines")
(should (eq (car (python-indent-context)) :inside-string))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "'''")
(should (eq (car (python-indent-context)) :inside-string))
(should (= (python-indent-calculate-indentation) 4))))
(ert-deftest python-indent-inside-string-3 ()
"Test indentation for nested strings."
(python-tests-with-temp-buffer
"
def fn(a, b, c=True):
some_var = '''
bunch
of
lines
'''
"
(python-tests-look-at "some_var = '''")
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "bunch")
(should (eq (car (python-indent-context)) :inside-string))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "of")
(should (eq (car (python-indent-context)) :inside-string))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "lines")
(should (eq (car (python-indent-context)) :inside-string))
(should (= (python-indent-calculate-indentation) 4))
(python-tests-look-at "'''")
(should (eq (car (python-indent-context)) :inside-string))
(should (= (python-indent-calculate-indentation) 4))))
(ert-deftest python-indent-electric-colon-1 ()
"Test indentation case from Bug#18228."
@ -1802,6 +2089,23 @@ def f():
(python-nav-backward-up-list)
(should (looking-at "def f():"))))
(ert-deftest python-indent-dedent-line-backspace-1 ()
"Check de-indentation on first call. Bug#18319."
(python-tests-with-temp-buffer
"
if True:
x ()
if False:
"
(python-tests-look-at "if False:")
(call-interactively #'python-indent-dedent-line-backspace)
(should (zerop (current-indentation)))
;; XXX: This should be a call to `undo' but it's triggering errors.
(insert " ")
(should (= (current-indentation) 4))
(call-interactively #'python-indent-dedent-line-backspace)
(should (zerop (current-indentation)))))
;;; Shell integration

View File

@ -23,6 +23,8 @@
;;; Code:
(require 'regexp-opt)
(ert-deftest regexp-test-regexp-opt ()
"Test the `compilation-error-regexp-alist' regexps.
The test data is in `compile-tests--test-regexps-data'."