1 ;;; nemerle.el -- major mode for editing nemerle programs
3 ;; Copyright (C) 2003, 2004 The University of Wroclaw
4 ;; All rights reserved.
6 ;; Author: Jacek Sliwerski (rzyjontko) <rzyj@o2.pl>
7 ;; Maintainer: Jacek Sliwerski (rzyjontko) <rzyj@o2.pl>
10 ;; Keywords: nemerle, mode, languages
11 ;; Website: http://nemerle.org
14 ;; This file is not part of GNU Emacs.
16 ;; Redistribution and use in source and binary forms, with or without
17 ;; modification, are permitted provided that the following conditions
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.
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.
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
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))
53 ;; If you'd like to have every line indented right after new line put
54 ;; these lines into your ~/.emacs files.
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)
65 ;; 2004-04-27 rzyjontko <rzyj@o2.pl>
66 ;; * further coloring improvements
67 ;; * fixed syntax table
69 ;; 2004-01-24 rzyjontko <rzyj@o2.pl>
72 ;; 2004-01-23 rzyjontko <rzyj@o2.pl>
73 ;; * indent to open parenthesis
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
82 ;; 2003-11-17 rzyjontko <rzyj@o2.pl>
83 ;; * updated copyright disclaimer
84 ;; * basic indentation engine
86 ;; 2003-10-09 rzyjontko <rzyj@o2.pl>
87 ;; * nemerle mode automatically sets file coding system to utf-8
88 ;; * syntax table changes
90 ;; * indentation framework
92 ;; 2003-10-05 rzyjontko <rzyj@o2.pl>
99 ;; - further indentation improvements
100 ;; - imenu (with ncc execution)
101 ;; - make _ be a special symbol (write matcher functions)
107 (provide 'nemerle-mode)
110 (defvar nemerle-mode-map nil
111 "The keymap used in nemerle-mode.")
113 (defvar nemerle-font-lock-keywords nil
114 "Font lock definitions for nemerle-mode.")
116 (defvar nemerle-mode-syntax-table nil
117 "The syntax table used in nemerle-mode.")
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.")
123 (defvar nemerle-basic-offset 4
124 "Indentation of blocks in nemerle.")
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)))
133 (unless nemerle-font-lock-keywords
134 (setq nemerle-font-lock-keywords
137 '("[^']\\(\"[^\"]*\"\\)" 1 font-lock-string-face)
138 '("'[^\\']'\\|'\\\\.'" 0 font-lock-string-face)
141 '("//.*" 0 font-lock-comment-face)
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)
151 '("\\<\\(foreach\\)\\s *(.*:\\s *\\(\\w*\\)\\s *\\(\\<in\\>\\)"
152 (1 font-lock-keyword-face) (2 font-lock-type-face) (3 font-lock-keyword-face))
154 '("\\<\\(variant\\|class\\|interface\\|module\\|namespace\\|using\\)\\s +\\(\\(\\w\\|\\.\\)*\\)"
155 (1 font-lock-keyword-face) (2 font-lock-function-name-face))
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)
166 '("\\<[0-9]+\\>" 0 font-lock-constant-face)
167 '("\\<Nil\\>" 0 font-lock-constant-face)
168 '("\\<\\(false\\|true\\|null\\)\\>" 0 font-lock-constant-face))))
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))
177 (defun nemerle-syntax ()
180 (cond ((looking-at "[ \t]*\\<try\\>")
182 ((looking-at "[ \t]*\\<catch\\>")
184 ((looking-at "[ \t]*|")
186 ((looking-at "[ \t]*$")
188 ((looking-at "[ \t]*\\<if\\>")
190 ((looking-at "[ \t]*\\<else\\>")
192 ((looking-at "[^\n{]*}")
194 ((looking-at "[^\n]*{[^\n}]*$")
196 ((looking-at "[ \t]*\\<when\\>")
198 ((looking-at "[ \t]*\\<unless\\>")
204 (defun nemerle-prev-line ()
209 (let ((there (point)))
210 (skip-chars-backward " \t\n")
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))
224 (cons indent syntax))))))))
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)
234 ((eq prev-syntax 'match-case) ; match-case
235 (cond ((eq cur-syntax 'match-case)
237 ((eq cur-syntax 'block-end)
238 (- prev-indent nemerle-basic-offset))
241 ((eq prev-syntax 'try) ; try
242 (cond ((eq cur-syntax 'block-beg)
244 ((eq cur-syntax 'catch)
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))
256 ((eq prev-syntax 'if) ; if
257 (+ prev-indent nemerle-basic-offset))
258 ((eq prev-syntax 'else) ; else
259 (+ prev-indent nemerle-basic-offset))
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))
271 (defun nemerle-indent-to (level)
274 (skip-chars-forward " \t")
275 (if (< level (current-indentation))
276 (delete-horizontal-space))
278 (if (< (current-column) (current-indentation))
279 (skip-chars-forward " \t")))
283 (defun nemerle-indent-line ()
284 "Indent current line of nemerle code."
286 (let ((level (nemerle-calculate-indentation)))
287 (nemerle-indent-to level)))
291 (defun nemerle-electric-bar (arg)
294 Also, the line is re-indented unless a numeric ARG is supplied
295 or there are some non-blank symbols on the line."
297 (if (or (not (eq (nemerle-syntax) 'empty)) (and arg (> arg 1)))
298 (self-insert-command (or arg 1))
300 (let* ((prev-info (nemerle-prev-line))
301 (prev-indent (car prev-info))
302 (prev-syntax (cdr prev-info))
304 (if (eq prev-syntax 'block-beg)
305 (setq level (+ prev-indent nemerle-basic-offset)))
306 (nemerle-indent-to level)
307 (insert-char ?| 1))))
310 (defun nemerle-electric-brace (arg)
313 Also, the line is re-indented unless a numeric ARG is supplied
314 or there are some non-blank symbols on the line."
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))
322 (nemerle-indent-to (- prev-indent nemerle-basic-offset))
323 (insert-char ?} 1))))
326 (defun nemerle-comment-indent ()
327 "Indent current line of nemerle comment."
332 (defun nemerle-mode ()
333 "Major mode for editing nemerle source files.
337 \\{nemerle-mode-map}"
340 (kill-all-local-variables)
342 (setq mode-name "Nemerle")
343 (setq major-mode 'nemerle-mode)
345 (use-local-map nemerle-mode-map)
346 (set-syntax-table nemerle-mode-syntax-table)
348 (make-local-variable 'font-lock-defaults)
349 (setq font-lock-defaults '(nemerle-font-lock-keywords nil nil
350 ((?_ . "w") (?. . "w") (?\/ . ". 14b")
351 (?* . ". 23") (?\" . ".") (?\' . "."))))
353 (make-local-variable 'indent-line-function)
354 (setq indent-line-function 'nemerle-indent-line)
356 (make-local-variable 'comment-indent-function)
357 (setq comment-indent-function 'c-comment-indent)
359 (make-local-variable 'comment-start)
360 (setq comment-start "/* ")
362 (make-local-variable 'comment-end)
363 (setq comment-end " */")
365 (make-local-variable 'comment-start-skip)
366 (setq comment-start-skip "/\\*+[ \t]*\\|//+ *")
368 (setq buffer-file-coding-system 'utf-8)
369 (setq indent-tabs-mode nil)
371 (run-hooks 'nemerle-mode-hook))
373 ;;; nemerle.el ends here