mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-24 10:38:38 +00:00
Fix indentation in perl-mode (Bug#35925)
* lisp/progmodes/perl-mode.el (perl--format-regexp): New defconst. (perl--end-of-format-p): New function. (perl-continuation-line-p): Use it. (perl-calculate-indent): Use it. Make the lines of the formlist stay at column 0. * test/lisp/progmodes/cperl-mode-resources/cperl-bug-35925.pl: New test file. * test/lisp/progmodes/cperl-mode-tests.el (cperl-test-bug-35925): New test.
This commit is contained in:
parent
6dd1565fcf
commit
7caa3f5499
@ -223,7 +223,10 @@
|
|||||||
"\\|=>"
|
"\\|=>"
|
||||||
"\\|[?:.,;|&*=!~({[]"
|
"\\|[?:.,;|&*=!~({[]"
|
||||||
"\\|[^-+][-+]" ;Bug#42168: `+' is intro but `++' isn't!
|
"\\|[^-+][-+]" ;Bug#42168: `+' is intro but `++' isn't!
|
||||||
"\\|\\(^\\)\\)[ \t\n]*")))
|
"\\|\\(^\\)\\)[ \t\n]*"))
|
||||||
|
|
||||||
|
(defconst perl--format-regexp "^[ \t]*format.*=[ \t]*\\(\n\\)"
|
||||||
|
"Regexp to match the start of a format declaration."))
|
||||||
|
|
||||||
(defun perl-syntax-propertize-function (start end)
|
(defun perl-syntax-propertize-function (start end)
|
||||||
(let ((case-fold-search nil))
|
(let ((case-fold-search nil))
|
||||||
@ -252,7 +255,7 @@
|
|||||||
;; Handle funny names like $DB'stop.
|
;; Handle funny names like $DB'stop.
|
||||||
("\\$ ?{?\\^?[_[:alpha:]][_[:alnum:]]*\\('\\)[_[:alpha:]]" (1 "_"))
|
("\\$ ?{?\\^?[_[:alpha:]][_[:alnum:]]*\\('\\)[_[:alpha:]]" (1 "_"))
|
||||||
;; format statements
|
;; format statements
|
||||||
("^[ \t]*format.*=[ \t]*\\(\n\\)"
|
(perl--format-regexp
|
||||||
(1 (prog1 "\"" (perl-syntax-propertize-special-constructs end))))
|
(1 (prog1 "\"" (perl-syntax-propertize-special-constructs end))))
|
||||||
;; Propertize perl prototype chars `$%&*;+@\[]' as punctuation
|
;; Propertize perl prototype chars `$%&*;+@\[]' as punctuation
|
||||||
;; in `sub' arg-specs like `sub myfun ($)' and `sub ($)'. But
|
;; in `sub' arg-specs like `sub myfun ($)' and `sub ($)'. But
|
||||||
@ -946,6 +949,17 @@ changed by, or (parse-state) if line starts in a quoted string."
|
|||||||
(goto-char (- (point-max) pos)))
|
(goto-char (- (point-max) pos)))
|
||||||
shift-amt))
|
shift-amt))
|
||||||
|
|
||||||
|
(defun perl--end-of-format-p ()
|
||||||
|
"Non-nil if point is at the end of a format declaration, skipping whitespace."
|
||||||
|
(save-excursion
|
||||||
|
(skip-chars-backward " \t\n")
|
||||||
|
(beginning-of-line)
|
||||||
|
(when-let ((comm (and (looking-at "^\\.$")
|
||||||
|
(nth 8 (syntax-ppss)))))
|
||||||
|
(goto-char comm)
|
||||||
|
(beginning-of-line)
|
||||||
|
(looking-at perl--format-regexp))))
|
||||||
|
|
||||||
(defun perl-continuation-line-p ()
|
(defun perl-continuation-line-p ()
|
||||||
"Move to end of previous line and return non-nil if continued."
|
"Move to end of previous line and return non-nil if continued."
|
||||||
;; Statement level. Is it a continuation or a new statement?
|
;; Statement level. Is it a continuation or a new statement?
|
||||||
@ -959,7 +973,8 @@ changed by, or (parse-state) if line starts in a quoted string."
|
|||||||
(beginning-of-line)
|
(beginning-of-line)
|
||||||
(perl-backward-to-noncomment))
|
(perl-backward-to-noncomment))
|
||||||
;; Now we get the answer.
|
;; Now we get the answer.
|
||||||
(unless (memq (preceding-char) '(?\; ?\} ?\{))
|
(unless (or (memq (preceding-char) '(?\; ?\} ?\{))
|
||||||
|
(perl--end-of-format-p))
|
||||||
(preceding-char)))
|
(preceding-char)))
|
||||||
|
|
||||||
(defun perl-hanging-paren-p ()
|
(defun perl-hanging-paren-p ()
|
||||||
@ -999,7 +1014,9 @@ Returns (parse-state) if line starts inside a string."
|
|||||||
(state (syntax-ppss))
|
(state (syntax-ppss))
|
||||||
(containing-sexp (nth 1 state))
|
(containing-sexp (nth 1 state))
|
||||||
;; Don't auto-indent in a quoted string or a here-document.
|
;; Don't auto-indent in a quoted string or a here-document.
|
||||||
(unindentable (or (nth 3 state) (eq 2 (nth 7 state)))))
|
(unindentable (or (nth 3 state) (eq 2 (nth 7 state))))
|
||||||
|
(format (and (nth 3 state)
|
||||||
|
(char-equal (nth 3 state) ?\n))))
|
||||||
(when (and (eq t (nth 3 state))
|
(when (and (eq t (nth 3 state))
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(goto-char (nth 8 state))
|
(goto-char (nth 8 state))
|
||||||
@ -1009,7 +1026,7 @@ Returns (parse-state) if line starts inside a string."
|
|||||||
(setq unindentable nil)
|
(setq unindentable nil)
|
||||||
(setq containing-sexp (nth 8 state)))
|
(setq containing-sexp (nth 8 state)))
|
||||||
(cond
|
(cond
|
||||||
(unindentable 'noindent)
|
(unindentable (if format 0 'noindent))
|
||||||
((null containing-sexp) ; Line is at top level.
|
((null containing-sexp) ; Line is at top level.
|
||||||
(skip-chars-forward " \t\f")
|
(skip-chars-forward " \t\f")
|
||||||
(if (memq (following-char)
|
(if (memq (following-char)
|
||||||
@ -1018,7 +1035,8 @@ Returns (parse-state) if line starts inside a string."
|
|||||||
;; indent a little if this is a continuation line
|
;; indent a little if this is a continuation line
|
||||||
(perl-backward-to-noncomment)
|
(perl-backward-to-noncomment)
|
||||||
(if (or (bobp)
|
(if (or (bobp)
|
||||||
(memq (preceding-char) '(?\; ?\})))
|
(memq (preceding-char) '(?\; ?\}))
|
||||||
|
(perl--end-of-format-p))
|
||||||
0 perl-continued-statement-offset)))
|
0 perl-continued-statement-offset)))
|
||||||
((/= (char-after containing-sexp) ?{)
|
((/= (char-after containing-sexp) ?{)
|
||||||
;; line is expression, not statement:
|
;; line is expression, not statement:
|
||||||
|
36
test/lisp/progmodes/cperl-mode-resources/cperl-bug-35925.pl
Normal file
36
test/lisp/progmodes/cperl-mode-resources/cperl-bug-35925.pl
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# This resource file can be run with cperl--run-testcases from
|
||||||
|
# cperl-tests.el and works with both perl-mode and cperl-mode.
|
||||||
|
|
||||||
|
# -------- Bug#35925: input -------
|
||||||
|
format FH =
|
||||||
|
@### @.### @###
|
||||||
|
42, 3.1415, 0
|
||||||
|
.
|
||||||
|
write FH;
|
||||||
|
|
||||||
|
# -------- Bug#35925: expected output -------
|
||||||
|
format FH =
|
||||||
|
@### @.### @###
|
||||||
|
42, 3.1415, 0
|
||||||
|
.
|
||||||
|
write FH;
|
||||||
|
|
||||||
|
# -------- Bug#35925: end -------
|
||||||
|
|
||||||
|
# -------- format not as top-level: input -------
|
||||||
|
foo: {
|
||||||
|
format STDOUT =
|
||||||
|
^<<<<
|
||||||
|
$foo
|
||||||
|
.
|
||||||
|
write;
|
||||||
|
}
|
||||||
|
# -------- format not as top-level: expected output -------
|
||||||
|
foo: {
|
||||||
|
format STDOUT =
|
||||||
|
^<<<<
|
||||||
|
$foo
|
||||||
|
.
|
||||||
|
write;
|
||||||
|
}
|
||||||
|
# -------- format not as top-level: end -------
|
@ -1143,6 +1143,20 @@ Perl is not Lisp: An open paren in column 0 does not start a function."
|
|||||||
(cperl-indent-command)
|
(cperl-indent-command)
|
||||||
(forward-line 1))))
|
(forward-line 1))))
|
||||||
|
|
||||||
|
(ert-deftest cperl-test-bug-35925 ()
|
||||||
|
"Check that indentation is correct after a terminating format declaration."
|
||||||
|
(cperl-set-style "PBP") ; Make cperl-mode use the same settings as perl-mode.
|
||||||
|
(cperl--run-test-cases
|
||||||
|
(ert-resource-file "cperl-bug-35925.pl")
|
||||||
|
(let ((tab-function
|
||||||
|
(if (equal cperl-test-mode 'perl-mode)
|
||||||
|
#'indent-for-tab-command
|
||||||
|
#'cperl-indent-command)))
|
||||||
|
(goto-char (point-max))
|
||||||
|
(forward-line -2)
|
||||||
|
(funcall tab-function)))
|
||||||
|
(cperl-set-style-back))
|
||||||
|
|
||||||
(ert-deftest cperl-test-bug-37127 ()
|
(ert-deftest cperl-test-bug-37127 ()
|
||||||
"Verify that closing a paren in a regex goes without a message.
|
"Verify that closing a paren in a regex goes without a message.
|
||||||
Also check that the message is issued if the regex terminator is
|
Also check that the message is issued if the regex terminator is
|
||||||
|
Loading…
Reference in New Issue
Block a user