diff options
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ChangeLog | 38 | ||||
| -rw-r--r-- | lisp/faces.el | 7 | ||||
| -rw-r--r-- | lisp/progmodes/python.el | 204 | ||||
| -rw-r--r-- | lisp/vc/log-edit.el | 78 | ||||
| -rw-r--r-- | lisp/vc/vc-dispatcher.el | 2 |
5 files changed, 202 insertions, 127 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index faa5a3dffff..db1f0481d62 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,41 @@ +2014-07-12 Paul Eggert <eggert@cs.ucla.edu> + + Fix bug: C-x v v discarded existing log message (Bug#17884). + * vc/vc-dispatcher.el (vc-log-edit): + Don't clobber an already-existing log message. + +2014-07-12 Glenn Morris <rgm@gnu.org> + + * vc/log-edit.el (log-edit-changelog-entries): + Check for a visited-but-never-saved ChangeLog. + +2014-07-12 Stefan Monnier <monnier@iro.umontreal.ca> + + * vc/log-edit.el (log-edit-changelog-entries): Don't both visiting + a non-existing file (bug#17970). + + * faces.el (face-name): Undo last change. + (x-resolve-font-name): Don't call face-name (bug#17956). + +2014-07-12 Fabián Ezequiel Gallina <fgallina@gnu.org> + + Fix dedenters and electric colon handling. (Bug#15163) + * progmodes/python.el + (python-rx-constituents): Add dedenter and block-ender. + (python-indent-dedenters, python-indent-block-enders): Delete. + (python-indent-context): Return new case for dedenter-statement. + (python-indent-calculate-indentation): Handle new case. + (python-indent-calculate-levels): Fix levels calculation for + dedenter statements. + (python-indent-post-self-insert-function): Fix colon handling. + (python-info-dedenter-opening-block-message): New function. + (python-indent-line): Use it. + (python-info-closing-block) + (python-info-closing-block-message): Remove. + (python-info-dedenter-opening-block-position) + (python-info-dedenter-opening-block-positions) + (python-info-dedenter-statement-p): New functions. + 2014-07-11 Dmitry Antipov <dmantipov@yandex.ru> * files.el (out-of-memory-warning-percentage): New defcustom. diff --git a/lisp/faces.el b/lisp/faces.el index bb77af0425e..d9239d9e1eb 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -370,10 +370,7 @@ If `inhibit-x-resources' is non-nil, this function does nothing." (defun face-name (face) "Return the name of face FACE." - (check-face face) - (if (symbolp face) - (symbol-name face) - face)) + (symbol-name (check-face face))) (defun face-all-attributes (face &optional frame) @@ -2749,8 +2746,6 @@ If PATTERN is nil, return the name of the frame's base font, which never contains wildcards. Given optional arguments FACE and FRAME, return a font which is also the same size as FACE on FRAME, or fail." - (when face - (setq face (face-name face))) (and (eq frame t) (setq frame nil)) (if pattern diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 065a182904f..1187636c663 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -321,6 +321,13 @@ (or "def" "class" "if" "elif" "else" "try" "except" "finally" "for" "while" "with") symbol-end)) + (dedenter . ,(rx symbol-start + (or "elif" "else" "except" "finally") + symbol-end)) + (block-ender . ,(rx symbol-start + (or + "break" "continue" "pass" "raise" "return") + symbol-end)) (decorator . ,(rx line-start (* space) ?@ (any letter ?_) (* (any word ?_)))) (defun . ,(rx symbol-start (or "def" "class") symbol-end)) @@ -630,18 +637,6 @@ It makes underscores and dots word constituent chars.") (defvar python-indent-levels '(0) "Levels of indentation available for `python-indent-line-function'.") -(defvar python-indent-dedenters '("else" "elif" "except" "finally") - "List of words that should be dedented. -These make `python-indent-calculate-indentation' subtract the value of -`python-indent-offset'.") - -(defvar python-indent-block-enders - '("break" "continue" "pass" "raise" "return") - "List of words that mark the end of a block. -These make `python-indent-calculate-indentation' subtract the -value of `python-indent-offset' when `python-indent-context' is -AFTER-LINE.") - (defun python-indent-guess-indent-offset () "Guess and set `python-indent-offset' for the current buffer." (interactive) @@ -692,6 +687,7 @@ Where status can be any of the following symbols: * 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." (save-restriction @@ -746,6 +742,8 @@ START is the buffer position where the sexp starts." (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 (back-to-indentation) @@ -776,8 +774,7 @@ START is the buffer position where the sexp starts." (goto-char context-start) (+ (current-indentation) python-indent-offset)) ;; When after a simple line just use previous line - ;; indentation, in the case current line starts with a - ;; `python-indent-dedenters' de-indent one level. + ;; indentation. (`after-line (let* ((pair (save-excursion (goto-char context-start) @@ -785,25 +782,27 @@ START is the buffer position where the sexp starts." (current-indentation) (python-info-beginning-of-block-p)))) (context-indentation (car pair)) - (after-block-start-p (cdr pair)) + ;; TODO: Separate block enders into its own case. (adjustment - (if (or (save-excursion - (back-to-indentation) - (and - ;; De-indent only when dedenters are not - ;; next to a block start. This allows - ;; one-liner constructs such as: - ;; if condition: print "yay" - ;; else: print "wry" - (not after-block-start-p) - (looking-at (regexp-opt python-indent-dedenters)))) - (save-excursion - (python-util-forward-comment -1) - (python-nav-beginning-of-statement) - (looking-at (regexp-opt python-indent-block-enders)))) + (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 @@ -930,16 +929,25 @@ START is the buffer position where the sexp starts." (defun python-indent-calculate-levels () "Calculate `python-indent-levels' and reset `python-indent-current-level'." - (let* ((indentation (python-indent-calculate-indentation)) - (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 (nreverse python-indent-levels)) - (setq python-indent-current-level (1- (length python-indent-levels))))) + (if (not (python-info-dedenter-statement-p)) + (let* ((indentation (python-indent-calculate-indentation)) + (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)))) + (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'." @@ -988,7 +996,7 @@ equal to (indent-to next-indent) (goto-char starting-pos)) (and follow-indentation-p (back-to-indentation))) - (python-info-closing-block-message)) + (python-info-dedenter-opening-block-message)) (defun python-indent-line-function () "`indent-line-function' for Python mode. @@ -1124,14 +1132,7 @@ the line will be re-indented automatically if needed." (eolp) (not (equal ?: (char-before (1- (point))))) (not (python-syntax-comment-or-string-p))) - (let ((indentation (current-indentation)) - (calculated-indentation (python-indent-calculate-indentation))) - (python-info-closing-block-message) - (when (> indentation calculated-indentation) - (save-excursion - (indent-line-to calculated-indentation) - (when (not (python-info-closing-block-message)) - (indent-line-to indentation))))))))) + (python-indent-line))))) ;;; Navigation @@ -3454,49 +3455,88 @@ parent defun name." (and (python-info-end-of-statement-p) (python-info-statement-ends-block-p))) -(defun python-info-closing-block () - "Return the point of the block the current line closes." - (let ((closing-word (save-excursion - (back-to-indentation) - (current-word))) - (indentation (current-indentation))) - (when (member closing-word python-indent-dedenters) +(define-obsolete-function-alias + 'python-info-closing-block + 'python-info-dedenter-opening-block-position "24.4") + +(defun python-info-dedenter-opening-block-position () + "Return the point of the closest block the current line closes. +Returns nil if point is not on a dedenter statement or no opening +block can be detected. The latter case meaning current file is +likely an invalid python file." + (let ((positions (python-info-dedenter-opening-block-positions)) + (indentation (current-indentation)) + (position)) + (while (and (not position) + positions) (save-excursion - (forward-line -1) - (while (and (> (current-indentation) indentation) - (not (bobp)) - (not (back-to-indentation)) - (forward-line -1))) - (back-to-indentation) - (cond - ((not (equal indentation (current-indentation))) nil) - ((string= closing-word "elif") - (when (member (current-word) '("if" "elif")) - (point-marker))) - ((string= closing-word "else") - (when (member (current-word) '("if" "elif" "except" "for" "while")) - (point-marker))) - ((string= closing-word "except") - (when (member (current-word) '("try")) - (point-marker))) - ((string= closing-word "finally") - (when (member (current-word) '("except" "else")) - (point-marker)))))))) - -(defun python-info-closing-block-message (&optional closing-block-point) - "Message the contents of the block the current line closes. -With optional argument CLOSING-BLOCK-POINT use that instead of -recalculating it calling `python-info-closing-block'." - (let ((point (or closing-block-point (python-info-closing-block)))) + (goto-char (car positions)) + (if (<= (current-indentation) indentation) + (setq position (car positions)) + (setq positions (cdr positions))))) + position)) + +(defun python-info-dedenter-opening-block-positions () + "Return points of blocks the current line may close sorted by closer. +Returns nil if point is not on a dedenter statement or no opening +block can be detected. The latter case meaning current file is +likely an invalid python file." + (save-excursion + (let ((dedenter-pos (python-info-dedenter-statement-p))) + (when dedenter-pos + (goto-char dedenter-pos) + (let* ((pairs '(("elif" "elif" "if") + ("else" "if" "elif" "except" "for" "while") + ("except" "except" "try") + ("finally" "else" "except" "try"))) + (dedenter (match-string-no-properties 0)) + (possible-opening-blocks (cdr (assoc-string dedenter pairs))) + (collected-indentations) + (opening-blocks)) + (catch 'exit + (while (python-nav--syntactically + (lambda () + (re-search-backward (python-rx block-start) nil t)) + #'<) + (let ((indentation (current-indentation))) + (when (and (not (memq indentation collected-indentations)) + (or (not collected-indentations) + (< indentation (apply #'min collected-indentations)))) + (setq collected-indentations + (cons indentation collected-indentations)) + (when (member (match-string-no-properties 0) + possible-opening-blocks) + (setq opening-blocks (cons (point) opening-blocks)))) + (when (zerop indentation) + (throw 'exit nil))))) + ;; sort by closer + (nreverse opening-blocks)))))) + +(define-obsolete-function-alias + 'python-info-closing-block-message + 'python-info-dedenter-opening-block-message "24.4") + +(defun python-info-dedenter-opening-block-message () + "Message the first line of the block the current statement closes." + (let ((point (python-info-dedenter-opening-block-position))) (when point (save-restriction (widen) (message "Closes %s" (save-excursion (goto-char point) - (back-to-indentation) (buffer-substring (point) (line-end-position)))))))) +(defun python-info-dedenter-statement-p () + "Return point if current statement is a dedenter. +Sets `match-data' to the keyword that starts the dedenter +statement." + (save-excursion + (python-nav-beginning-of-statement) + (when (and (not (python-syntax-context-type)) + (looking-at (python-rx dedenter))) + (point)))) + (defun python-info-line-ends-backslash-p (&optional line-number) "Return non-nil if current line ends with backslash. With optional argument LINE-NUMBER, check that line instead." diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el index 1d75411ec1f..3b03ee14c0b 100644 --- a/lisp/vc/log-edit.el +++ b/lisp/vc/log-edit.el @@ -905,44 +905,46 @@ where LOGBUFFER is the name of the ChangeLog buffer, and each ;; that memoizing which is undesired here. (setq change-log-default-name nil) (find-change-log))))) - (with-current-buffer (find-file-noselect changelog-file-name) - (unless (eq major-mode 'change-log-mode) (change-log-mode)) - (goto-char (point-min)) - (if (looking-at "\\s-*\n") (goto-char (match-end 0))) - (if (not (log-edit-changelog-ours-p)) - (list (current-buffer)) - (save-restriction - (log-edit-narrow-changelog) - (goto-char (point-min)) - - ;; Search for the name of FILE relative to the ChangeLog. If that - ;; doesn't occur anywhere, they're not using full relative - ;; filenames in the ChangeLog, so just look for FILE; we'll accept - ;; some false positives. - (let ((pattern (file-relative-name - file (file-name-directory changelog-file-name)))) - (if (or (string= pattern "") - (not (save-excursion - (search-forward pattern nil t)))) - (setq pattern (file-name-nondirectory file))) - - (setq pattern (concat "\\(^\\|[^[:alnum:]]\\)" - (regexp-quote pattern) - "\\($\\|[^[:alnum:]]\\)")) - - (let (texts - (pos (point))) - (while (and (not (eobp)) (re-search-forward pattern nil t)) - (let ((entry (log-edit-changelog-entry))) - (if (< (elt entry 1) (max (1+ pos) (point))) - ;; This is not relevant, actually. - nil - (push entry texts)) - ;; Make sure we make progress. - (setq pos (max (1+ pos) (elt entry 1))) - (goto-char pos))) - - (cons (current-buffer) texts)))))))) + (when (or (find-buffer-visiting changelog-file-name) + (file-exists-p changelog-file-name)) + (with-current-buffer (find-file-noselect changelog-file-name) + (unless (eq major-mode 'change-log-mode) (change-log-mode)) + (goto-char (point-min)) + (if (looking-at "\\s-*\n") (goto-char (match-end 0))) + (if (not (log-edit-changelog-ours-p)) + (list (current-buffer)) + (save-restriction + (log-edit-narrow-changelog) + (goto-char (point-min)) + + ;; Search for the name of FILE relative to the ChangeLog. If that + ;; doesn't occur anywhere, they're not using full relative + ;; filenames in the ChangeLog, so just look for FILE; we'll accept + ;; some false positives. + (let ((pattern (file-relative-name + file (file-name-directory changelog-file-name)))) + (if (or (string= pattern "") + (not (save-excursion + (search-forward pattern nil t)))) + (setq pattern (file-name-nondirectory file))) + + (setq pattern (concat "\\(^\\|[^[:alnum:]]\\)" + (regexp-quote pattern) + "\\($\\|[^[:alnum:]]\\)")) + + (let (texts + (pos (point))) + (while (and (not (eobp)) (re-search-forward pattern nil t)) + (let ((entry (log-edit-changelog-entry))) + (if (< (elt entry 1) (max (1+ pos) (point))) + ;; This is not relevant, actually. + nil + (push entry texts)) + ;; Make sure we make progress. + (setq pos (max (1+ pos) (elt entry 1))) + (goto-char pos))) + + (cons (current-buffer) texts))))))))) (defun log-edit-changelog-insert-entries (buffer beg end &rest files) "Insert the text from BUFFER between BEG and END. diff --git a/lisp/vc/vc-dispatcher.el b/lisp/vc/vc-dispatcher.el index a0efe023a1d..0445891ed55 100644 --- a/lisp/vc/vc-dispatcher.el +++ b/lisp/vc/vc-dispatcher.el @@ -596,7 +596,7 @@ NOT-URGENT means it is ok to continue if the user says not to save." (setq default-directory (buffer-local-value 'default-directory vc-parent-buffer)) (log-edit 'vc-finish-logentry - t + (= (point-min) (point-max)) `((log-edit-listfun . (lambda () ;; FIXME: Should expand the list ;; for directories. |
