summaryrefslogtreecommitdiff
path: root/lisp/progmodes/perl-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/perl-mode.el')
-rw-r--r--lisp/progmodes/perl-mode.el43
1 files changed, 35 insertions, 8 deletions
diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el
index 81a765d6f0c..f6c4dbed1e2 100644
--- a/lisp/progmodes/perl-mode.el
+++ b/lisp/progmodes/perl-mode.el
@@ -223,7 +223,10 @@
"\\|=>"
"\\|[?:.,;|&*=!~({[]"
"\\|[^-+][-+]" ;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)
(let ((case-fold-search nil))
@@ -248,11 +251,20 @@
;; correctly the \() construct (Bug#11996) as well as references
;; to string values.
("\\(\\\\\\)['`\"($]" (1 (unless (nth 3 (syntax-ppss))
- (string-to-syntax "."))))
+ (string-to-syntax "."))))
+ ;; A "$" in Perl code must escape the next char to protect against
+ ;; misinterpreting Perl's punctuation variables as unbalanced
+ ;; quotes or parens. This is not needed in strings and broken in
+ ;; the special case of "$\"" (Bug#69604). Make "$" a punctuation
+ ;; char in strings.
+ ("\\$" (0 (if (save-excursion
+ (nth 3 (syntax-ppss (match-beginning 0))))
+ (string-to-syntax ".")
+ (string-to-syntax "/"))))
;; Handle funny names like $DB'stop.
("\\$ ?{?\\^?[_[:alpha:]][_[:alnum:]]*\\('\\)[_[:alpha:]]" (1 "_"))
;; format statements
- ("^[ \t]*format.*=[ \t]*\\(\n\\)"
+ (perl--format-regexp
(1 (prog1 "\"" (perl-syntax-propertize-special-constructs end))))
;; Propertize perl prototype chars `$%&*;+@\[]' as punctuation
;; in `sub' arg-specs like `sub myfun ($)' and `sub ($)'. But
@@ -946,6 +958,17 @@ changed by, or (parse-state) if line starts in a quoted string."
(goto-char (- (point-max) pos)))
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 ()
"Move to end of previous line and return non-nil if continued."
;; Statement level. Is it a continuation or a new statement?
@@ -959,12 +982,13 @@ changed by, or (parse-state) if line starts in a quoted string."
(beginning-of-line)
(perl-backward-to-noncomment))
;; Now we get the answer.
- (unless (memq (preceding-char) '(?\; ?\} ?\{))
+ (unless (or (memq (preceding-char) '(?\; ?\} ?\{))
+ (perl--end-of-format-p))
(preceding-char)))
(defun perl-hanging-paren-p ()
"Non-nil if we are right after a hanging parenthesis-like char."
- (and (looking-at "[ \t]*$")
+ (and (looking-at "[ \t]*\\(?:#.*\\)?$")
(save-excursion
(skip-syntax-backward " (") (not (bolp)))))
@@ -999,7 +1023,9 @@ Returns (parse-state) if line starts inside a string."
(state (syntax-ppss))
(containing-sexp (nth 1 state))
;; 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))
(save-excursion
(goto-char (nth 8 state))
@@ -1009,7 +1035,7 @@ Returns (parse-state) if line starts inside a string."
(setq unindentable nil)
(setq containing-sexp (nth 8 state)))
(cond
- (unindentable 'noindent)
+ (unindentable (if format 0 'noindent))
((null containing-sexp) ; Line is at top level.
(skip-chars-forward " \t\f")
(if (memq (following-char)
@@ -1018,7 +1044,8 @@ Returns (parse-state) if line starts inside a string."
;; indent a little if this is a continuation line
(perl-backward-to-noncomment)
(if (or (bobp)
- (memq (preceding-char) '(?\; ?\})))
+ (memq (preceding-char) '(?\; ?\}))
+ (perl--end-of-format-p))
0 perl-continued-statement-offset)))
((/= (char-after containing-sexp) ?{)
;; line is expression, not statement: