;;; Code:
+(defgroup perl nil
+ "Major mode for editing Perl code."
+ :prefix "perl-"
+ :group 'languages)
+
(defvar perl-mode-abbrev-table nil
"Abbrev table in use in perl-mode buffers.")
(define-abbrev-table 'perl-mode-abbrev-table ())
(nil "^sub\\s-+\\([-A-Za-z0-9+_:]+\\)\\(\\s-\\|\n\\)*{" 1 )
;;Variables
("Variables" "^\\([$@%][-A-Za-z0-9+_:]+\\)\\s-*=" 1 )
+ ("Packages" "^package\\s-+\\([-A-Za-z0-9+_:]+\\);" 1 )
)
"Imenu generic expression for Perl mode. See `imenu-generic-expression'.")
-(defvar perl-font-lock-keywords
- (list
-; ("if" "until" "while" "elsif" "else" "unless" "for" "foreach" "continue"
-; "exit" "die" "last" "goto" "next" "redo" "return" "local" "exec")
- (concat "\\<\\("
- "continue\\|die\\|e\\(ls\\(e\\|if\\)\\|x\\(ec\\|it\\)\\)\\|"
- "for\\(\\|each\\)\\|goto\\|if\\|l\\(ast\\|ocal\\)\\|next\\|"
- "re\\(do\\|turn\\)\\|un\\(less\\|til\\)\\|while"
- "\\)\\>")
-; ("#endif" "#else" "#ifdef" "#ifndef" "#if" "#include" "#define" "#undef")
- (cons (concat "#\\(define\\|e\\(lse\\|ndif\\)\\|"
- "i\\(f\\(\\|def\\|ndef\\)\\|nclude\\)\\|undef\\)\\>")
- 'font-lock-reference-face)
- '("^[ \n\t]*sub[ \t]+\\([^ \t{]+\\)[ \t]*[{]" 1 font-lock-function-name-face)
- '("[ \n\t{]*\\(eval\\)[ \n\t(;]" 1 font-lock-function-name-face)
- '("\\(--- .* ---\\|=== .* ===\\)" . font-lock-string-face)
- )
- "Additional expressions to highlight in Perl mode.")
-
-(defvar perl-indent-level 4
- "*Indentation of Perl statements with respect to containing block.")
-(defvar perl-continued-statement-offset 4
- "*Extra indent for lines not starting new statements.")
-(defvar perl-continued-brace-offset -4
+;; Regexps updated with help from Tom Tromey <tromey@cambric.colorado.edu> and
+;; Jim Campbell <jec@murzim.ca.boeing.com>.
+
+(defconst perl-font-lock-keywords-1
+ '(;; What is this for?
+ ;;("\\(--- .* ---\\|=== .* ===\\)" . font-lock-string-face)
+ ;;
+ ;; Fontify preprocessor statements as we do in `c-font-lock-keywords'.
+ ;; Ilya Zakharevich <ilya@math.ohio-state.edu> thinks this is a bad idea.
+ ("^#[ \t]*include[ \t]+\\(<[^>\"\n]+>\\)" 1 font-lock-string-face)
+ ("^#[ \t]*define[ \t]+\\(\\sw+\\)(" 1 font-lock-function-name-face)
+ ("^#[ \t]*if\\>"
+ ("\\<\\(defined\\)\\>[ \t]*(?\\(\\sw+\\)?" nil nil
+ (1 font-lock-constant-face) (2 font-lock-variable-name-face nil t)))
+ ("^#[ \t]*\\(\\sw+\\)\\>[ \t]*\\(\\sw+\\)?"
+ (1 font-lock-constant-face) (2 font-lock-variable-name-face nil t))
+ ;;
+ ;; Fontify function and package names in declarations.
+ ("\\<\\(package\\|sub\\)\\>[ \t]*\\(\\sw+\\)?"
+ (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))
+ ("\\<\\(import\\|no\\|require\\|use\\)\\>[ \t]*\\(\\sw+\\)?"
+ (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)))
+ "Subdued level highlighting for Perl mode.")
+
+(defconst perl-font-lock-keywords-2
+ (append perl-font-lock-keywords-1
+ (list
+ ;;
+ ;; Fontify keywords, except those fontified otherwise.
+; (make-regexp '("if" "until" "while" "elsif" "else" "unless" "do" "dump"
+; "for" "foreach" "exit" "die"
+; "BEGIN" "END" "return" "exec" "eval"))
+ (concat "\\<\\("
+ "BEGIN\\|END\\|d\\(ie\\|o\\|ump\\)\\|"
+ "e\\(ls\\(e\\|if\\)\\|val\\|x\\(ec\\|it\\)\\)\\|"
+ "for\\(\\|each\\)\\|if\\|return\\|un\\(less\\|til\\)\\|while"
+ "\\)\\>")
+ ;;
+ ;; Fontify local and my keywords as types.
+ '("\\<\\(local\\|my\\)\\>" . font-lock-type-face)
+ ;;
+ ;; Fontify function, variable and file name references.
+ '("&\\(\\sw+\\)" 1 font-lock-function-name-face)
+ ;; Additionally underline non-scalar variables. Maybe this is a bad idea.
+ ;;'("[$@%*][#{]?\\(\\sw+\\)" 1 font-lock-variable-name-face)
+ '("[$*]{?\\(\\sw+\\)" 1 font-lock-variable-name-face)
+ '("\\([@%]\\|\\$#\\)\\(\\sw+\\)"
+ (2 (cons font-lock-variable-name-face '(underline))))
+ '("<\\(\\sw+\\)>" 1 font-lock-constant-face)
+ ;;
+ ;; Fontify keywords with/and labels as we do in `c++-font-lock-keywords'.
+ '("\\<\\(continue\\|goto\\|last\\|next\\|redo\\)\\>[ \t]*\\(\\sw+\\)?"
+ (1 font-lock-keyword-face) (2 font-lock-constant-face nil t))
+ '("^[ \t]*\\(\\sw+\\)[ \t]*:[^:]" 1 font-lock-constant-face)))
+ "Gaudy level highlighting for Perl mode.")
+
+(defvar perl-font-lock-keywords perl-font-lock-keywords-1
+ "Default expressions to highlight in Perl mode.")
+
+
+(defcustom perl-indent-level 4
+ "*Indentation of Perl statements with respect to containing block."
+ :type 'integer
+ :group 'perl)
+(defcustom perl-continued-statement-offset 4
+ "*Extra indent for lines not starting new statements."
+ :type 'integer
+ :group 'perl)
+(defcustom perl-continued-brace-offset -4
"*Extra indent for substatements that start with open-braces.
-This is in addition to `perl-continued-statement-offset'.")
-(defvar perl-brace-offset 0
- "*Extra indentation for braces, compared with other text in same context.")
-(defvar perl-brace-imaginary-offset 0
- "*Imagined indentation of an open brace that actually follows a statement.")
-(defvar perl-label-offset -2
- "*Offset of Perl label lines relative to usual indentation.")
-
-(defvar perl-tab-always-indent t
+This is in addition to `perl-continued-statement-offset'."
+ :type 'integer
+ :group 'perl)
+(defcustom perl-brace-offset 0
+ "*Extra indentation for braces, compared with other text in same context."
+ :type 'integer
+ :group 'perl)
+(defcustom perl-brace-imaginary-offset 0
+ "*Imagined indentation of an open brace that actually follows a statement."
+ :type 'integer
+ :group 'perl)
+(defcustom perl-label-offset -2
+ "*Offset of Perl label lines relative to usual indentation."
+ :type 'integer
+ :group 'perl)
+
+(defcustom perl-tab-always-indent t
"*Non-nil means TAB in Perl mode always indents the current line.
Otherwise it inserts a tab character if you type it past the first
-nonwhite character on the line.")
+nonwhite character on the line."
+ :type 'boolean
+ :group 'perl)
;; I changed the default to nil for consistency with general Emacs
;; conventions -- rms.
-(defvar perl-tab-to-comment nil
+(defcustom perl-tab-to-comment nil
"*Non-nil means TAB moves to eol or makes a comment in some cases.
For lines which don't need indenting, TAB either indents an
existing comment, moves to end-of-line, or if at end-of-line already,
-create a new comment.")
-
-(defvar perl-nochange ";?#\\|\f\\|\\s(\\|\\(\\w\\|\\s_\\)+:"
- "*Lines starting with this regular expression are not auto-indented.")
+create a new comment."
+ :type 'boolean
+ :group 'perl)
+
+(defcustom perl-nochange ";?#\\|\f\\|\\s(\\|\\(\\w\\|\\s_\\)+:"
+ "*Lines starting with this regular expression are not auto-indented."
+ :type 'regexp
+ :group 'perl)
\f
;;;###autoload
(defun perl-mode ()
(setq comment-indent-function 'perl-comment-indent)
(make-local-variable 'parse-sexp-ignore-comments)
(setq parse-sexp-ignore-comments t)
+ ;; Tell font-lock.el how to handle Perl.
(make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(perl-font-lock-keywords))
+ (setq font-lock-defaults '((perl-font-lock-keywords
+ perl-font-lock-keywords-1
+ perl-font-lock-keywords-2)
+ nil nil ((?\_ . "w"))))
;; Tell imenu how to handle Perl.
(make-local-variable 'imenu-generic-expression)
(setq imenu-generic-expression perl-imenu-generic-expression)
+ (setq imenu-case-fold-search nil)
(run-hooks 'perl-mode-hook))
\f
;; This is used by indent-for-comment
(save-excursion
(beginning-of-line)
(and (not ; eliminate comments quickly
- (re-search-forward comment-start-skip insertpos t))
+ (and comment-start-skip
+ (re-search-forward comment-start-skip insertpos t)) )
(or (/= last-command-char ?:)
;; Colon is special only after a label ....
(looking-at "\\s-*\\(\\w\\|\\s_\\)+$"))
(if (= oldpnt eol) ; no comment, create one?
(indent-for-comment))
(beginning-of-line)
- (if (re-search-forward comment-start-skip eol 'move)
+ (if (and comment-start-skip
+ (re-search-forward comment-start-skip eol 'move))
(if (eolp)
(progn ; kill existing comment
(goto-char (match-beginning 0))
;; line is expression, not statement:
;; indent to just after the surrounding open.
(goto-char (1+ containing-sexp))
+ (skip-chars-forward " \t")
(current-column))
(t
;; Statement level. Is it a continuation or a new statement?
(while (not stop)
(setq opoint (point))
(beginning-of-line)
- (if (re-search-forward comment-start-skip opoint 'move 1)
+ (if (and comment-start-skip
+ (re-search-forward comment-start-skip opoint 'move 1))
(progn (goto-char (match-end 1))
(skip-chars-forward ";")))
(skip-chars-backward " \t\f")
(listp delta)
(and (/= 0 delta)
(= (- (current-indentation) delta) comment-column)))
- (if (re-search-forward comment-start-skip eol t)
+ (if (and comment-start-skip
+ (re-search-forward comment-start-skip eol t))
(indent-for-comment))))) ; indent existing comment
(forward-line 1))
(goto-char (marker-position oldpnt))
(perl-beginning-of-function)
(backward-paragraph))
-;;;;;;;; That's all, folks! ;;;;;;;;;
+(provide 'perl-mode)
+
+;;; perl-mode.el ends here