Blame


1 7f103319 2021-11-06 op ;;; a68-mode.el --- Major mode for editing Algol 68 code
2 7f103319 2021-11-06 op
3 7f103319 2021-11-06 op ;; Copyright (C) 2011 Jose E. Marchesi
4 7f103319 2021-11-06 op
5 7f103319 2021-11-06 op ;; Maintainer: Jose E. Marchesi
6 7f103319 2021-11-06 op
7 7f103319 2021-11-06 op ;; This file is NOT part of GNU Emacs.
8 7f103319 2021-11-06 op
9 7f103319 2021-11-06 op ;; This program is free software; you can redistribute it and/or modify
10 7f103319 2021-11-06 op ;; it under the terms of the GNU General Public License as published by
11 7f103319 2021-11-06 op ;; the Free Software Foundation; either version 3, or (at your option)
12 7f103319 2021-11-06 op ;; any later version.
13 7f103319 2021-11-06 op
14 7f103319 2021-11-06 op ;; This program is distributed in the hope that it will be useful,
15 7f103319 2021-11-06 op ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 7f103319 2021-11-06 op ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 7f103319 2021-11-06 op ;; GNU General Public License for more details.
18 7f103319 2021-11-06 op
19 7f103319 2021-11-06 op ;; You should have received a copy of the GNU General Public License
20 7f103319 2021-11-06 op ;; along with this program; see the file COPYING. If not, write to the
21 7f103319 2021-11-06 op ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 7f103319 2021-11-06 op ;; Boston, MA 02110-1301, USA.
23 7f103319 2021-11-06 op
24 7f103319 2021-11-06 op ;;; Commentary:
25 7f103319 2021-11-06 op
26 7f103319 2021-11-06 op ;; A major mode for editing Algol 68 code.
27 7f103319 2021-11-06 op ;;
28 7f103319 2021-11-06 op ;; TODO: support quote and dot stropping.
29 7f103319 2021-11-06 op
30 7f103319 2021-11-06 op ;;; Code:
31 7f103319 2021-11-06 op
32 7f103319 2021-11-06 op (require 'syntax)
33 7f103319 2021-11-06 op (require 'font-lock)
34 7f103319 2021-11-06 op
35 7f103319 2021-11-06 op (defvar a68-indent-step 3
36 a6ba7179 2021-11-06 op "Indentation step for Algol 68.")
37 7f103319 2021-11-06 op
38 7f103319 2021-11-06 op (defvar a68-mode-hook nil)
39 7f103319 2021-11-06 op
40 7f103319 2021-11-06 op (defvar a68-mode-map
41 7f103319 2021-11-06 op (let ((map (make-keymap)))
42 7f103319 2021-11-06 op (define-key map "\C-j" 'newline-and-indent)
43 7f103319 2021-11-06 op (define-key map "\r" 'electric-a68-terminate-line)
44 7f103319 2021-11-06 op (define-key map "\t" 'electric-a68-tab)
45 7f103319 2021-11-06 op map)
46 a6ba7179 2021-11-06 op "Keymap for Algol 68 major mode.")
47 7f103319 2021-11-06 op
48 7f103319 2021-11-06 op ;;;###autoload
49 7f103319 2021-11-06 op (add-to-list 'auto-mode-alist '("\\.a68\\'" . a68-mode))
50 7f103319 2021-11-06 op
51 7f103319 2021-11-06 op (defconst a68-font-lock-keywords
52 7f103319 2021-11-06 op (list
53 7f103319 2021-11-06 op (cons (concat "\\<\\("
54 7f103319 2021-11-06 op "DECS\\|PROGRAM\\|CONTEXT\\|USE\\|FINISH\\|KEEP"
55 7f103319 2021-11-06 op "\\|ALIEN"
56 7f103319 2021-11-06 op "\\|MODE\\|OP\\|PRIO\\|PROC"
57 7f103319 2021-11-06 op "\\|PROC"
58 7f103319 2021-11-06 op "\\|OF\\|AT\\|IS\\|ISNT\\|EMPTY\\|SKIP"
59 7f103319 2021-11-06 op "\\|PR\\|PRAGMAT"
60 7f103319 2021-11-06 op "\\|CASE\\|IN\\|OUSE\\|OUT\\|ESAC\\|"
61 7f103319 2021-11-06 op "\\|FOR\\|FORALL\\|FROM\\|TO\\|BY\\|WHILE\\|DO\\|OD"
62 7f103319 2021-11-06 op "\\|IF\\|THEN\\|ELIF\\|THEN\\|ELSE\\|FI"
63 7f103319 2021-11-06 op "\\|PAR\\|BEGIN\\|END\\|GOTO\\|EXIT"
64 7f103319 2021-11-06 op "\\|LWB\\|UPB\\|NOT\\|ABS\\|BIN\\|REPR\\|LENG\\|SHORTEN\\|ODD\\|SIGN\\|ROUND\\ENTIER"
65 7f103319 2021-11-06 op "\\|AND\\|OR\\|DIV\\|OVER\\|MOD\\|ELEM\\|SHL\\|SHR\\|IS\\|ISNT"
66 7f103319 2021-11-06 op "\\|OVERAB\\|DIVAB\\|MODAB"
67 7f103319 2021-11-06 op "\\|REF"
68 7f103319 2021-11-06 op "\\)\\>")
69 7f103319 2021-11-06 op 'font-lock-keyword-face)
70 7f103319 2021-11-06 op (cons (concat "\\<\\("
71 7f103319 2021-11-06 op "TRUE\\|\\FALSE"
72 7f103319 2021-11-06 op "\\)\\>")
73 7f103319 2021-11-06 op 'font-lock-constant-face)
74 7f103319 2021-11-06 op ;; Note that the following rule is only valid for bold stropping.
75 7f103319 2021-11-06 op (cons (concat "\\<[A-Z]+\\>") 'font-lock-type-face)
76 7f103319 2021-11-06 op
77 7f103319 2021-11-06 op (cons "\\('\\w*'\\)"
78 7f103319 2021-11-06 op font-lock-variable-name-face))
79 a6ba7179 2021-11-06 op "Highlighting expressions for Algol 68 mode.")
80 7f103319 2021-11-06 op
81 7f103319 2021-11-06 op (defun a68-within-string ()
82 a6ba7179 2021-11-06 op "Check if inside a string."
83 7f103319 2021-11-06 op (nth 3 (syntax-ppss)))
84 7f103319 2021-11-06 op
85 7f103319 2021-11-06 op (defun a68-within-comment ()
86 a6ba7179 2021-11-06 op "Check if inside a comment."
87 7f103319 2021-11-06 op (nth 4 (syntax-ppss)))
88 7f103319 2021-11-06 op
89 7f103319 2021-11-06 op ;; Indentation rules:
90 7f103319 2021-11-06 op ;;
91 7f103319 2021-11-06 op ;; - If we are at the beginning of the buffer, or looking at some
92 7f103319 2021-11-06 op ;; indent-0 content, indent to column 0.
93 7f103319 2021-11-06 op ;;
94 7f103319 2021-11-06 op ;; - If we are currently at an END, ), FI or OD, then de-indent
95 7f103319 2021-11-06 op ;; relative to the previous line.
96 7f103319 2021-11-06 op ;;
97 7f103319 2021-11-06 op ;; - If we first see and "end line" before our current line,
98 7f103319 2021-11-06 op ;; then we should indent our current line to the same indentation as
99 7f103319 2021-11-06 op ;; the end line.
100 7f103319 2021-11-06 op ;;
101 7f103319 2021-11-06 op ;; - If we first see a "start line" like IF, then we need to increase
102 7f103319 2021-11-06 op ;; our indentation relative to that start line.
103 7f103319 2021-11-06 op ;;
104 7f103319 2021-11-06 op ;; - If into a balanced expression, we should indent to the column
105 7f103319 2021-11-06 op ;; where the start of the innermost parenthetical group.
106 7f103319 2021-11-06 op ;;
107 7f103319 2021-11-06 op ;; - If none of the above apply, then do not indent at all.
108 7f103319 2021-11-06 op
109 7f103319 2021-11-06 op (defun a68-indent-line ()
110 a6ba7179 2021-11-06 op "Indent current line as Algol 68 code."
111 7f103319 2021-11-06 op (interactive)
112 7f103319 2021-11-06 op (let ((case-fold-search nil))
113 7f103319 2021-11-06 op (save-excursion
114 7f103319 2021-11-06 op (beginning-of-line)
115 7f103319 2021-11-06 op (if (nth 1 (syntax-ppss)) ; Check for rule 5
116 7f103319 2021-11-06 op (let ((offset (save-excursion (goto-char (+ (nth 1 (syntax-ppss)) 1))
117 7f103319 2021-11-06 op (current-column))))
118 7f103319 2021-11-06 op (indent-line-to offset))
119 7f103319 2021-11-06 op (if (or (bobp) ; Check for rule 1
120 7f103319 2021-11-06 op (looking-at "^[ \t]*\\<\\(KEEP\\|FINISH\\|DECS\\|USE\\|PROGRAM\\)\\>"))
121 7f103319 2021-11-06 op (indent-line-to 0)
122 7f103319 2021-11-06 op (let ((not-indented t)
123 7f103319 2021-11-06 op (prev-indent (current-indentation))
124 7f103319 2021-11-06 op (begin-indent-re "^[ \t]*\\<\\(PAR\\|BEGIN\\|KEEP\\|IF\\|DO\\|ELSE\\|ELIF\\|THEN\\)")
125 7f103319 2021-11-06 op (deindent-line-re "^[ \t]*\\<\\(END\\|FI\\|OD\\|ELSE\\|ELIF\\)\\>")
126 7f103319 2021-11-06 op (eqindent-line-re "^[ \t]*\\<\\(THEN\\)\\>")
127 7f103319 2021-11-06 op (end-line-re "^[ \t]*\\(END\\|FI\\|OD\\)")
128 7f103319 2021-11-06 op cur-indent)
129 7f103319 2021-11-06 op (if (looking-at eqindent-line-re)
130 7f103319 2021-11-06 op (save-excursion
131 7f103319 2021-11-06 op (forward-line -1)
132 7f103319 2021-11-06 op (setq cur-indent (current-indentation)))
133 7f103319 2021-11-06 op (if (looking-at deindent-line-re) ; Check for rule 2
134 7f103319 2021-11-06 op (progn
135 7f103319 2021-11-06 op (save-excursion
136 7f103319 2021-11-06 op (forward-line -1)
137 7f103319 2021-11-06 op (setq cur-indent (- (current-indentation) a68-indent-step)))
138 7f103319 2021-11-06 op (if (< cur-indent 0)
139 7f103319 2021-11-06 op (setq cur-indent 0)))
140 7f103319 2021-11-06 op (save-excursion
141 7f103319 2021-11-06 op (while not-indented
142 7f103319 2021-11-06 op (forward-line -1)
143 7f103319 2021-11-06 op (if (looking-at end-line-re) ; Check for rule 3
144 7f103319 2021-11-06 op (progn
145 7f103319 2021-11-06 op (setq cur-indent (current-indentation))
146 7f103319 2021-11-06 op (setq not-indented nil))
147 7f103319 2021-11-06 op ;; Check for rule 4
148 7f103319 2021-11-06 op (if (looking-at begin-indent-re)
149 7f103319 2021-11-06 op (progn
150 7f103319 2021-11-06 op (setq cur-indent (+ (current-indentation) a68-indent-step))
151 7f103319 2021-11-06 op (setq not-indented nil))
152 7f103319 2021-11-06 op (if (bobp) ; Check for rule 5
153 7f103319 2021-11-06 op (setq not-indented nil))))))))
154 7f103319 2021-11-06 op (if cur-indent
155 7f103319 2021-11-06 op (indent-line-to cur-indent)
156 7f103319 2021-11-06 op ;; If we didn't see an indentation hint, then allow no
157 7f103319 2021-11-06 op ;; indentation.
158 7f103319 2021-11-06 op (indent-line-to 0)))))))
159 7f103319 2021-11-06 op (when (< (current-column) (current-indentation))
160 7f103319 2021-11-06 op (move-to-column (current-indentation))))
161 7f103319 2021-11-06 op
162 7f103319 2021-11-06 op (defvar a68-mode-syntax-table
163 7f103319 2021-11-06 op (let ((st (make-syntax-table)))
164 7f103319 2021-11-06 op (modify-syntax-entry ?{ "<" st)
165 7f103319 2021-11-06 op (modify-syntax-entry ?# "<" st)
166 7f103319 2021-11-06 op (modify-syntax-entry ?} ">" st)
167 7f103319 2021-11-06 op (modify-syntax-entry ?# ">" st)
168 7f103319 2021-11-06 op (modify-syntax-entry ?\\ "." st)
169 7f103319 2021-11-06 op ;; (modify-syntax-entry ?C "< 13" st)
170 7f103319 2021-11-06 op ;; (modify-syntax-entry ?O "> 24" st)
171 7f103319 2021-11-06 op ;; define parentheses to match
172 7f103319 2021-11-06 op (modify-syntax-entry ?\( "()" st)
173 7f103319 2021-11-06 op (modify-syntax-entry ?\) ")(" st)
174 7f103319 2021-11-06 op st))
175 7f103319 2021-11-06 op
176 7f103319 2021-11-06 op ;;;
177 7f103319 2021-11-06 op ;;; Electric functions
178 7f103319 2021-11-06 op ;;;
179 7f103319 2021-11-06 op
180 7f103319 2021-11-06 op (defconst a68-autoindent-lines-re
181 7f103319 2021-11-06 op "\\<\\(BEGIN\\|END\\|ELSE\\|ELIF\\|DO\\|OD\\|CASE\\|ESAC\\|IN\\|OUT\\)\\>")
182 7f103319 2021-11-06 op
183 7f103319 2021-11-06 op (defun electric-a68-terminate-line ()
184 7f103319 2021-11-06 op "Terminate line and indent next line."
185 7f103319 2021-11-06 op (interactive)
186 7f103319 2021-11-06 op ;; First, check if current line should be indented
187 7f103319 2021-11-06 op (save-excursion
188 7f103319 2021-11-06 op (beginning-of-line)
189 7f103319 2021-11-06 op (skip-chars-forward " \t")
190 7f103319 2021-11-06 op (if (looking-at a68-autoindent-lines-re)
191 7f103319 2021-11-06 op (a68-indent-line)))
192 7f103319 2021-11-06 op (delete-horizontal-space) ; Removes triling whitespaces
193 7f103319 2021-11-06 op ;; Indent next line if we are not in a string
194 7f103319 2021-11-06 op (let ((in-string (a68-within-string)))
195 7f103319 2021-11-06 op (newline)
196 7f103319 2021-11-06 op (unless in-string
197 7f103319 2021-11-06 op (a68-indent-line))))
198 7f103319 2021-11-06 op
199 7f103319 2021-11-06 op (defun electric-a68-tab ()
200 7f103319 2021-11-06 op "Function called when TAB is pressed in Algol68 mode."
201 7f103319 2021-11-06 op (interactive)
202 7f103319 2021-11-06 op (unless (save-excursion
203 7f103319 2021-11-06 op (beginning-of-line)
204 7f103319 2021-11-06 op (a68-within-string))
205 7f103319 2021-11-06 op (a68-indent-line)))
206 7f103319 2021-11-06 op
207 962671ab 2021-11-06 op ;;;###autoload
208 962671ab 2021-11-06 op (define-derived-mode a68-mode prog-mode "Algol68"
209 962671ab 2021-11-06 op "Major mode for editing Alogl68 files."
210 962671ab 2021-11-06 op (setq-local font-lock-defaults '(a68-font-lock-keywords))
211 962671ab 2021-11-06 op (setq-local indent-line-function #'a68-indent-line)
212 962671ab 2021-11-06 op (setq-local comment-start "#")
213 64609eee 2021-11-06 op (setq-local comment-end "#"))
214 7f103319 2021-11-06 op
215 6c0a5a76 2021-11-06 op ;;;###autoload
216 6c0a5a76 2021-11-06 op (add-to-list 'auto-mode-alist '("\\.a68\\'" . a68-mode))
217 6c0a5a76 2021-11-06 op
218 7f103319 2021-11-06 op (provide 'algol-mode)
219 a6ba7179 2021-11-06 op ;;; algol-mode.el ends here