changelog shortlog tags changeset files revisions annotate raw

rnc-mode.el

changeset 66: 5b737eefe5ea
author: kim.vanwyk
date: Wed Nov 10 15:19:03 2010 +0200 (18 months ago)
permissions: -rw-r--r--
description: Adding CSharp Mode and Google Weather
1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2;; A major mode for editing RELAX NG Compact syntax.
3;; Version: 1.0b3
4;; Date: 2002-12-05
5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6
7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8;;
9;; Copyright (c) 2002, Pantor Engineering AB
10;; All rights reserved.
11;;
12;; Redistribution and use in source and binary forms, with or
13;; without modification, are permitted provided that the following
14;; conditions are met:
15;;
16;; * Redistributions of source code must retain the above copyright
17;; notice, this list of conditions and the following disclaimer.
18;;
19;; * Redistributions in binary form must reproduce the above
20;; copyright notice, this list of conditions and the following
21;; disclaimer in the documentation and/or other materials provided
22;; with the distribution.
23;;
24;; * Neither the name of Pantor Engineering AB nor the names of its
25;; contributors may be used to endorse or promote products derived
26;; from this software without specific prior written permission.
27;;
28;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29;; CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
30;; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
31;; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32;; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
33;; BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
34;; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
35;; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
37;; ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
38;; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39;; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40;; POSSIBILITY OF SUCH DAMAGE.
41;;
42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
43
44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
45;; Created by David.Rosenborg@pantor.com
46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
47
48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
49;; Example setup for your ~/.emacs file:
50;;
51;; (autoload 'rnc-mode "rnc-mode")
52;; (setq auto-mode-alist
53;; (cons '("\\.rnc\\'" . rnc-mode) auto-mode-alist))
54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
55
56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
57;; Changes since 1.0b:
58;; Added a couple of defvars for faces to handle differences
59;; between GNU Emacs and XEmacs.
60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
61
62(require 'font-lock)
63
64(defvar rnc-indent-level 3 "The RNC indentation level.")
65
66(defvar rnc-keywords
67 (mapcar (lambda (kw) (concat "\\b" kw "\\b"))
68 '("attribute" "div" "element"
69 "empty" "external" "grammar" "include" "inherit" "list"
70 "mixed" "notAllowed" "parent" "start" "string"
71 "text" "token"))
72 "RNC keywords")
73
74(defvar rnc-atoms
75 (mapcar (lambda (kw) (concat "\\b" kw "\\b"))
76 '("empty" "notAllowed" "string" "text" "token"))
77 "RNC atomic pattern keywords")
78
79(defun rnc-make-regexp-choice (operands)
80 "(op1 op2 ...) -> \"\\(op1\\|op2\\|...\\)\""
81 (let ((result "\\("))
82 (mapcar (lambda (op) (setq result (concat result op "\\|"))) operands)
83 (concat (substring result 0 -2) "\\)")))
84
85;; Font lock treats face names differently in GNU Emacs and XEmacs
86;; The following defvars is a workaround
87
88(defvar italic 'italic)
89(defvar default 'default)
90(defvar font-lock-preprocessor-face 'font-lock-preprocessor-face)
91
92(defvar rnc-font-lock-keywords
93 (list
94 '("\\b\\(attribute\\|element\\)\\b\\([^{]+\\){" 2
95 font-lock-variable-name-face)
96 '("[a-zA-Z][-a-zA-Z0-9._]*:[a-zA-Z][-a-zA-Z0-9._]*" . italic)
97 '("\\b\\(default\\(\\s +namespace\\)?\\|namespace\\|datatypes\\)\\(\\s +[a-zA-Z][-a-zA-Z0-9._]*\\)?\\s *=" 1 font-lock-preprocessor-face)
98 '("\\([a-zA-Z][-a-zA-Z0-9._]*\\)\\(\\s \\|\n\\)*[|&]?=" 1
99 font-lock-function-name-face)
100 '("[a-zA-Z][a-zA-Z0-9._]*\\(-[a-zA-Z][a-zA-Z0-9._]*\\)+" . default)
101 (cons (rnc-make-regexp-choice rnc-atoms) 'italic)
102 (cons (rnc-make-regexp-choice rnc-keywords) font-lock-keyword-face)
103 )
104 "RNC Highlighting")
105
106
107(defun rnc-find-column (first start)
108 "Find which column to indent to."
109
110 ;; FIXME: backward-sexp doesn't work with unbalanced braces in comments
111
112 (let* (column
113 pos
114 ;; Find start of enclosing block or assignment
115 (token
116 (if (member first '("]" "}" ")"))
117 (progn
118 (goto-char (+ start 1))
119 (backward-sexp)
120 (beginning-of-line)
121 (re-search-forward "\\S ")
122 (setq pos (point))
123 (setq column (- (current-column) 1))
124 'lpar)
125 (catch 'done
126 (while (setq pos (re-search-backward "[{}()=]\\|\\[\\|\\]"
127 (point-min) t))
128 (let ((c (match-string 0)))
129 (beginning-of-line)
130 (re-search-forward "\\S ")
131 (setq column (- (current-column) 1))
132 (beginning-of-line)
133 (cond
134 ;; Don't match inside comments
135 ;; FIXME: Should exclude matches inside string literals too
136 ((re-search-forward "#" pos t) (beginning-of-line))
137 ;; Skip block
138 ((member c '("]" "}" ")"))
139 (goto-char (+ pos 1))
140 (backward-sexp))
141
142 ((string= c "=") (throw 'done 'eq))
143 (t (throw 'done 'lpar)))))))))
144
145 (cond
146 ((not pos) 0)
147 ((member first '("]" "}" ")")) column)
148 ((member first '("{" "(")) (+ column rnc-indent-level))
149
150 ;; Give lines starting with an operator a small negative indent.
151 ;; This allows for the following indentation style:
152 ;; foo =
153 ;; bar
154 ;; | baz
155 ;; | oof
156 ((member first '("," "&" "|")) (+ column (- rnc-indent-level 2)))
157
158 ;; Check if first preceding non-whitespace character was an operator
159 ;; If not, this is most likely a new assignment.
160 ;; FIXME: This doesn't play well with name classes starting on a new
161 ;; line
162 ((eq token 'eq)
163 (goto-char start)
164 (if (and (re-search-backward "[^ \t\n]" (point-min) t)
165 (member (match-string 0) '("&" "|" "," "=" "~")))
166 (+ column rnc-indent-level)
167 column))
168
169 (t (+ column rnc-indent-level)))))
170
171(defun rnc-indent-line ()
172 "Indents the current line."
173 (interactive)
174 (let ((orig-point (point)))
175 (beginning-of-line)
176 (let* ((beg-of-line (point))
177 (pos (re-search-forward "\\(\\S \\|\n\\)" (point-max) t))
178 (first (match-string 0))
179 (start (match-beginning 0))
180 (col (- (current-column) 1)))
181
182 (goto-char beg-of-line)
183
184 (let ((indent-column (rnc-find-column first start)))
185 (goto-char beg-of-line)
186
187 (cond
188 ;; Only modify buffer if the line must be reindented
189 ((not (= col indent-column))
190 (if (not (or (null pos)
191 (= beg-of-line start)))
192 (kill-region beg-of-line start))
193
194 (goto-char beg-of-line)
195
196 (while (< 0 indent-column)
197 (insert " ")
198 (setq indent-column (- indent-column 1))))
199
200 ((< orig-point start) (goto-char start))
201 (t (goto-char orig-point)))))))
202
203
204(defun rnc-electric-brace (arg)
205 (interactive "*P")
206 (self-insert-command (prefix-numeric-value arg))
207 (rnc-indent-line)
208 (let ((p (point)))
209 (when (save-excursion
210 (beginning-of-line)
211 (let ((pos (re-search-forward "\\S " (point-max) t)))
212 (and pos (= (- pos 1) p))))
213 (forward-char-command))))
214
215(defvar rnc-mode-map () "Keymap used in RNC mode.")
216(when (not rnc-mode-map)
217 (setq rnc-mode-map (make-sparse-keymap))
218 (define-key rnc-mode-map "\C-c\C-c" 'comment-region)
219 (define-key rnc-mode-map "}" 'rnc-electric-brace)
220 (define-key rnc-mode-map "{" 'rnc-electric-brace)
221 (define-key rnc-mode-map "]" 'rnc-electric-brace)
222 (define-key rnc-mode-map "[" 'rnc-electric-brace))
223
224(defun rnc-mode ()
225 "Major mode for editing RELAX NG Compact Syntax schemas.
226\\{rnc-mode-map}"
227 (interactive)
228
229 (kill-all-local-variables)
230
231 (make-local-variable 'indent-line-function)
232 (setq indent-line-function 'rnc-indent-line)
233
234 (make-local-variable 'font-lock-defaults)
235 (setq font-lock-defaults '(rnc-font-lock-keywords nil t nil nil))
236
237 (use-local-map rnc-mode-map)
238
239 (make-local-variable 'comment-start)
240 (make-local-variable 'comment-end)
241 (make-local-variable 'comment-start-skip)
242
243 (setq comment-start "#"
244 comment-end ""
245 comment-start-skip "\\([ \n\t]+\\)##?[ \n\t]+")
246
247 (let ((rnc-syntax-table (copy-syntax-table)))
248 (modify-syntax-entry ?# "< " rnc-syntax-table)
249 (modify-syntax-entry ?\n "> " rnc-syntax-table)
250 (modify-syntax-entry ?\^m "> " rnc-syntax-table)
251 (modify-syntax-entry ?\\ "w " rnc-syntax-table)
252 (modify-syntax-entry ?' "\" " rnc-syntax-table)
253 (modify-syntax-entry ?. "w " rnc-syntax-table)
254 (modify-syntax-entry ?- "w " rnc-syntax-table)
255 (modify-syntax-entry ?_ "w " rnc-syntax-table)
256 (set-syntax-table rnc-syntax-table))
257
258 (setq mode-name "RNC"
259 major-mode 'rnc-mode)
260 (run-hooks 'rnc-mode-hook))
261
262(provide 'rnc-mode)