22
|
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 |