mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-06 06:20:55 -08:00
cperl-mode.el: Support syntax of Perl version 5.42
* lisp/progmodes/cperl-mode.el (cperl--sub-name-generated-rx): Simplify captures to account for the :writer attribute. Parsing is done later. (cperl-imenu-sub-keywords): Remove attributes which generate subs (cperl-imenu--create-perl-index): Analyze field declarations for autogenerated methods (cperl-init-faces): Add "all" and "any" to the list of functions (cperl-short-docs): Add short docs for "all" and "any" * test/lisp/progmodes/cperl-mode-tests.el (cperl-test-autogenerated-reader-rx): Adjust for modified rx form due to ":writer" support (cperl-test-imenu-index): Add tests for autogenerated writer accessors (in grammar.pl) * test/lisp/progmodes/cperl-mode-resources/grammar.pl: Add code samples for ":writer" * etc/NEWS: Announce that CPerl mode supports Perl 5.42.
This commit is contained in:
parent
62fba3a723
commit
cef4302d30
4 changed files with 67 additions and 29 deletions
7
etc/NEWS
7
etc/NEWS
|
|
@ -2460,6 +2460,13 @@ The new commands 'newsticker-hide-old-feed-header' and
|
|||
respectively, hide and show the headers of feeds whose items are all old
|
||||
or obsolete.
|
||||
|
||||
** CPerl mode
|
||||
|
||||
*** Syntax of Perl up to version 5.42 is supported.
|
||||
|
||||
CPerl mode creates imenu entries for :writer-generated accessors and
|
||||
recognizes the new functions "all" and "any".
|
||||
|
||||
|
||||
* New Modes and Packages in Emacs 31.1
|
||||
|
||||
|
|
|
|||
|
|
@ -1465,28 +1465,17 @@ the subroutine name.")
|
|||
`(sequence symbol-start
|
||||
(optional (group-n 3 unmatchable))
|
||||
;; autogenerated methods are not lexicals, so enforce the
|
||||
;; first capture group to be nil
|
||||
"field"
|
||||
;; third capture group to be nil
|
||||
(group-n 1 "field")
|
||||
,cperl--ws+-rx
|
||||
(or
|
||||
(sequence (in "$%@")
|
||||
(group-n 2 ,cperl--basic-identifier-rx)
|
||||
(1+ (not (in ";={")))
|
||||
":"
|
||||
(group-n 1 "reader")
|
||||
(not "("))
|
||||
(sequence ,cperl--basic-variable-rx
|
||||
(1+ (not (in ";={")))
|
||||
":"
|
||||
(group-n 1 "reader")
|
||||
"("
|
||||
(group-n 2 ,cperl--basic-identifier-rx)
|
||||
")")))
|
||||
,cperl--basic-variable-rx
|
||||
,cperl--ws+-rx
|
||||
(group-n 2 ,cperl--attribute-list-rx))
|
||||
"A regular expression to capture autogenerated reader methods.
|
||||
The name of the method is either the field name without its sigil, or
|
||||
given in parentheses after the \":reader\" keyword.")
|
||||
;; I don't dare to think about :writer where the generated name does
|
||||
;; not even occur in the text.
|
||||
given in parentheses after the \":reader\" or \":writer\" keyword. More
|
||||
than one attribute can be present: The match will be parsed in an extra
|
||||
step.")
|
||||
|
||||
(defconst cperl--block-declaration-rx
|
||||
`(sequence
|
||||
|
|
@ -6106,8 +6095,7 @@ use, it indicates a recursive call."
|
|||
;; The following lists are used for categorizing the entries found by
|
||||
;; `cperl-imenu--create-perl-index'.
|
||||
(defvar cperl-imenu-package-keywords '("package" "class" "role"))
|
||||
(defvar cperl-imenu-sub-keywords '("sub" "method" "function" "fun"
|
||||
"reader")) ;; for autogenerated
|
||||
(defvar cperl-imenu-sub-keywords '("sub" "method" "function" "fun"))
|
||||
(defvar cperl-imenu-pod-keywords '("=head"))
|
||||
|
||||
(defun cperl-imenu--create-perl-index ()
|
||||
|
|
@ -6175,6 +6163,38 @@ comment, or POD."
|
|||
(push index index-alist)
|
||||
(push index index-sub-alist)
|
||||
(push index index-unsorted-alist))))
|
||||
((string-equal entry-type "field")
|
||||
(unless (nth 4 state) ; skip if in a comment
|
||||
(let ((limit (match-end 0))
|
||||
field-name)
|
||||
(save-excursion
|
||||
(goto-char (match-end 1))
|
||||
(re-search-forward
|
||||
(rx (in "$%@")
|
||||
(group-n 1 (eval cperl--basic-identifier-rx)))
|
||||
limit t)
|
||||
(setq field-name (match-string-no-properties 1))
|
||||
(when field-name
|
||||
(while (re-search-forward
|
||||
(rx (group-n 1 (eval cperl--basic-identifier-rx))
|
||||
(optional
|
||||
(sequence
|
||||
"("
|
||||
(group-n 2
|
||||
(eval cperl--basic-identifier-rx))
|
||||
")")))
|
||||
limit t)
|
||||
(when (member (match-string 1) '("reader" "writer"))
|
||||
(let* ((name (or (match-string 2)
|
||||
(if (string-equal
|
||||
(match-string 1) "reader")
|
||||
field-name)
|
||||
(concat "set_" field-name)))
|
||||
(qname (concat current-namespace "->" name))
|
||||
(index (cons qname (match-beginning 1))))
|
||||
(push index index-alist)
|
||||
(push index index-sub-alist)
|
||||
(push index index-unsorted-alist)))))))))
|
||||
((member entry-type cperl-imenu-pod-keywords) ; POD heading
|
||||
(when (get-text-property (match-beginning 2) 'in-pod)
|
||||
(setq name (concat (make-string
|
||||
|
|
@ -6461,7 +6481,9 @@ functions (which they are not). Inherits from `default'.")
|
|||
"\\(^\\|[^$@%&\\]\\)\\<\\("
|
||||
(regexp-opt
|
||||
'("AUTOLOAD" "BEGIN" "CHECK" "DESTROY" "END" "INIT" "UNITCHECK"
|
||||
"__END__" "__DATA__" "break" "catch" "chomp" "chop" "default"
|
||||
"__END__" "__DATA__"
|
||||
"all" "any"
|
||||
"break" "catch" "chomp" "chop" "default"
|
||||
"defined" "delete" "do" "each" "else" "elsif" "eval"
|
||||
"evalbytes" "exists" "finally" "for" "foreach" "format" "given"
|
||||
"goto" "grep" "if" "keys" "last" "local" "m" "map" "my" "next"
|
||||
|
|
@ -8295,6 +8317,8 @@ DATA Input filehandle for what follows after __END__ or __DATA__.
|
|||
abs [ EXPR ] absolute value function
|
||||
accept(NEWSOCKET,GENERICSOCKET) accept an incoming socket connect
|
||||
alarm(SECONDS) schedule a SIGALRM
|
||||
all {BLOCK} LIST true if BLOCK is true for all elements in LIST
|
||||
any {BLOCK} LIST true if BLOCK is true for any element in LIST
|
||||
async(SUB NAME {}|SUB {}) Mark function as potentially asynchronous
|
||||
atan2(X,Y) arctangent of Y/X in the range -PI to PI
|
||||
await(ASYNCEXPR) Yield result of Future
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use 5.024;
|
||||
use 5.042;
|
||||
use strict;
|
||||
use warnings;
|
||||
use utf8;
|
||||
|
|
@ -204,9 +204,11 @@ method-generator for classes are available with Perl 5.40.
|
|||
|
||||
=cut
|
||||
|
||||
class With::Readers {
|
||||
class With::Accessors {
|
||||
field $simple;
|
||||
field $auto_reader :reader;
|
||||
field $named_reader :reader(named);
|
||||
field $auto_writer :writer = 0;
|
||||
field $auto_all :param :reader(read_all) :writer;
|
||||
}
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -637,14 +637,16 @@ Also includes valid cases with whitespace in strange places."
|
|||
"field $name :param :reader;"
|
||||
"field $field :param :reader(name);"
|
||||
"field $field :reader(name) :param;"
|
||||
"field $field :reader(name) = 'value';")))
|
||||
"field $field :reader(name) = 'value';"
|
||||
"field $field :writer = 'value';"
|
||||
"field $field :writer(write_f)")))
|
||||
(dolist (code code-examples)
|
||||
(with-temp-buffer
|
||||
(insert code)
|
||||
(goto-char (point-min))
|
||||
(search-forward-regexp (rx (eval cperl--sub-name-generated-rx)))
|
||||
(should (string= (match-string 1) "reader"))
|
||||
(should (string= (match-string 2) "name"))))))
|
||||
(should (string= (match-string 1) "field"))
|
||||
(should (string-match ":\\(reader\\|writer\\)" (match-string 2)))))))
|
||||
|
||||
;;; Test unicode identifier in various places
|
||||
|
||||
|
|
@ -973,8 +975,11 @@ created by CPerl mode, so skip it for Perl mode."
|
|||
"Erdős::Number::erdős_number"
|
||||
"Class::Class::init"
|
||||
"Class::Inner::init_again"
|
||||
"With::Readers::auto_reader"
|
||||
"With::Readers::named")))
|
||||
"With::Accessors->auto_reader"
|
||||
"With::Accessors->named"
|
||||
"With::Accessors->set_auto_writer"
|
||||
"With::Accessors->read_all"
|
||||
"With::Accessors->set_auto_all")))
|
||||
(dolist (sub expected)
|
||||
(should (assoc-string sub index))))
|
||||
(should-not (assoc-string "_false" index)))))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue