]>
Commit | Line | Data |
---|---|---|
fe590b1d | 1 | ;;; nemerle.el -- major mode for editing nemerle programs |
2 | ||
3 | ;; Copyright (C) 2003, 2004 The University of Wroclaw | |
4 | ;; All rights reserved. | |
5 | ||
6 | ;; Author: Jacek Sliwerski (rzyjontko) <rzyj@o2.pl> | |
7 | ;; Maintainer: Jacek Sliwerski (rzyjontko) <rzyj@o2.pl> | |
8 | ;; Created: 5 Oct 2003 | |
9 | ;; Version: 0.1 | |
10 | ;; Keywords: nemerle, mode, languages | |
11 | ;; Website: http://nemerle.org | |
12 | ||
13 | ||
14 | ;; This file is not part of GNU Emacs. | |
15 | ;; | |
16 | ;; Redistribution and use in source and binary forms, with or without | |
17 | ;; modification, are permitted provided that the following conditions | |
18 | ;; are met: | |
19 | ;; 1. Redistributions of source code must retain the above copyright | |
20 | ;; notice, this list of conditions and the following disclaimer. | |
21 | ;; 2. Redistributions in binary form must reproduce the above copyright | |
22 | ;; notice, this list of conditions and the following disclaimer in the | |
23 | ;; documentation and/or other materials provided with the distribution. | |
24 | ;; 3. The name of the University may not be used to endorse or promote | |
25 | ;; products derived from this software without specific prior | |
26 | ;; written permission. | |
27 | ;; | |
28 | ;; THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY ``AS IS'' AND ANY EXPRESS OR | |
29 | ;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
30 | ;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | |
31 | ;; NO EVENT SHALL THE UNIVERSITY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
32 | ;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
33 | ;; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
34 | ;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
35 | ;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
36 | ;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
37 | ;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
38 | ||
39 | ||
40 | ||
41 | ;;; Commentary: | |
42 | ||
43 | ;; A major mode for editing nemerle source files. It provides syntax | |
44 | ;; hilighting, proper indentation, and many other features. | |
45 | ;; To install the nemerle mode, put the following lines into your | |
46 | ;; ~/.emacs file: | |
47 | ||
48 | ;; (setq load-path (cons "/path/to/dir/where/this/file/resides" load-path)) | |
49 | ;; (autoload 'nemerle-mode "nemerle.el" | |
50 | ;; "Major mode for editing nemerle programs." t) | |
51 | ;; (setq auto-mode-alist (cons '("\\.n$" . nemerle-mode) auto-mode-alist)) | |
52 | ||
53 | ;; If you'd like to have every line indented right after new line put | |
54 | ;; these lines into your ~/.emacs files. | |
55 | ||
56 | ;; (defun my-nemerle-mode-hook () | |
57 | ;; (setq nemerle-basic-offset 2) | |
58 | ;; (define-key nemerle-mode-map "\C-m" 'newline-and-indent)) | |
59 | ;; (add-hook 'nemerle-mode-hook 'my-nemerle-mode-hook) | |
60 | ||
61 | ||
62 | ||
63 | ;;; Change Log: | |
64 | ||
65 | ;; 2004-04-27 rzyjontko <rzyj@o2.pl> | |
66 | ;; * further coloring improvements | |
67 | ;; * fixed syntax table | |
68 | ||
69 | ;; 2004-01-24 rzyjontko <rzyj@o2.pl> | |
70 | ;; * fixed coloring | |
71 | ||
72 | ;; 2004-01-23 rzyjontko <rzyj@o2.pl> | |
73 | ;; * indent to open parenthesis | |
74 | ||
75 | ;; 2004-01-21 rzyjontko <rzyj@o2.pl> | |
76 | ;; * improved indentation | |
77 | ;; * changed syntax table | |
78 | ;; * disabled tab-indent | |
79 | ;; * switched to new grammar | |
80 | ;; * electric-bar and electric-brace | |
81 | ||
82 | ;; 2003-11-17 rzyjontko <rzyj@o2.pl> | |
83 | ;; * updated copyright disclaimer | |
84 | ;; * basic indentation engine | |
85 | ||
86 | ;; 2003-10-09 rzyjontko <rzyj@o2.pl> | |
87 | ;; * nemerle mode automatically sets file coding system to utf-8 | |
88 | ;; * syntax table changes | |
89 | ;; * more colours | |
90 | ;; * indentation framework | |
91 | ||
92 | ;; 2003-10-05 rzyjontko <rzyj@o2.pl> | |
93 | ;; * initial version | |
94 | ||
95 | ||
96 | ||
97 | ;;; Todo: | |
98 | ||
99 | ;; - further indentation improvements | |
100 | ;; - imenu (with ncc execution) | |
101 | ;; - make _ be a special symbol (write matcher functions) | |
102 | ||
103 | ||
104 | ||
105 | ;;; Code: | |
106 | ||
107 | (provide 'nemerle-mode) | |
108 | ||
109 | ||
110 | (defvar nemerle-mode-map nil | |
111 | "The keymap used in nemerle-mode.") | |
112 | ||
113 | (defvar nemerle-font-lock-keywords nil | |
114 | "Font lock definitions for nemerle-mode.") | |
115 | ||
116 | (defvar nemerle-mode-syntax-table nil | |
117 | "The syntax table used in nemerle-mode.") | |
118 | ||
119 | (defvar nemerle-mode-hook nil | |
120 | "This hook is run when nemerle-mode is loaded, or a new nemerle-mode | |
121 | buffer created. This is a good place to put your customizations.") | |
122 | ||
123 | (defvar nemerle-basic-offset 4 | |
124 | "Indentation of blocks in nemerle.") | |
125 | ||
126 | (unless nemerle-mode-map | |
127 | (let ((map (make-sparse-keymap))) | |
128 | (define-key map "\C-c\C-c" 'comment-region) | |
129 | (define-key map "|" 'nemerle-electric-bar) | |
130 | (define-key map "}" 'nemerle-electric-brace) | |
131 | (setq nemerle-mode-map map))) | |
132 | ||
133 | (unless nemerle-font-lock-keywords | |
134 | (setq nemerle-font-lock-keywords | |
135 | (list | |
136 | ;; strings | |
137 | '("[^']\\(\"[^\"]*\"\\)" 1 font-lock-string-face) | |
138 | '("'[^\\']'\\|'\\\\.'" 0 font-lock-string-face) | |
139 | ||
140 | ;; one-line comments | |
141 | '("//.*" 0 font-lock-comment-face) | |
142 | ||
143 | ;; keywords | |
144 | '("\\<\\(_\\|abstract\\|and\\|as\\|base\\|catch\\|const\\|def\\|delegate\\|enum\\|extends\\|extern\\|finally\\|fun\\|implements\\|interface\\|internal\\|is\\|macro\\|match\\|matches\\|mutable\\|new\\|out\\|override\\|params\\|private\\|protected\\|public\\|ref\\|sealed\\|static\\|struct\\|syntax\\|this\\|throw\\|try\\|tymatch\\|type\\|typeof\\|virtual\\|where\\|partial\\)\\>" | |
145 | 0 font-lock-keyword-face) | |
146 | ;; these aren't really keywords but we set them so | |
147 | '("\\<\\(do\\|else\\|for\\|if\\|regexp\\|unless\\|while\\|when\\|in\\|foreach\\)\\>" | |
148 | 0 font-lock-keyword-face) | |
149 | '("=>\\||" 0 font-lock-keyword-face) | |
150 | ||
151 | '("\\<\\(foreach\\)\\s *(.*:\\s *\\(\\w*\\)\\s *\\(\\<in\\>\\)" | |
152 | (1 font-lock-keyword-face) (2 font-lock-type-face) (3 font-lock-keyword-face)) | |
153 | ||
154 | '("\\<\\(variant\\|class\\|interface\\|module\\|namespace\\|using\\)\\s +\\(\\(\\w\\|\\.\\)*\\)" | |
155 | (1 font-lock-keyword-face) (2 font-lock-function-name-face)) | |
156 | ||
157 | ;; types | |
158 | '("\\<list\\s *<[^>]*[^\\-]>+" 0 font-lock-type-face t) | |
159 | '("\\<option\\s *<[^>]*>+" 0 font-lock-type-face t) | |
160 | '("\\<array\\s *<[^>]*>+" 0 font-lock-type-face t) | |
161 | '("->" 0 font-lock-type-face) | |
162 | '("\\<\\(void\\|int\\|uint\\|char\\|float\\|double\\|decimal\\|byte\\|sbyte\\|short\\|ushort\\|long\\|ulong\\|bool\\|string\\|object\\)\\>" | |
163 | 0 font-lock-type-face) | |
164 | ||
165 | ;; constants | |
166 | '("\\<[0-9]+\\>" 0 font-lock-constant-face) | |
167 | '("\\<Nil\\>" 0 font-lock-constant-face) | |
168 | '("\\<\\(false\\|true\\|null\\)\\>" 0 font-lock-constant-face)))) | |
169 | ||
170 | ||
171 | (unless nemerle-mode-syntax-table | |
172 | (setq nemerle-mode-syntax-table (copy-syntax-table c-mode-syntax-table)) | |
173 | (modify-syntax-entry ?< "(>" nemerle-mode-syntax-table) | |
174 | (modify-syntax-entry ?> ")<" nemerle-mode-syntax-table)) | |
175 | ||
176 | ||
177 | (defun nemerle-syntax () | |
178 | (save-excursion | |
179 | (beginning-of-line) | |
180 | (cond ((looking-at "[ \t]*\\<try\\>") | |
181 | 'try) | |
182 | ((looking-at "[ \t]*\\<catch\\>") | |
183 | 'catch) | |
184 | ((looking-at "[ \t]*|") | |
185 | 'match-case) | |
186 | ((looking-at "[ \t]*$") | |
187 | 'empty) | |
188 | ((looking-at "[ \t]*\\<if\\>") | |
189 | 'if) | |
190 | ((looking-at "[ \t]*\\<else\\>") | |
191 | 'else) | |
192 | ((looking-at "[^\n{]*}") | |
193 | 'block-end) | |
194 | ((looking-at "[^\n]*{[^\n}]*$") | |
195 | 'block-beg) | |
196 | ((looking-at "[ \t]*\\<when\\>") | |
197 | 'if) | |
198 | ((looking-at "[ \t]*\\<unless\\>") | |
199 | 'if) | |
200 | (t | |
201 | 'other)))) | |
202 | ||
203 | ||
204 | (defun nemerle-prev-line () | |
205 | (save-excursion | |
206 | (beginning-of-line) | |
207 | (if (bobp) | |
208 | 0 | |
209 | (let ((there (point))) | |
210 | (skip-chars-backward " \t\n") | |
211 | (beginning-of-line) | |
212 | (let* ((here (point)) | |
213 | (syntax (nemerle-syntax)) | |
214 | (indent (current-indentation)) | |
215 | (state (parse-partial-sexp here there))) | |
216 | (cond ((and (< (nth 0 state) 0) (eq ?\) (nth 2 state))) | |
217 | (goto-char (scan-lists (nth 2 state) -1 1)) | |
218 | (cons (current-indentation) (nemerle-syntax))) | |
219 | ((null (nth 1 state)) | |
220 | (cons indent syntax)) | |
221 | ((eq (char-after (nth 1 state)) ?\() | |
222 | (cons (- (nth 1 state) here) 'open-paren)) | |
223 | (t | |
224 | (cons indent syntax)))))))) | |
225 | ||
226 | ||
227 | (defun nemerle-calculate-indentation () | |
228 | (let* ((prev-info (nemerle-prev-line)) | |
229 | (prev-indent (car prev-info)) | |
230 | (prev-syntax (cdr prev-info)) | |
231 | (cur-syntax (nemerle-syntax))) | |
232 | (cond ((eq prev-syntax 'open-paren) | |
233 | (1+ prev-indent)) | |
234 | ((eq prev-syntax 'match-case) ; match-case | |
235 | (cond ((eq cur-syntax 'match-case) | |
236 | prev-indent) | |
237 | ((eq cur-syntax 'block-end) | |
238 | (- prev-indent nemerle-basic-offset)) | |
239 | (t | |
240 | (+ prev-indent 2)))) | |
241 | ((eq prev-syntax 'try) ; try | |
242 | (cond ((eq cur-syntax 'block-beg) | |
243 | prev-indent) | |
244 | ((eq cur-syntax 'catch) | |
245 | prev-indent) | |
246 | (t (+ prev-indent nemerle-basic-offset)))) | |
247 | ((eq prev-syntax 'catch) | |
248 | (+ prev-indent nemerle-basic-offset)) | |
249 | ((eq prev-syntax 'block-beg) ; beginning of block | |
250 | (+ prev-indent nemerle-basic-offset)) | |
251 | ((eq prev-syntax 'block-end) ; end of block | |
252 | (cond ((eq cur-syntax 'block-end) | |
253 | (- prev-indent nemerle-basic-offset)) | |
254 | (t | |
255 | prev-indent))) | |
256 | ((eq prev-syntax 'if) ; if | |
257 | (+ prev-indent nemerle-basic-offset)) | |
258 | ((eq prev-syntax 'else) ; else | |
259 | (+ prev-indent nemerle-basic-offset)) | |
260 | (t | |
261 | (cond ((eq cur-syntax 'block-end) | |
262 | (- prev-indent nemerle-basic-offset)) | |
263 | ((eq cur-syntax 'else) | |
264 | (- prev-indent nemerle-basic-offset)) | |
265 | ((eq cur-syntax 'catch) | |
266 | (- prev-indent nemerle-basic-offset)) | |
267 | (t | |
268 | prev-indent)))))) | |
269 | ||
270 | ||
271 | (defun nemerle-indent-to (level) | |
272 | (save-excursion | |
273 | (beginning-of-line) | |
274 | (skip-chars-forward " \t") | |
275 | (if (< level (current-indentation)) | |
276 | (delete-horizontal-space)) | |
277 | (indent-to level)) | |
278 | (if (< (current-column) (current-indentation)) | |
279 | (skip-chars-forward " \t"))) | |
280 | ||
281 | ||
282 | ||
283 | (defun nemerle-indent-line () | |
284 | "Indent current line of nemerle code." | |
285 | (interactive) | |
286 | (let ((level (nemerle-calculate-indentation))) | |
287 | (nemerle-indent-to level))) | |
288 | ||
289 | ||
290 | ||
291 | (defun nemerle-electric-bar (arg) | |
292 | "Insert a bar. | |
293 | ||
294 | Also, the line is re-indented unless a numeric ARG is supplied | |
295 | or there are some non-blank symbols on the line." | |
296 | (interactive "p") | |
297 | (if (or (not (eq (nemerle-syntax) 'empty)) (and arg (> arg 1))) | |
298 | (self-insert-command (or arg 1)) | |
299 | (message "ok") | |
300 | (let* ((prev-info (nemerle-prev-line)) | |
301 | (prev-indent (car prev-info)) | |
302 | (prev-syntax (cdr prev-info)) | |
303 | (level prev-indent)) | |
304 | (if (eq prev-syntax 'block-beg) | |
305 | (setq level (+ prev-indent nemerle-basic-offset))) | |
306 | (nemerle-indent-to level) | |
307 | (insert-char ?| 1)))) | |
308 | ||
309 | ||
310 | (defun nemerle-electric-brace (arg) | |
311 | "Insert a brace. | |
312 | ||
313 | Also, the line is re-indented unless a numeric ARG is supplied | |
314 | or there are some non-blank symbols on the line." | |
315 | (interactive "p") | |
316 | (if (or (not (eq (nemerle-syntax) 'empty)) (and arg (> arg 1))) | |
317 | (self-insert-command (or arg 1)) | |
318 | (let* ((prev-info (nemerle-prev-line)) | |
319 | (prev-indent (car prev-info)) | |
320 | (prev-syntax (cdr prev-info)) | |
321 | (level prev-indent)) | |
322 | (nemerle-indent-to (- prev-indent nemerle-basic-offset)) | |
323 | (insert-char ?} 1)))) | |
324 | ||
325 | ||
326 | (defun nemerle-comment-indent () | |
327 | "Indent current line of nemerle comment." | |
328 | (interactive) | |
329 | 0) | |
330 | ||
331 | ||
332 | (defun nemerle-mode () | |
333 | "Major mode for editing nemerle source files. | |
334 | ||
335 | Mode map | |
336 | ======== | |
337 | \\{nemerle-mode-map}" | |
338 | ||
339 | (interactive) | |
340 | (kill-all-local-variables) | |
341 | ||
342 | (setq mode-name "Nemerle") | |
343 | (setq major-mode 'nemerle-mode) | |
344 | ||
345 | (use-local-map nemerle-mode-map) | |
346 | (set-syntax-table nemerle-mode-syntax-table) | |
347 | ||
348 | (make-local-variable 'font-lock-defaults) | |
349 | (setq font-lock-defaults '(nemerle-font-lock-keywords nil nil | |
350 | ((?_ . "w") (?. . "w") (?\/ . ". 14b") | |
351 | (?* . ". 23") (?\" . ".") (?\' . ".")))) | |
352 | ||
353 | (make-local-variable 'indent-line-function) | |
354 | (setq indent-line-function 'nemerle-indent-line) | |
355 | ||
356 | (make-local-variable 'comment-indent-function) | |
357 | (setq comment-indent-function 'c-comment-indent) | |
358 | ||
359 | (make-local-variable 'comment-start) | |
360 | (setq comment-start "/* ") | |
361 | ||
362 | (make-local-variable 'comment-end) | |
363 | (setq comment-end " */") | |
364 | ||
365 | (make-local-variable 'comment-start-skip) | |
366 | (setq comment-start-skip "/\\*+[ \t]*\\|//+ *") | |
367 | ||
368 | (setq buffer-file-coding-system 'utf-8) | |
369 | (setq indent-tabs-mode nil) | |
370 | ||
371 | (run-hooks 'nemerle-mode-hook)) | |
372 | ||
373 | ;;; nemerle.el ends here |