]> code.delx.au - gnu-emacs-elpa/blob - packages/ada-mode/ada-skel.el
53c513ed6b163f2756723e8a95f986d529d3c7a1
[gnu-emacs-elpa] / packages / ada-mode / ada-skel.el
1 ;;; ada-skel.el --- an extension to Ada mode for inserting statement skeletons
2
3 ;; Copyright (C) 1987, 1993, 1994, 1996-2013 Free Software Foundation, Inc.
4
5 ;; Authors: Stephen Leake <stephen_leake@stephe-leake.org>
6
7 ;; This file is part of GNU Emacs.
8
9 ;; GNU Emacs is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
13
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
21
22 ;;; Design:
23 ;;
24 ;; The primary user command is `ada-skel-expand', which inserts the
25 ;; skeleton associated with the previous word (possibly skipping a
26 ;; name).
27 ;;
28 ;; We don't define skeletons that prompt for most of the content; it
29 ;; is easier just to type in the buffer.
30 ;;
31 ;; These skeletons are not intended to teach a novice the language,
32 ;; just to make it easier to write code that the ada-wisi parser
33 ;; likes, and handle repeated names nicely.
34
35 ;;; History:
36
37 ;; Created May 1987.
38 ;; Original version from V. Bowman as in ada.el of Emacs-18
39 ;; (borrowed heavily from Mick Jordan's Modula-2 package for GNU,
40 ;; as modified by Peter Robinson, Michael Schmidt, and Tom Perrine.)
41 ;;
42 ;; Sep 1993. Daniel Pfeiffer <pfeiffer@cict.fr> (DP)
43 ;; Introduced statement.el for smaller code and user configurability.
44 ;;
45 ;; Nov 1993. Rolf Ebert <ebert@enpc.fr> (RE) Moved the
46 ;; skeleton generation into this separate file. The code still is
47 ;; essentially written by DP
48 ;;
49 ;; Adapted Jun 1994. Markus Heritsch
50 ;; <Markus.Heritsch@studbox.uni-stuttgart.de> (MH)
51 ;; added menu bar support for templates
52 ;;
53 ;; 1994/12/02 Christian Egli <cegli@hcsd.hac.com>
54 ;; General cleanup and bug fixes.
55 ;;
56 ;; 1995/12/20 John Hutchison <hutchiso@epi.syr.ge.com>
57 ;; made it work with skeleton.el from Emacs-19.30. Several
58 ;; enhancements and bug fixes.
59 ;;
60 ;; Sep 2013 Stephen Leake renamed to ada-skel (to match skeleton.el),
61 ;; complete re-write: added ada-skel-alist (to get some of the
62 ;; functionality of the sadly missed Else package). Simplified
63 ;; skeletons; just make it easier to work with the ada-wisi parser,
64 ;; don't try to teach syntax.
65
66 (require 'skeleton nil t)
67
68 ;;;;; user variables, example skeletons intended to be overwritten
69
70 (defcustom ada-skel-initial-string "header"
71 "*String to insert in empty buffer.
72 This could end in a token recognized by `ada-skel-expand'."
73 :type 'string
74 :group 'ada
75 :safe 'stringp)
76
77 (define-skeleton ada-skel-user-restricted
78 "Example copyright/license skeleton, with automatic year and owner."
79 ()
80 "-- Copyright (C) " (format-time-string "%Y ") user-full-name " All Rights Reserved.\n"
81 "\n"
82 "pragma License (Restricted);\n"
83 )
84
85 (define-skeleton ada-skel-gpl
86 "Example copyright/license skeleton, with automatic year and owner, GPLv3."
87 ()
88 "-- Copyright (C) " (format-time-string "%Y ") user-full-name " All Rights Reserved.\n"
89 "--\n"
90 "-- This program is free software; you can redistribute it and/or\n"
91 "-- modify it under terms of the GNU General Public License as\n"
92 "-- published by the Free Software Foundation; either version 3, or (at\n"
93 "-- your option) any later version. This program is distributed in the\n"
94 "-- hope that it will be useful, but WITHOUT ANY WARRANTY; without even\n"
95 "-- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n"
96 "-- PURPOSE. See the GNU General Public License for more details. You\n"
97 "-- should have received a copy of the GNU General Public License\n"
98 "-- distributed with this program; see file COPYING. If not, write to\n"
99 "-- the Free Software Foundation, 51 Franklin Street, Suite 500, Boston,\n"
100 "-- MA 02110-1335, USA.\n"
101 "\n"
102 "pragma License (GPL);\n"
103
104 )
105
106 ;;;;; Ada skeletons (alphabetical)
107
108 (define-skeleton ada-skel-accept
109 "Insert accept statement with name from `str'."
110 ()
111 "accept " str " do\n"
112 "end " str ";")
113
114 (define-skeleton ada-skel-case
115 "Insert case statement."
116 ()
117 "case " str " is\n"
118 "when " _ "=>\n"
119 "end case;")
120
121 (define-skeleton ada-skel-declare
122 "Insert a block statement with an optional name (from `str')."
123 ()
124 str & ":\n"
125 "declare\n"
126 _
127 "begin\n"
128 "exception\n"
129 "end " str | -1 ?\;)
130
131 (define-skeleton ada-skel-entry
132 "Insert entry statement with name from `str'."
133 ()
134 "entry " str " when " _ "\n"
135 "is\n"
136 "begin\n"
137 "end " str ";")
138
139 (define-skeleton ada-skel-for
140 "Insert a for loop statement with an optional name (from `str')."
141 ()
142 str & ":\n"
143 "for " _ " loop\n"
144 "end loop " str | -1 ";")
145
146 (define-skeleton ada-skel-function-body
147 "Insert a function body with name from `str'."
148 ()
149 "function " str " return \n"
150 "is\n"
151 "begin\n"
152 _
153 "end " str ";")
154
155 (define-skeleton ada-skel-function-spec
156 "Insert a function type specification with name from `str'."
157 ()
158 "function " str " return ;")
159
160 (define-skeleton ada-skel-header
161 "Insert a file header comment, with automatic copyright year and prompt for copyright owner/license.
162 Each user will probably want to override this."
163 ()
164 "-- Abstract :\n"
165 "--\n"
166 "-- " _ "\n"
167 "--\n"
168 "{copyright_license}\n"
169 )
170
171 (define-skeleton ada-skel-if
172 "Insert an if statement."
173 ()
174 "if " _ " then\n"
175 "elsif then\n"
176 "else\n"
177 "end if;")
178
179 (define-skeleton ada-skel-loop
180 "Insert a loop statement with an optional name (from `str')."
181 ()
182 str & ":\n"
183 "loop\n"
184 "exit " str | -1 " when " _ ";\n"
185 "end loop " str | -1 ";")
186
187 (define-skeleton ada-skel-package-body
188 "Insert a package body with name from `str'."
189 ()
190 "package body " str " is\n"
191 _
192 "begin\n"
193 "end " str ";")
194
195 (define-skeleton ada-skel-package-spec
196 "Insert a package specification with name from `str'.
197 See `ada-find-other-file' to create library level package body from spec."
198 ()
199 "package " str " is\n"
200 _
201 "private\n"
202 "end " str ";")
203
204 (define-skeleton ada-skel-procedure-body
205 "Insert a procedure body with name from `str'."
206 ()
207 "procedure " str "\n"
208 "is\n"
209 "begin\n"
210 _
211 "end " str ";")
212
213 (define-skeleton ada-skel-procedure-spec
214 "Insert a procedure type specification with name from `str'."
215 ()
216 "procedure " str ";")
217
218 (define-skeleton ada-skel-protected-body
219 "Insert a protected body with name from `str'."
220 ()
221 "protected body " str " is\n"
222 _
223 "end " str ";")
224
225 (define-skeleton ada-skel-protected-spec
226 "Insert a protected type specification with name from `str'."
227 ()
228 "protected type " str " is\n"
229 _
230 "private\n"
231 "end " str ";")
232
233 (define-skeleton ada-skel-record
234 "Insert a record type declaration with a type name from `str'."
235 ()
236 "type " str " is record\n"
237 _
238 "end record;")
239
240 (define-skeleton ada-skel-return
241 "Insert an extended return statement."
242 ()
243 "return" _ "\n"
244 "do\n"
245 "end return;")
246
247 (define-skeleton ada-skel-select
248 "Insert a select statement."
249 ()
250 "select\n"
251 _
252 "else\n"
253 "end select;")
254
255 (define-skeleton ada-skel-task-body
256 "Insert a task body with name from `str'."
257 ()
258 "task body " str "\n"
259 "is\n"
260 _
261 "begin\n"
262 "end " str ";")
263
264 (define-skeleton ada-skel-task-spec
265 "Insert a task specification with name from `str'."
266 ()
267 "task " str " is\n"
268 _
269 "end " str ";")
270
271 (define-skeleton ada-skel-while
272 "Insert a while loop statement with an optional name (from `str')."
273 ()
274 str & ":\n"
275 "while " _ " loop\n"
276 "end loop " str | -1 ";")
277
278 (define-skeleton ada-skel-with-use
279 "Insert with and use context clauses with name from `str'."
280 ()
281 "with " str "; use " str ";")
282
283 ;;;;; token alist, other functions
284
285 (defconst ada-skel-token-alist
286 '(("accept" . ada-skel-accept)
287 ("begin" . ada-skel-declare) ;; easy enough to delete the declare
288 ("case" . ada-skel-case)
289 ("copyright_license"
290 ("GPL" . ada-skel-gpl)
291 ("restricted" . ada-skel-user-restricted))
292 ("declare" . ada-skel-declare)
293 ("entry" . ada-skel-entry)
294 ("for" . ada-skel-for)
295 ("function"
296 ("body" . ada-skel-function-body)
297 ("spec" . ada-skel-function-spec))
298 ("header" . ada-skel-header)
299 ("if" . ada-skel-if)
300 ("loop" . ada-skel-loop)
301 ("package"
302 ("body" . ada-skel-package-body)
303 ("spec" . ada-skel-package-spec))
304 ("procedure"
305 ("body" . ada-skel-procedure-body)
306 ("spec" . ada-skel-procedure-spec))
307 ("protected"
308 ("body" . ada-skel-protected-body)
309 ("spec" . ada-skel-protected-spec))
310 ("record" . ada-skel-record)
311 ("return" . ada-skel-return)
312 ("select" . ada-skel-select)
313 ("task"
314 ("body" . ada-skel-task-body)
315 ("spec" . ada-skel-task-spec))
316 ("while" . ada-skel-while)
317 ("with" . ada-skel-with-use))
318 "alist of elements (STRING ELEMENT). See `ada-skel-expand'.
319 STRING must be a symbol in the current syntax, and is normally
320 the first Ada keyword in the skeleton. All strings must be
321 lowercase; `ada-skel-expand' converts user inputs.
322
323 ELEMENT may be:
324 - a skeleton, which is inserted
325 - an alist of (string . skeleton). User is prompted with `completing-read', selected skeleton is inserted. ")
326
327 (defvar ada-skel-test-input nil
328 "When non-nil, bypasses prompt in alist token expansions - used for unit testing.")
329
330 (defun ada-skel-build-prompt (alist count)
331 "Build a prompt from the keys of the ALIST.
332 The prompt consists of the first COUNT keys from the alist, separated by `|', with
333 trailing `...' if there are more keys."
334 (if (>= count (length alist))
335 (concat (mapconcat 'car alist " | ") " : ")
336 (let ((alist-1 (butlast alist (- (length alist) count))))
337 (concat (mapconcat 'car alist-1 " | ") " | ... : "))
338 ))
339
340 ;;;###autoload
341 (defun ada-skel-expand (&optional name)
342 "Expand the token or placeholder before point to a skeleton, as defined by `ada-skel-token-alist'.
343 A token is a symbol in the current syntax.
344 A placeholder is a symbol enclosed in generic comment delimiters.
345 If the word before point is not in `ada-skel-token-alist', assume
346 it is a name, and use the word before that as the token."
347 (interactive "*")
348
349 ;; Skip trailing space, newline, and placeholder delimiter.
350 ;; Standard comment end included for languages where that is newline.
351 (skip-syntax-backward " !>")
352
353 ;; include punctuation here, in case is is an identifier, to allow Ada.Text_IO
354 (let* ((end (prog1 (point) (skip-syntax-backward "w_.")))
355 (token (downcase (buffer-substring-no-properties (point) end)))
356 (skel (assoc-string token ada-skel-token-alist))
357 (handled nil))
358
359 (if skel
360 (progn
361 (when (listp (cdr skel))
362 (let* ((alist (cdr skel))
363 (prompt (ada-skel-build-prompt alist 4)))
364 (setq skel (assoc-string
365 (or ada-skel-test-input
366 (completing-read prompt alist))
367 alist))
368 (setq ada-skel-test-input nil) ;; don't reuse input on recursive call
369 ))
370
371 ;; delete placeholder delimiters around token, token, and
372 ;; name. point is currently before token.
373 (skip-syntax-backward "!")
374 (delete-region
375 (point)
376 (progn
377 (skip-syntax-forward "!w_")
378 (when name
379 (skip-syntax-forward " ")
380 (skip-syntax-forward "w_."))
381 (point)))
382 (funcall (cdr skel) name)
383 (setq handled t))
384
385 ;; word in point .. end is not a token; assume it is a name
386 (when (not name)
387 ;; avoid infinite recursion
388
389 ;; Do this now, because skeleton insert won't.
390 ;;
391 ;; We didn't do it above, because we don't want to adjust case
392 ;; on tokens and placeholders.
393 (save-excursion (ada-case-adjust-region (point) end))
394 (setq token (buffer-substring-no-properties (point) end))
395
396 (ada-skel-expand token)
397 (setq handled t)))
398
399 (when (not handled)
400 (error "undefined skeleton token: %s" name))
401 ))
402
403 (defun ada-skel-hippie-try (old)
404 "For `hippie-expand-try-functions-list'. OLD is ignored."
405 (if old
406 ;; hippie is asking us to try the "next" completion; we don't have one
407 nil
408 (let ((pos (point)))
409 (undo-boundary)
410 (condition-case nil
411 (progn
412 (ada-skel-expand)
413 t)
414 ('error
415 ;; undo ada-case-adjust, motion
416 (undo)
417 (goto-char pos)
418 nil)))))
419
420 (defun ada-skel-setup ()
421 "Setup a buffer ada-skel."
422 (add-hook 'skeleton-end-hook 'ada-indent-statement nil t)
423 (when (and ada-skel-initial-string
424 (= (buffer-size) 0))
425 (insert ada-skel-initial-string))
426 )
427
428 (provide 'ada-skeletons)
429 (provide 'ada-skel)
430
431 (setq ada-expand 'ada-skel-expand)
432
433 (add-hook 'ada-mode-hook 'ada-skel-setup)
434
435 ;;; ada-skel.el ends here