]> git.pld-linux.org Git - packages/emacs.git/blob - emacs-nemerle.el
- rebuild with ImageMagick 7.0.9.23
[packages/emacs.git] / emacs-nemerle.el
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
This page took 0.088461 seconds and 3 git commands to generate.