;; java-flock.el -- Java reserved words and font lock keywords. ;; Fred White (fwhite@bbn.com) ;; Portions derived from CC mode and from code by Mitch Chapman. ;; In order to accurately pick out method and constructor definitions, ;; some of these regexp's assume Sun's coding conventions, ie, that ;; class names begin with a upper-case letter and method names begin ;; with a lower-case letter. This seemed like the best compromise ;; between accuracy and messiness. ;; Since some of the regexps are generally useful, I've placed them ;; into separate defvar's. ;; Change History: ;; 30May96: First version ;; 12Jun96: Handle constructors, default visibilility, $ in identifiers, etc. ;; Example usage: ;; (add-hook 'java-mode-hook '(lambda () (java-font-lock-mode 'subdued))) (defvar java-primitive-types '("boolean" "char" "byte" "short" "int" "long" "float" "double" "void")) (defvar java-storage-classes '("abstract" "const" "final" "synchronized" "transient" "static" "volatile")) (defvar java-visibility-modifiers '("public" "private" "protected")) ;; Java reserved words, other than those above. (defvar java-reserved-words '("break" "byvalue" "case" "cast" "catch" "class" "continue" "default" "do" "else" "extends" "false" "finally" "for" "future" "generic" "goto" "if" "implements" "import" "inner" "instanceof" "interface" "native" "new" "null" "operator" "outer" "package" "rest" "return" "super" "switch" "this" "throw" "throws" "true" "try" "var" "while")) (defvar java-identifier-regexp "[a-zA-Z$_][a-zA-Z0-9$_.]*") ;; Any java identifier may contain one of these, too. (defvar java-unicode-regexp "\\\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]") (defun java-regexpify-list (list &optional noparens) (concat (if noparens "" "\\(") (mapconcat 'identity list "\\|") (if noparens "" "\\)"))) (defvar java-modifiers-regexp (java-regexpify-list (append java-visibility-modifiers java-storage-classes))) ;;; Class and interface names. (defvar java-class-regexp (concat "^[ \t]*\\(abstract\\|final\\|public\\|[ \t]\\)*\\(class\\|interface\\)[ \t]+\\(" java-identifier-regexp "\\)")) ;; The hand-wave here is to assume that the names of user-defined ;; types (classes) begin with a capital letter, in order to ;; distinguish them from reserved words. Loosening this constraint ;; causes, eg, "return sum(...)", to appear to be a method declaration. (defvar java-class-name-regexp "[A-Z$_][a-zA-Z0-9$_]*") (defvar java-type-regexp (concat "\\(" (java-regexpify-list java-primitive-types t) "\\|" java-class-name-regexp "\\)" "[ \t]*" "\\(\\[\\]\\)*" ; Any number of [] )) ;; Method names, but not constructors. (defvar java-method-regexp (concat "^[ \t]*" "\\(" java-modifiers-regexp "[ \t]+\\)*" "\\(" java-type-regexp "[ \t]+\\)+" "\\(" java-identifier-regexp "\\)[ \t]*(")) ;; Constructors. We can distinguish these from a function call by ;; also assuming that function names begin with a lower-case letter. ;; This also serves to discriminate against reserved words, eg, "if(...". (defvar java-constructor-regexp (concat "^[ \t]*" "\\(" java-modifiers-regexp "[ \t]+\\)*" "\\(" java-class-name-regexp "\\)[ \t]*(")) ;; This will catch a few more constructors, without catching function ;; names, if you use lower-case class names. Assumes function calls ;; are always followed by some operator or semicolon. (defvar java-constructor2-regexp (concat "^[ \t]*" "\\(" java-modifiers-regexp "[ \t]+\\)*" "\\(" java-identifier-regexp "\\)[ \t]*(" "\\([ \t]*\\|" java-type-regexp "[ \t]+" "\\([a-zA-Z$_, \t]\\|\\[\\]\\)*" ; Stuff that can appear in arglist. "\\)" ")" "[ \t]*\\(//.*\\|/\\*.*\\*/\\|\\)[ \t]*$")) ; Trailing comments ;; Static initializers. (defvar java-static-init-regexp "^[ \t]*static[ \t]*[/{\n]") (defvar java-font-lock-keywords nil "Expressions to highlight in Java mode.") (defvar java-font-lock-keywords-1 (list ;; C++ comments. '("//.*" . font-lock-comment-face) ;; Definition names. (list java-class-regexp 3 'font-lock-function-name-face t) (list java-method-regexp 6 'font-lock-function-name-face t) (list java-constructor-regexp 3 'font-lock-function-name-face t) ; (list java-constructor2-regexp 3 'font-lock-function-name-face t) ;; Case clauses. (cons (concat "^[ \t]*case[ \t]+\\([^:]*\\):") 1) (cons "^[ \t]*\\(default\\):" 1))) (defvar java-font-lock-keywords-2 (append java-font-lock-keywords-1 (list ;; Fontify storage classes and primitive types. (cons (concat "\\<" (java-regexpify-list java-storage-classes) "\\>") 'font-lock-type-face) (cons (concat "\\<" (java-regexpify-list java-primitive-types) "\\>") 'font-lock-type-face) ;; Fontify reserved words in font-lock-keyword-face (cons (concat "\\<" (java-regexpify-list (append java-reserved-words java-visibility-modifiers)) "\\>") 1)))) ;; For code which does not use java-font-lock-mode, below. (setq java-font-lock-keywords java-font-lock-keywords-2) (defun java-font-lock-mode (&optional gaudy) "Turn on font lock mode in current buffer for Java. Argument should be one of these symbols, defaulting to 'gaudy: none: turn off font lock mode. minimal: highlight comments. subdued: highlight method names, too. gaudy: highlight reserved words, too." (interactive (list (let ((tab '(("none" . none) ("minimal" . minimal) ("subdued" . subdued) ("gaudy" . gaudy)))) (cdr (assoc (completing-read "How much highlighting: " tab) tab))))) (setq gaudy (or gaudy 'gaudy)) (setq java-font-lock-keywords (cond ((or (eq gaudy 'none) (eq gaudy 'minimal)) nil) ((or (eq gaudy 'subdued) (eq gaudy t)) java-font-lock-keywords-1) ((eq gaudy 'gaudy) java-font-lock-keywords-2))) (cond ((eq gaudy 'none) (font-lock-mode -1)) ((string-match "19.6 Lucid" (emacs-version)) ;; In WinEmacs this sets font-lock-keywords back to nil! (font-lock-mode 1) (setq font-lock-keywords java-font-lock-keywords) (font-lock-fontify-buffer)) (t (setq font-lock-keywords java-font-lock-keywords) (cond ((and (boundp 'font-lock-mode) font-lock-mode) (font-lock-fontify-buffer)) (t (font-lock-mode 1)))))) (provide 'java-flock)