5
|
1 ;; octave-mode.el - major mode for editing Octave source with GNU Emacs |
|
2 ;; |
|
3 ;; This major mode for GNU Emacs provides support for editing Octave |
|
4 ;; source files. It automatically indents for block structures, line |
|
5 ;; continuations (e.g., ...), and comments. The usual paren matching |
|
6 ;; support is included. Indenting for continued matrix expressions is |
|
7 ;; currently not supported. Perhaps it will be in the future. Auto-fill |
|
8 ;; mode seems to actually work! For convient use add something like the |
|
9 ;; following to your .emacs start-up file: |
|
10 ;; |
|
11 ;; (autoload 'octave-mode "octave-mode" "Enter Octave-mode." t) |
|
12 ;; (setq auto-mode-alist (cons '("\\.m$" . octave-mode) auto-mode-alist)) |
|
13 ;; (setq octave-mode-hook '(lambda () (setq fill-column 74))) |
|
14 ;; |
|
15 ;; Enjoy. |
|
16 ;; |
|
17 ;; Last modified Sun Mar 7 17:55:20 1993. |
|
18 ;; |
|
19 ;; This file was modified by John W. Eaton (jwe@che.utexas.edu) from |
|
20 ;; the file matlab-mode.el which is: |
|
21 ;; |
|
22 ;; Copyright (C) 1991 Matthew R. Wette. |
|
23 ;; Everyone is granted permission to copy, modify and redistribute this |
|
24 ;; file provided: |
|
25 ;; 1. All copies contain this copyright notice. |
|
26 ;; 2. All modified copies shall carry a prominant notice stating who |
|
27 ;; made the last modification and the date of such modification. |
|
28 ;; 3. No charge is made for this software or works derived from it. |
|
29 ;; This clause shall not be construed as constraining other software |
|
30 ;; distributed on the same medium as this software, nor is a |
|
31 ;; distribution fee considered a charge. |
|
32 ;; |
|
33 ;; Version 1.01, dated 25Jan91 |
|
34 ;; |
|
35 ;; 25Jan91 by Matt Wette, mwette@csi.jpl.nasa.gov |
|
36 ;; Got indentation of matrix expression to work, I think. Also, |
|
37 ;; added tabs to comment start regular-expression. |
|
38 ;; |
|
39 ;; 14Jan91 by Matt Wette, mwette@csi.jpl.nasa.gov |
|
40 ;; Added functions (ml-unbal-matexp ml-matexp-indent) for matrix |
|
41 ;; expressions. |
|
42 ;; |
|
43 ;; 07Jan91 by Matt Wette, mwette@csi.jpl.nasa.gov |
|
44 ;; Many changes. Seems to work reasonably well. Still would like |
|
45 ;; to add some support for filling in comments and handle continued |
|
46 ;; matrix expressions. Released as Version 1.0. |
|
47 ;; |
|
48 ;; 04Jan91 by Matt Wette, mwette@csi.jpl.nasa.gov |
|
49 ;; Created. Used eiffel.el as a guide. |
|
50 |
|
51 |
|
52 ;; Constants used in all Octave-mode buffers. |
|
53 (defconst octave-indent-level 2 |
|
54 "*The indentation in Octave-mode.") |
|
55 |
|
56 (defconst octave-comment-column 40 |
|
57 "*The goal comment column in Octave-mode buffers.") |
|
58 |
|
59 |
|
60 ;; Syntax Table |
|
61 (defvar octave-mode-syntax-table nil |
|
62 "Syntax table used in Octave-mode buffers.") |
|
63 |
|
64 (if octave-mode-syntax-table |
|
65 () |
|
66 (setq octave-mode-syntax-table (make-syntax-table)) |
|
67 (modify-syntax-entry ?\\ "." octave-mode-syntax-table) |
|
68 (modify-syntax-entry ?/ "." octave-mode-syntax-table) |
|
69 (modify-syntax-entry ?* "." octave-mode-syntax-table) |
|
70 (modify-syntax-entry ?+ "." octave-mode-syntax-table) |
|
71 (modify-syntax-entry ?- "." octave-mode-syntax-table) |
|
72 (modify-syntax-entry ?= "." octave-mode-syntax-table) |
|
73 (modify-syntax-entry ?< "." octave-mode-syntax-table) |
|
74 (modify-syntax-entry ?> "." octave-mode-syntax-table) |
|
75 (modify-syntax-entry ?& "." octave-mode-syntax-table) |
|
76 (modify-syntax-entry ?| "." octave-mode-syntax-table) |
|
77 (modify-syntax-entry ?\' "\"" octave-mode-syntax-table) |
|
78 (modify-syntax-entry ?# "<" octave-mode-syntax-table) |
|
79 (modify-syntax-entry ?% "<" octave-mode-syntax-table) |
|
80 (modify-syntax-entry ?\n ">" octave-mode-syntax-table) |
|
81 (set-syntax-table octave-mode-syntax-table)) |
|
82 |
|
83 |
|
84 ;; Abbrev Table |
|
85 (defvar octave-mode-abbrev-table nil |
|
86 "Abbrev table used in Octave-mode buffers.") |
|
87 |
|
88 (define-abbrev-table 'octave-mode-abbrev-table ()) |
|
89 |
|
90 |
|
91 ;; Mode Map |
|
92 (defvar octave-mode-map () |
|
93 "Keymap used in octave-mode.") |
|
94 |
|
95 (if octave-mode-map |
|
96 () |
|
97 (setq octave-mode-map (make-sparse-keymap)) |
|
98 (define-key octave-mode-map "\r" 'octave-return) |
|
99 (define-key octave-mode-map "\t" 'octave-indent-line) |
|
100 (define-key octave-mode-map "\M-;" 'octave-comment) |
|
101 (define-key octave-mode-map "\C-ct" 'octave-line-type) |
|
102 (define-key octave-mode-map "\C-ci" 'octave-indent-type) |
|
103 (define-key octave-mode-map "\M-\r" 'newline)) |
|
104 |
|
105 |
|
106 ;; Octave Mode |
|
107 (defun octave-mode () |
|
108 "Major mode for editing Octave source files. Version 1.0, 23 Feb 1993. |
|
109 Will run octave-mode-hook if it is non-nil. Auto-fill-mode seems to work. |
|
110 Filling does not work (yet). |
|
111 Special Key Bindings: |
|
112 \\{octave-mode-map} |
|
113 Variables: |
|
114 octave-indent-level Level to indent blocks. |
|
115 octave-comment-column Goal column for on-line comments. |
|
116 fill-column Column used in auto-fill (default=70). |
|
117 Commands: |
|
118 octave-mode Enter Octave major mode. |
|
119 octave-return Handle return with indenting. |
|
120 octave-indent-line Indent line for structure. |
|
121 octave-comment Add comment to current line. |
|
122 octave-comment-indent Compute indent for comment. |
|
123 octave-line-type Tell current line type (for debugging). |
|
124 octave-indent-type Tell last indent type (for debugging). |
|
125 To add automatic support put something like the following in your .emacs file: |
|
126 \(autoload 'octave-mode \"octave-mode\" \"Enter Octave-mode.\" t\) |
|
127 \(setq auto-mode-alist \(cons '\(\"\\\\.m$\" . octave-mode\) \ |
|
128 auto-mode-alist\)\) |
|
129 \(setq octave-mode-hook '\(lambda \(\) \(setq fill-column 74\)\)\)" |
|
130 (interactive) |
|
131 (kill-all-local-variables) |
|
132 (use-local-map octave-mode-map) |
|
133 (setq major-mode 'octave-mode) |
|
134 (setq mode-name "Octave") |
|
135 (setq local-abbrev-table octave-mode-abbrev-table) |
|
136 (set-syntax-table octave-mode-syntax-table) |
|
137 (make-local-variable 'paragraph-start) |
|
138 (setq paragraph-start (concat "^$\\|" page-delimiter)) |
|
139 (make-local-variable 'paragraph-separate) |
|
140 (setq paragraph-separate paragraph-start) |
|
141 (make-local-variable 'paragraph-ignore-fill-prefix) |
|
142 (setq paragraph-ignore-fill-prefix t) |
|
143 (make-local-variable 'indent-line-function) |
|
144 (setq indent-line-function 'octave-indent-line) |
|
145 (make-local-variable 'comment-start-skip) |
|
146 (setq comment-start-skip "[%#][ \t]*") |
|
147 (make-local-variable 'comment-column) |
|
148 (setq comment-column 'octave-comment-column) |
|
149 (make-local-variable 'comment-indent-hook) |
|
150 (setq comment-indent-hook 'octave-comment-indent) |
|
151 (make-local-variable 'fill-column) |
|
152 (setq fill-column default-fill-column) |
|
153 (run-hooks 'octave-mode-hook)) |
|
154 |
|
155 |
|
156 (defun octave-return () |
|
157 "Handle carriage return in Octave-mode." |
|
158 (interactive) |
|
159 (if (oct-block-end-line) |
|
160 (octave-indent-line)) |
|
161 (newline) |
|
162 (octave-indent-line)) |
|
163 |
|
164 (defun octave-comment () |
|
165 "Add a comment to the following line, or format if one already exists." |
|
166 (interactive) |
|
167 (cond |
|
168 ((oct-empty-line) |
|
169 (octave-indent-line) |
|
170 (insert "# ")) |
|
171 ((oct-comment-line)) |
|
172 (t |
|
173 (end-of-line) |
|
174 (re-search-backward "[^ \t^]" 0 t) |
|
175 (forward-char) |
|
176 (delete-horizontal-space) |
|
177 (if (< (current-column) octave-comment-column) |
|
178 (indent-to octave-comment-column) |
|
179 (insert " ")) |
|
180 (insert "# ")))) |
|
181 |
|
182 (defun octave-comment-indent () |
|
183 "Indent a comment line in Octave-mode." |
|
184 (oct-calc-indent)) |
|
185 |
|
186 (defun octave-indent-line () |
|
187 "Indent a line in Octave-mode." |
|
188 (interactive) |
|
189 (save-excursion |
|
190 (beginning-of-line) |
|
191 (delete-horizontal-space) |
|
192 (indent-to (oct-calc-indent))) |
|
193 (skip-chars-forward " \t")) |
|
194 |
|
195 (defun octave-line-type () |
|
196 "Display type of current line. Used in debugging." |
|
197 (interactive) |
|
198 (cond |
|
199 ((oct-empty-line) |
|
200 (message "octave-line-type: empty-line")) |
|
201 ((oct-comment-line) |
|
202 (message "octave-line-type: comment-line")) |
|
203 ((oct-continuation-line) |
|
204 (message "octave-line-type: continuation-line")) |
|
205 ((oct-block-beg-end-line) |
|
206 (message "octave-line-type: block-beg-end-line")) |
|
207 ((oct-block-beg-line) |
|
208 (message "octave-line-type: block-beg-line")) |
|
209 ((oct-block-end-line) |
|
210 (message "octave-line-type: block-end-line")) |
|
211 (t |
|
212 (message "octave-line-type: other")))) |
|
213 |
|
214 (defun octave-indent-type () |
|
215 "Display type of current or previous nonempty line. Used in debugging." |
|
216 (interactive) |
|
217 (message (concat "octave-ident-type: " oct-last-indent-type))) |
|
218 |
|
219 (defun octave-fill-region (from to &optional justify-flag) |
|
220 "Fill the region of comments. |
|
221 Prefix arg (non-nil third arg, if called from program) |
|
222 means justify as well." |
|
223 (interactive "r\nP") |
|
224 (messages "octave-fill-region not implemented yet.")) |
|
225 |
|
226 (defvar oct-last-indent-type "unknown" |
|
227 "String to tell line type.") |
|
228 |
|
229 (defun oct-calc-indent () |
|
230 "Return the appropriate indentation for this line as an int." |
|
231 (let ((indent 0)) |
|
232 (save-excursion |
|
233 (forward-line -1) ; compute indent based on previous |
|
234 (if (oct-empty-line) ; non-empty line |
|
235 (re-search-backward "[^ \t\n]" 0 t)) |
|
236 (cond |
|
237 ((oct-empty-line) |
|
238 (setq oct-last-indent-type "empty")) |
|
239 ((oct-comment-line) |
|
240 (setq oct-last-indent-type "comment")) |
|
241 ((oct-continuation-line) |
|
242 (setq oct-last-indent-type "continuation") |
|
243 (setq indent (* 2 octave-indent-level))) |
|
244 ((oct-block-beg-end-line) |
|
245 (setq oct-last-indent-type "block begin-end")) |
|
246 ((oct-block-beg-line) |
|
247 (setq oct-last-indent-type "block begin") |
|
248 (setq indent octave-indent-level)) |
|
249 ((oct-unbal-matexp-line) |
|
250 (setq oct-last-indent-type "unbalanced-matrix-expression") |
|
251 (setq indent (oct-calc-matexp-indent))) |
|
252 (t |
|
253 (setq oct-last-indent-type "other"))) |
|
254 (setq indent (+ indent (current-indentation))) |
|
255 (if (= 0 (forward-line -1)) |
|
256 (if (oct-continuation-line) |
|
257 (setq indent (- indent (* 2 octave-indent-level)))))) |
|
258 (if (oct-block-end-line) (setq indent (- indent octave-indent-level))) |
|
259 (if (< indent 0) (setq indent 0)) |
|
260 indent)) |
|
261 |
|
262 |
|
263 (defun oct-empty-line () |
|
264 "Returns t if current line is empty." |
|
265 (save-excursion |
|
266 (beginning-of-line) |
|
267 (looking-at "^[ \t]*$"))) |
|
268 |
|
269 (defun oct-comment-line () |
|
270 "Returns t if current line is an Octave comment line." |
|
271 (save-excursion |
|
272 (beginning-of-line) |
|
273 (skip-chars-forward " \t") |
|
274 (looking-at "[%#]"))) |
|
275 |
|
276 (defun oct-continuation-line () |
|
277 "Returns t if current line ends in ... and optional comment." |
|
278 (save-excursion |
|
279 (beginning-of-line) |
|
280 (re-search-forward "\\.\\.\\.+[ \t]*\\(%.*\\)?$" (oct-eoln-point) t))) |
|
281 |
|
282 (defun oct-eoln-point () |
|
283 "Returns point for end-of-line in Octave-mode." |
|
284 (save-excursion |
|
285 (end-of-line) |
|
286 (point))) |
|
287 |
|
288 (defun oct-block-beg-line () |
|
289 "Returns t if line contains beginning of Octave block." |
|
290 (save-excursion |
|
291 (beginning-of-line) |
|
292 (looking-at (concat "\\([^%#\n]*[ \t]\\)?" oct-block-beg-kw)))) |
|
293 |
|
294 (defconst oct-block-beg-kw "\\(for\\|while\\|if\\|else\\|elseif\\|function\\)" |
|
295 "Regular expression for keywords which begin blocks in Octave-mode.") |
|
296 |
|
297 (defun oct-block-end-line () |
|
298 "Returns t if line contains end of Octave block." |
|
299 (save-excursion |
|
300 (beginning-of-line) |
|
301 (looking-at (concat "\\([^%#\n]*[ \t]\\)?" oct-block-end-kw)))) |
|
302 |
|
303 (defconst oct-block-end-kw "\\(end\\|endfor\\|endwhile\\|endif\\|endfunction\\|else\\|elseif\\)" |
|
304 "Regular expression for keywords which end blocks.") |
|
305 |
|
306 (defun oct-block-beg-end-line () |
|
307 "Returns t if line contains matching block begin-end in Octave-mode." |
|
308 (save-excursion |
|
309 (beginning-of-line) |
|
310 (looking-at (concat |
|
311 "\\([^%#\n]*[ \t]\\)?" oct-block-beg-kw |
|
312 "." "\\([^%#\n]*[ \t]\\)?" oct-block-end-kw)))) |
|
313 |
|
314 (defun oct-unbal-matexp-line () |
|
315 (if (= (oct-calc-matexp-indent) 0) |
|
316 () |
|
317 t)) |
|
318 |
|
319 (defun oct-calc-matexp-indent () |
|
320 (let ((indent 0)) |
|
321 (save-excursion |
|
322 (beginning-of-line) |
|
323 (while (< (point) (oct-eoln-point)) |
|
324 (cond |
|
325 ((looking-at "\\[") |
|
326 (setq indent (+ indent octave-indent-level))) |
|
327 ((looking-at "\\]") |
|
328 (setq indent (- indent octave-indent-level)))) |
|
329 (forward-char))) |
|
330 (* 2 indent))) |
|
331 |
|
332 (defun oct-comment-on-line () |
|
333 "Returns t if current line contains a comment." |
|
334 (save-excursion |
|
335 (beginning-of-line) |
|
336 (looking-at "[^\n]*[%#]"))) |
|
337 |
|
338 (defun oct-in-comment () |
|
339 "Returns t if point is in a comment." |
|
340 (save-excursion |
|
341 (and (/= (point) (point-max)) (forward-char)) |
|
342 (search-backward "[%#]" (save-excursion (beginning-of-line) (point)) t))) |
|
343 |
|
344 (provide 'octave-mode) |
|
345 |
|
346 ;; --- last line of octave-mode.el --- |