vala-mode.el
changeset 22 a7906973ceb5
equal deleted inserted replaced
21:a48713acd5c1 22:a7906973ceb5
       
     1 ;;; vala-mode.el --- Vala mode derived mode
       
     2 
       
     3 ;; Author:     2005 Dylan R. E. Moonfire
       
     4 ;;	       2008 Étienne BERSAC
       
     5 ;; Maintainer: Étienne BERSAC <[email protected]>
       
     6 ;; Created:    2008 May the 4th
       
     7 ;; Modified:   May 2008
       
     8 ;; Version:    0.1
       
     9 ;; Keywords:   vala languages oop
       
    10 
       
    11 ;; This program is free software; you can redistribute it and/or modify
       
    12 ;; it under the terms of the GNU General Public License as published by
       
    13 ;; the Free Software Foundation; either version 2 of the License, or
       
    14 ;; (at your option) any later version.
       
    15 ;; 
       
    16 ;; This program is distributed in the hope that it will be useful,
       
    17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    19 ;; GNU General Public License for more details.
       
    20 ;; 
       
    21 ;; You should have received a copy of the GNU General Public License
       
    22 ;; along with this program; see the file COPYING.  If not, write to
       
    23 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    24 ;; Boston, MA 02111-1307, USA.
       
    25 
       
    26 ;;; Commentary:
       
    27 ;;
       
    28 ;;    See http://live.gnome.org/Vala for details about Vala language.
       
    29 ;;
       
    30 ;;    This is a separate mode to implement the Vala constructs and
       
    31 ;;    font-locking. It is mostly the csharp-mode from
       
    32 ;;    http://mfgames.com/linux/csharp-mode with vala specific keywords
       
    33 ;;    and filename suffixes.
       
    34 ;;
       
    35 ;;    Note: The interface used in this file requires CC Mode 5.30 or
       
    36 ;;    later.
       
    37 
       
    38 ;;; .emacs (don't put in (require 'vala-mode))
       
    39 ;; (autoload 'vala-mode "vala-mode" "Major mode for editing Vala code." t)
       
    40 ;; (setq auto-mode-alist
       
    41 ;;    (append '(("\\.vala$" . vala-mode)) auto-mode-alist))
       
    42 
       
    43 ;;; Versions:
       
    44 ;;
       
    45 ;;	0.1	: Initial version based on csharp-mode
       
    46 ;;
       
    47 
       
    48 ;; This is a copy of the function in cc-mode which is used to handle
       
    49 ;; the eval-when-compile which is needed during other times.
       
    50 (defun c-filter-ops (ops opgroup-filter op-filter &optional xlate)
       
    51   ;; See cc-langs.el, a direct copy.
       
    52   (unless (listp (car-safe ops))
       
    53     (setq ops (list ops)))
       
    54   (cond ((eq opgroup-filter t)
       
    55 	 (setq opgroup-filter (lambda (opgroup) t)))
       
    56 	((not (functionp opgroup-filter))
       
    57 	 (setq opgroup-filter `(lambda (opgroup)
       
    58 				 (memq opgroup ',opgroup-filter)))))
       
    59   (cond ((eq op-filter t)
       
    60 	 (setq op-filter (lambda (op) t)))
       
    61 	((stringp op-filter)
       
    62 	 (setq op-filter `(lambda (op)
       
    63 			    (string-match ,op-filter op)))))
       
    64   (unless xlate
       
    65     (setq xlate 'identity))
       
    66   (c-with-syntax-table (c-lang-const c-mode-syntax-table)
       
    67     (delete-duplicates
       
    68      (mapcan (lambda (opgroup)
       
    69 	       (when (if (symbolp (car opgroup))
       
    70 			 (when (funcall opgroup-filter (car opgroup))
       
    71 			   (setq opgroup (cdr opgroup))
       
    72 			   t)
       
    73 		       t)
       
    74 		 (mapcan (lambda (op)
       
    75 			   (when (funcall op-filter op)
       
    76 			     (let ((res (funcall xlate op)))
       
    77 			       (if (listp res) res (list res)))))
       
    78 			 opgroup)))
       
    79 	     ops)
       
    80      :test 'equal)))
       
    81 
       
    82 ;; This inserts the bulk of the code.
       
    83 (require 'cc-mode)
       
    84 
       
    85 ;; These are only required at compile time to get the sources for the
       
    86 ;; language constants.  (The cc-fonts require and the font-lock
       
    87 ;; related constants could additionally be put inside an
       
    88 ;; (eval-after-load "font-lock" ...) but then some trickery is
       
    89 ;; necessary to get them compiled.)
       
    90 (eval-when-compile
       
    91   (let ((load-path
       
    92 	 (if (and (boundp 'byte-compile-dest-file)
       
    93 		  (stringp byte-compile-dest-file))
       
    94 	     (cons (file-name-directory byte-compile-dest-file) load-path)
       
    95 	   load-path)))
       
    96     (load "cc-mode" nil t)
       
    97     (load "cc-fonts" nil t)
       
    98     (load "cc-langs" nil t)))
       
    99 
       
   100 (eval-and-compile
       
   101   ;; Make our mode known to the language constant system.  Use Java
       
   102   ;; mode as the fallback for the constants we don't change here.
       
   103   ;; This needs to be done also at compile time since the language
       
   104   ;; constants are evaluated then.
       
   105   (c-add-language 'vala-mode 'java-mode))
       
   106 
       
   107 ;; Java uses a series of regexes to change the font-lock for class
       
   108 ;; references. The problem comes in because Java uses Pascal (leading
       
   109 ;; space in names, SomeClass) for class and package names, but
       
   110 ;; Camel-casing (initial lowercase, upper case in words,
       
   111 ;; i.e. someVariable) for variables.
       
   112 ;;(error (byte-compile-dest-file))
       
   113 ;;(error (c-get-current-file))
       
   114 (c-lang-defconst c-opt-after-id-concat-key
       
   115   vala (if (c-lang-const c-opt-identifier-concat-key)
       
   116 	   (c-lang-const c-symbol-start)))
       
   117 
       
   118 (c-lang-defconst c-basic-matchers-before
       
   119   vala `(
       
   120 ;;;; Font-lock the attributes by searching for the
       
   121 ;;;; appropriate regex and marking it as TODO.
       
   122 	 ;;,`(,(concat "\\(" vala-attribute-regex "\\)")
       
   123 	 ;;   0 font-lock-function-name-face)	   
       
   124 
       
   125 	 ;; Put a warning face on the opener of unclosed strings that
       
   126 	 ;; can't span lines.  Later font
       
   127 	 ;; lock packages have a `font-lock-syntactic-face-function' for
       
   128 	 ;; this, but it doesn't give the control we want since any
       
   129 	 ;; fontification done inside the function will be
       
   130 	 ;; unconditionally overridden.
       
   131 	 ,(c-make-font-lock-search-function
       
   132 	   ;; Match a char before the string starter to make
       
   133 	   ;; `c-skip-comments-and-strings' work correctly.
       
   134 	   (concat ".\\(" c-string-limit-regexp "\\)")
       
   135 	   '((c-font-lock-invalid-string)))
       
   136 	   
       
   137 	 ;; Fontify keyword constants.
       
   138 	 ,@(when (c-lang-const c-constant-kwds)
       
   139 	     (let ((re (c-make-keywords-re nil
       
   140 			 (c-lang-const c-constant-kwds))))
       
   141 	       `((eval . (list ,(concat "\\<\\(" re "\\)\\>")
       
   142 			       1 c-constant-face-name)))))
       
   143 	   
       
   144 	 ;; Fontify all keywords except the primitive types.
       
   145 	 ,`(,(concat "\\<" (c-lang-const c-regular-keywords-regexp))
       
   146 	    1 font-lock-keyword-face)
       
   147 
       
   148 	 ;; Fontify leading identifiers in fully
       
   149 	 ;; qualified names like "Foo.Bar".
       
   150 	 ,@(when (c-lang-const c-opt-identifier-concat-key)
       
   151 	     `((,(byte-compile
       
   152 		  `(lambda (limit)
       
   153 		     (while (re-search-forward
       
   154 			     ,(concat "\\(\\<" ; 1
       
   155 				      "\\(" (c-lang-const c-symbol-key)
       
   156 				      "\\)" ; 2
       
   157 				      "[ \t\n\r\f\v]*"
       
   158 				      (c-lang-const
       
   159 				       c-opt-identifier-concat-key)
       
   160 				      "[ \t\n\r\f\v]*"
       
   161 				      "\\)"
       
   162 				      "\\("
       
   163 				      (c-lang-const
       
   164 				       c-opt-after-id-concat-key)
       
   165 				      "\\)")
       
   166 			     limit t)
       
   167 		       (unless (progn
       
   168 				 (goto-char (match-beginning 0))
       
   169 				 (c-skip-comments-and-strings limit))
       
   170 			 (or (get-text-property (match-beginning 2) 'face)
       
   171 			     (c-put-font-lock-face (match-beginning 2)
       
   172 						   (match-end 2)
       
   173 						   c-reference-face-name))
       
   174 			 (goto-char (match-end 1)))))))))
       
   175 	 ))
       
   176 
       
   177 ;; Vala does not allow a leading qualifier operator. It also doesn't
       
   178 ;; allow the ".*" construct of Java. So, we redo this regex without
       
   179 ;; the "\\|\\*" regex.
       
   180 (c-lang-defconst c-identifier-key
       
   181   vala (concat "\\(" (c-lang-const c-symbol-key) "\\)" ; 1
       
   182 	       (concat "\\("
       
   183 		       "[ \t\n\r\f\v]*"
       
   184 		       (c-lang-const c-opt-identifier-concat-key)
       
   185 		       "[ \t\n\r\f\v]*"
       
   186 		       (concat "\\("
       
   187 			       "\\(" (c-lang-const c-symbol-key) "\\)"
       
   188 			       "\\)")
       
   189 		       "\\)*")))
       
   190 
       
   191 ;; Vala has a few rules that are slightly different than Java for
       
   192 ;; operators. This also removed the Java's "super" and replaces it
       
   193 ;; with the Vala's "base".
       
   194 (c-lang-defconst c-operators
       
   195   vala `((prefix "base")))
       
   196 
       
   197 ;; Vala directives ?
       
   198 ;; (c-lang-defconst c-opt-cpp-prefix
       
   199 ;;   csharp "^\\s *#.*")
       
   200 
       
   201 
       
   202 ;; Vala uses the following assignment operators
       
   203 (c-lang-defconst c-assignment-operators
       
   204   vala '("=" "*=" "/=" "%=" "+=" "-=" ">>=" "<<="
       
   205 	 "&=" "^=" "|=" "++" "--"))
       
   206 
       
   207 ;; This defines the primative types for Vala
       
   208 (c-lang-defconst c-primitive-type-kwds
       
   209   vala '("void" "char" "int" "float" "double" "string"))
       
   210 
       
   211 ;; The keywords that define that the following is a type, such as a
       
   212 ;; class definition.
       
   213 (c-lang-defconst c-type-prefix-kwds
       
   214   vala '("class" "interface" "struct" "enum" "signal"))
       
   215 
       
   216 ;; Type modifier keywords. They appear anywhere in types, but modifiy
       
   217 ;; instead create one.
       
   218 (c-lang-defconst c-type-modifier-kwds
       
   219   vala '("const"))
       
   220 
       
   221 ;; Structures that are similiar to classes.
       
   222 (c-lang-defconst c-class-decl-kwds
       
   223   vala '("class" "interface"))
       
   224 
       
   225 ;; The various modifiers used for class and method descriptions.
       
   226 (c-lang-defconst c-modifier-kwds
       
   227   vala '("public" "partial" "private" "const" "abstract"
       
   228 	 "protected" "ref" "in" "out" "static" "virtual"
       
   229 	 "override" "params" "internal" "weak" "owned"
       
   230 	 "unowned"))
       
   231 
       
   232 ;; We don't use the protection level stuff because it breaks the
       
   233 ;; method indenting. Not sure why, though.
       
   234 (c-lang-defconst c-protection-kwds
       
   235   vala nil)
       
   236 
       
   237 ;; Define the keywords that can have something following after them.
       
   238 (c-lang-defconst c-type-list-kwds
       
   239   vala '("struct" "class" "interface" "is" "as"
       
   240 	 "delegate" "event" "set" "get" "add" "remove"
       
   241 	 "callback" "signal" "var" "default"))
       
   242 
       
   243 ;; This allows the classes after the : in the class declartion to be
       
   244 ;; fontified. 
       
   245 (c-lang-defconst c-typeless-decl-kwds
       
   246   vala '(":"))
       
   247 
       
   248 ;; Sets up the enum to handle the list properly
       
   249 (c-lang-defconst c-brace-list-decl-kwds
       
   250   vala '("enum" "errordomain"))
       
   251 
       
   252 ;; We need to remove Java's package keyword
       
   253 (c-lang-defconst c-ref-list-kwds
       
   254   vala '("using" "namespace" "construct"))
       
   255 
       
   256 ;; Follow-on blocks that don't require a brace
       
   257 (c-lang-defconst c-block-stmt-2-kwds
       
   258   vala '("for" "if" "switch" "while" "catch" "foreach" "lock"))
       
   259 
       
   260 ;; Statements that break out of braces
       
   261 (c-lang-defconst c-simple-stmt-kwds
       
   262   vala '("return" "continue" "break" "throw"))
       
   263 
       
   264 ;; Statements that allow a label
       
   265 ;; TODO?
       
   266 (c-lang-defconst c-before-label-kwds
       
   267   vala nil)
       
   268 
       
   269 ;; Constant keywords
       
   270 (c-lang-defconst c-constant-kwds
       
   271   vala '("true" "false" "null"))
       
   272 
       
   273 ;; Keywords that start "primary expressions."
       
   274 (c-lang-defconst c-primary-expr-kwds
       
   275   vala '("this" "base"))
       
   276 
       
   277 ;; We need to treat namespace as an outer block to class indenting
       
   278 ;; works properly.
       
   279 (c-lang-defconst c-other-block-decl-kwds
       
   280   vala '("namespace"))
       
   281 
       
   282 ;; We need to include the "in" for the foreach
       
   283 (c-lang-defconst c-other-kwds
       
   284   vala '("in" "sizeof" "typeof"))
       
   285 
       
   286 (require 'cc-awk)
       
   287 
       
   288 (c-lang-defconst c-at-vsemi-p-fn
       
   289   vala 'c-awk-at-vsemi-p)
       
   290 
       
   291 
       
   292 (defcustom vala-font-lock-extra-types nil
       
   293   "*List of extra types (aside from the type keywords) to recognize in Vala mode.
       
   294 Each list item should be a regexp matching a single identifier.")
       
   295 
       
   296 (defconst vala-font-lock-keywords-1 (c-lang-const c-matchers-1 vala)
       
   297   "Minimal highlighting for Vala mode.")
       
   298 
       
   299 (defconst vala-font-lock-keywords-2 (c-lang-const c-matchers-2 vala)
       
   300   "Fast normal highlighting for Vala mode.")
       
   301 
       
   302 (defconst vala-font-lock-keywords-3 (c-lang-const c-matchers-3 vala)
       
   303   "Accurate normal highlighting for Vala mode.")
       
   304 
       
   305 (defvar vala-font-lock-keywords vala-font-lock-keywords-3
       
   306   "Default expressions to highlight in Vala mode.")
       
   307 
       
   308 (defvar vala-mode-syntax-table
       
   309   nil
       
   310   "Syntax table used in vala-mode buffers.")
       
   311 (or vala-mode-syntax-table
       
   312     (setq vala-mode-syntax-table
       
   313 	  (funcall (c-lang-const c-make-mode-syntax-table vala))))
       
   314 
       
   315 (defvar vala-mode-abbrev-table nil
       
   316   "Abbreviation table used in vala-mode buffers.")
       
   317 (c-define-abbrev-table 'vala-mode-abbrev-table
       
   318   ;; Keywords that if they occur first on a line
       
   319   ;; might alter the syntactic context, and which
       
   320   ;; therefore should trig reindentation when
       
   321   ;; they are completed.
       
   322   '(("else" "else" c-electric-continued-statement 0)
       
   323     ("while" "while" c-electric-continued-statement 0)
       
   324     ("catch" "catch" c-electric-continued-statement 0)
       
   325     ("finally" "finally" c-electric-continued-statement 0)))
       
   326 
       
   327 (defvar vala-mode-map (let ((map (c-make-inherited-keymap)))
       
   328 			;; Add bindings which are only useful for Vala
       
   329 			map)
       
   330   "Keymap used in vala-mode buffers.")
       
   331 
       
   332 ;;(easy-menu-define vala-menu vala-mode-map "Vala Mode Commands"
       
   333 ;;		  ;; Can use `vala' as the language for `c-mode-menu'
       
   334 ;;		  ;; since its definition covers any language.  In
       
   335 ;;		  ;; this case the language is used to adapt to the
       
   336 ;;		  ;; nonexistence of a cpp pass and thus removing some
       
   337 ;;		  ;; irrelevant menu alternatives.
       
   338 ;;		  (cons "Vala" (c-lang-const c-mode-menu vala)))
       
   339 
       
   340 ;;; Autoload mode trigger
       
   341 (add-to-list 'auto-mode-alist '("\\.vala$" . vala-mode))
       
   342 (add-to-list 'auto-mode-alist '("\\.vapi$" . vala-mode))
       
   343 
       
   344 ;; Custom variables
       
   345 (defcustom vala-mode-hook nil
       
   346   "*Hook called by `vala-mode'."
       
   347   :type 'hook
       
   348   :group 'c)
       
   349 
       
   350 ;;; The entry point into the mode
       
   351 ;;;###autoload
       
   352 (defun vala-mode ()
       
   353   "Major mode for editing Vala code.
       
   354 This is a simple example of a separate mode derived from CC Mode
       
   355 to support a language with syntax similar to
       
   356 C#/C/C++/ObjC/Java/IDL/Pike.
       
   357 
       
   358 The hook `c-mode-common-hook' is run with no args at mode
       
   359 initialization, then `vala-mode-hook'.
       
   360 
       
   361 Key bindings:
       
   362 \\{vala-mode-map}"
       
   363   (interactive)
       
   364   (kill-all-local-variables)
       
   365   (c-initialize-cc-mode t)
       
   366   (set-syntax-table vala-mode-syntax-table)
       
   367   (setq major-mode 'vala-mode
       
   368 	mode-name "Vala"
       
   369 	local-abbrev-table vala-mode-abbrev-table
       
   370 	abbrev-mode t)
       
   371   (use-local-map c-mode-map)
       
   372   ;; `c-init-language-vars' is a macro that is expanded at compile
       
   373   ;; time to a large `setq' with all the language variables and their
       
   374   ;; customized values for our language.
       
   375   (c-init-language-vars vala-mode)
       
   376   ;; `c-common-init' initializes most of the components of a CC Mode
       
   377   ;; buffer, including setup of the mode menu, font-lock, etc.
       
   378   ;; There's also a lower level routine `c-basic-common-init' that
       
   379   ;; only makes the necessary initialization to get the syntactic
       
   380   ;; analysis and similar things working.
       
   381   (c-common-init 'vala-mode)
       
   382   ;;(easy-menu-add vala-menu)
       
   383   (c-set-style "linux")
       
   384   (setq indent-tabs-mode t)
       
   385   (setq c-basic-offset 4)
       
   386   (setq tab-width 4)
       
   387   (c-toggle-auto-newline -1)
       
   388   (c-toggle-hungry-state -1)
       
   389   (run-hooks 'c-mode-common-hook)
       
   390   (run-hooks 'vala-mode-hook)
       
   391   (c-update-modeline))
       
   392 
       
   393 (provide 'vala-mode)
       
   394 
       
   395 ;;; vala-mode.el ends here