comparison lisp/utils/skeleton.el @ 2:ac2d302a0011 r19-15b2

Import from CVS: tag r19-15b2
author cvs
date Mon, 13 Aug 2007 08:46:35 +0200
parents 376386a54a3c
children 859a2309aef8
comparison
equal deleted inserted replaced
1:c0c6a60d29db 2:ac2d302a0011
3 3
4 ;; Author: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389 4 ;; Author: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389
5 ;; Maintainer: FSF 5 ;; Maintainer: FSF
6 ;; Keywords: extensions, abbrev, languages, tools 6 ;; Keywords: extensions, abbrev, languages, tools
7 7
8 ;; This file is part of GNU Emacs. 8 ;; This file is part of XEmacs.
9 9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify 10 ;; XEmacs is free software; you can redistribute it and/or modify it
11 ;; it under the terms of the GNU General Public License as published by 11 ;; under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option) 12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version. 13 ;; any later version.
14 14
15 ;; GNU Emacs is distributed in the hope that it will be useful, 15 ;; XEmacs is distributed in the hope that it will be useful, but
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ;; GNU General Public License for more details. 18 ;; General Public License for more details.
19 19
20 ;; You should have received a copy of the GNU General Public License 20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to 21 ;; along with XEmacs; see the file COPYING. If not, write to the Free
22 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 22 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 23 ;; 02111-1307, USA.
24 ;;; Synched up with: FSF 19.30. 24
25 ;;; Synched up with: FSF 19.34.
25 26
26 ;;; Commentary: 27 ;;; Commentary:
27 28
28 ;; A very concise language extension for writing structured statement 29 ;; A very concise language extension for writing structured statement
29 ;; skeleton insertion commands for programming language modes. This 30 ;; skeleton insertion commands for programming language modes. This
47 ; this should be a fourth argument to defvar 48 ; this should be a fourth argument to defvar
48 (put 'skeleton-transformation 'variable-interactive 49 (put 'skeleton-transformation 'variable-interactive
49 "aTransformation function: ") 50 "aTransformation function: ")
50 51
51 52
53 (defvar skeleton-autowrap t
54 "Controls wrapping behaviour of functions created with `define-skeleton'.
55 When the region is visible (due to `transient-mark-mode' or marking a region
56 with the mouse) and this is non-`nil' and the function was called without an
57 explicit ARG, then the ARG defaults to -1, i.e. wrapping around the visible
58 region.
59
60 We will probably delete this variable in a future Emacs version
61 unless we get a substantial number of complaints about the auto-wrap
62 feature.")
52 63
53 (defvar skeleton-end-hook 64 (defvar skeleton-end-hook
54 (lambda () 65 (lambda ()
55 (or (eolp) (newline-and-indent))) 66 (or (eolp) (newline-and-indent)))
56 "Hook called at end of skeleton but before going to point of interest. 67 "Hook called at end of skeleton but before going to point of interest.
58 The variables `v1' and `v2' are still set when calling this.") 69 The variables `v1' and `v2' are still set when calling this.")
59 70
60 71
61 ;;;###autoload 72 ;;;###autoload
62 (defvar skeleton-filter 'identity 73 (defvar skeleton-filter 'identity
63 "Function for transforming a skeleton-proxy's aliases' variable value.") 74 "Function for transforming a skeleton proxy's aliases' variable value.")
64 75
65 (defvar skeleton-untabify t 76 (defvar skeleton-untabify t
66 "When non-`nil' untabifies when deleting backwards with element -ARG.") 77 "When non-`nil' untabifies when deleting backwards with element -ARG.")
67 78
68 (defvar skeleton-newline-indent-rigidly nil 79 (defvar skeleton-newline-indent-rigidly nil
81 (substitute-command-keys 92 (substitute-command-keys
82 "RET, \\<minibuffer-local-map>\\[abort-recursive-edit] or \\[help-command]") 93 "RET, \\<minibuffer-local-map>\\[abort-recursive-edit] or \\[help-command]")
83 "*Replacement for %s in prompts of recursive subskeletons.") 94 "*Replacement for %s in prompts of recursive subskeletons.")
84 95
85 96
86 (defvar skeleton-abbrev-cleanup nil) 97 (defvar skeleton-abbrev-cleanup nil
87 98 "Variable used to delete the character that led to abbrev expansion.")
88 99
100 ;; XEmacs -- won't byte compile without the wrapper
89 (eval-and-compile 101 (eval-and-compile
90 (defvar skeleton-debug nil 102 (defvar skeleton-debug nil
91 "*If non-nil `define-skeleton' will override previous definition.")) 103 "*If non-nil `define-skeleton' will override previous definition."))
92 104
93 ;; reduce the number of compiler warnings 105 ;; reduce the number of compiler warnings
103 which contains the skeleton, has a documentation to that effect. 115 which contains the skeleton, has a documentation to that effect.
104 INTERACTOR and ELEMENT ... are as defined under `skeleton-insert'." 116 INTERACTOR and ELEMENT ... are as defined under `skeleton-insert'."
105 (if skeleton-debug 117 (if skeleton-debug
106 (set command skeleton)) 118 (set command skeleton))
107 `(progn 119 `(progn
108 (defvar ,command ',skeleton ,documentation) 120 (defun ,command (&optional str arg)
109 (defalias ',command 'skeleton-proxy))) 121 ,(concat documentation
110 122 (if (string-match "\n\\>" documentation)
111 123 "" "\n")
124 "\n"
125 "This is a skeleton command (see `skeleton-insert').
126 Normally the skeleton text is inserted at point, with nothing \"inside\".
127 If there is a highlighted region, the skeleton text is wrapped
128 around the region text.
129
130 A prefix argument ARG says to wrap the skeleton around the next ARG words.
131 A prefix argument of zero says to wrap around zero words---that is, nothing.
132 This is a way of overiding the use of a highlighted region.")
133 (interactive "*P\nP")
134 (skeleton-proxy-new ',skeleton str arg))))
135
136 ;;;###autoload
137 (defun skeleton-proxy-new (skeleton &optional str arg)
138 "Insert skeleton defined by variable of same name (see `skeleton-insert').
139 Prefix ARG allows wrapping around words or regions (see `skeleton-insert').
140 If no ARG was given, but the region is visible, ARG defaults to -1 depending
141 on `skeleton-autowrap'. An ARG of M-0 will prevent this just for once.
142 This command can also be an abbrev expansion (3rd and 4th columns in
143 \\[edit-abbrevs] buffer: \"\" command-name).
144
145 When called as a function, optional first argument STR may also be a string
146 which will be the value of `str' whereas the skeleton's interactor is then
147 ignored."
148 (interactive "*P\nP")
149 (setq skeleton (funcall skeleton-filter skeleton))
150 (if (not skeleton)
151 (if (memq this-command '(self-insert-command
152 skeleton-pair-insert-maybe
153 expand-abbrev))
154 (setq buffer-undo-list (primitive-undo 1 buffer-undo-list)))
155 (skeleton-insert skeleton
156 (if (setq skeleton-abbrev-cleanup
157 (or (eq this-command 'self-insert-command)
158 (eq this-command
159 'skeleton-pair-insert-maybe)))
160 ()
161 ;; Pretend C-x a e passed its prefix arg to us
162 (if (or arg current-prefix-arg)
163 (prefix-numeric-value (or arg
164 current-prefix-arg))
165 (and skeleton-autowrap
166 (or (eq last-command 'mouse-drag-region)
167 (and (boundp 'transient-mark-mode)
168 transient-mark-mode mark-active))
169 -1)))
170 (if (stringp str)
171 str))
172 (and skeleton-abbrev-cleanup
173 (setq skeleton-abbrev-cleanup (point))
174 (add-hook 'post-command-hook 'skeleton-abbrev-cleanup nil t))))
112 175
113 ;; This command isn't meant to be called, only it's aliases with meaningful 176 ;; This command isn't meant to be called, only it's aliases with meaningful
114 ;; names are. 177 ;; names are.
115 ;;;###autoload 178 ;;;###autoload
116 (defun skeleton-proxy (&optional str arg) 179 (defun skeleton-proxy (&optional str arg)
117 "Insert skeleton defined by variable of same name (see `skeleton-insert'). 180 "Insert skeleton defined by variable of same name (see `skeleton-insert').
118 Prefix ARG allows wrapping around words or regions (see `skeleton-insert'). 181 Prefix ARG allows wrapping around words or regions (see `skeleton-insert').
182 If no ARG was given, but the region is visible, ARG defaults to -1 depending
183 on `skeleton-autowrap'. An ARG of M-0 will prevent this just for once.
119 This command can also be an abbrev expansion (3rd and 4th columns in 184 This command can also be an abbrev expansion (3rd and 4th columns in
120 \\[edit-abbrevs] buffer: \"\" command-name). 185 \\[edit-abbrevs] buffer: \"\" command-name).
121 186
122 When called as a function, optional first argument STR may also be a string 187 When called as a function, optional first argument STR may also be a string
123 which will be the value of `str' whereas the skeleton's interactor is then 188 which will be the value of `str' whereas the skeleton's interactor is then
124 ignored." 189 ignored."
125 (interactive "*P\nP") 190 (interactive "*P\nP")
126 (let ((function (nth 1 (backtrace-frame 1)))) 191 (let ((function (nth 1 (backtrace-frame 1))))
127 (if (eq function 'nth) ; uncompiled lisp function 192 (if (eq function 'nth) ; uncompiled Lisp function
128 (setq function (nth 1 (backtrace-frame 5))) 193 (setq function (nth 1 (backtrace-frame 5)))
129 (if (eq function 'byte-code) ; tracing byte-compiled function 194 (if (eq function 'byte-code) ; tracing byte-compiled function
130 (setq function (nth 1 (backtrace-frame 2))))) 195 (setq function (nth 1 (backtrace-frame 2)))))
131 (if (not (setq function (funcall skeleton-filter (symbol-value function)))) 196 (if (not (setq function (funcall skeleton-filter (symbol-value function))))
132 (if (memq this-command '(self-insert-command 197 (if (memq this-command '(self-insert-command
140 'skeleton-pair-insert-maybe))) 205 'skeleton-pair-insert-maybe)))
141 () 206 ()
142 ;; Pretend C-x a e passed its prefix arg to us 207 ;; Pretend C-x a e passed its prefix arg to us
143 (if (or arg current-prefix-arg) 208 (if (or arg current-prefix-arg)
144 (prefix-numeric-value (or arg 209 (prefix-numeric-value (or arg
145 current-prefix-arg)))) 210 current-prefix-arg))
211 (and skeleton-autowrap
212 (or (eq last-command 'mouse-drag-region)
213 (and (boundp 'transient-mark-mode)
214 transient-mark-mode mark-active))
215 -1)))
146 (if (stringp str) 216 (if (stringp str)
147 str)) 217 str))
148 (if skeleton-abbrev-cleanup 218 (and skeleton-abbrev-cleanup
149 (setq deferred-action-list t 219 (setq skeleton-abbrev-cleanup (point))
150 deferred-action-function 'skeleton-abbrev-cleanup 220 (add-hook 'post-command-hook 'skeleton-abbrev-cleanup nil t)))))
151 skeleton-abbrev-cleanup (point))))))
152 221
153 222
154 (defun skeleton-abbrev-cleanup (&rest list) 223 (defun skeleton-abbrev-cleanup (&rest list)
155 "Value for `post-command-hook' to remove char that expanded abbrev." 224 "Value for `post-command-hook' to remove char that expanded abbrev."
156 (if (integerp skeleton-abbrev-cleanup) 225 (if (integerp skeleton-abbrev-cleanup)
157 (progn 226 (progn
158 (delete-region skeleton-abbrev-cleanup (point)) 227 (delete-region skeleton-abbrev-cleanup (point))
159 (setq deferred-action-list () 228 (setq skeleton-abbrev-cleanup nil)
160 deferred-action-function nil 229 (remove-hook 'post-command-hook 'skeleton-abbrev-cleanup t))))
161 skeleton-abbrev-cleanup nil))))
162
163 230
164 ;;;###autoload 231 ;;;###autoload
165 (defun skeleton-insert (skeleton &optional skeleton-regions str) 232 (defun skeleton-insert (skeleton &optional skeleton-regions str)
166 "Insert the complex statement skeleton SKELETON describes very concisely. 233 "Insert the complex statement skeleton SKELETON describes very concisely.
167 234
199 continues after `resume:' and positions at `_' if any. If INTERACTOR in such 266 continues after `resume:' and positions at `_' if any. If INTERACTOR in such
200 a subskeleton is a prompt-string which contains a \".. %s ..\" it is 267 a subskeleton is a prompt-string which contains a \".. %s ..\" it is
201 formatted with `skeleton-subprompt'. Such an INTERACTOR may also a list of 268 formatted with `skeleton-subprompt'. Such an INTERACTOR may also a list of
202 strings with the subskeleton being repeated once for each string. 269 strings with the subskeleton being repeated once for each string.
203 270
204 Quoted lisp-expressions are evaluated evaluated for their side-effect. 271 Quoted Lisp expressions are evaluated evaluated for their side-effect.
205 Other lisp-expressions are evaluated and the value treated as above. 272 Other Lisp expressions are evaluated and the value treated as above.
206 Note that expressions may not return `t' since this impplies an 273 Note that expressions may not return `t' since this implies an
207 endless loop. Modes can define other symbols by locally setting them 274 endless loop. Modes can define other symbols by locally setting them
208 to any valid skeleton element. The following local variables are 275 to any valid skeleton element. The following local variables are
209 available: 276 available:
210 277
211 str first time: read a string according to INTERACTOR 278 str first time: read a string according to INTERACTOR
212 then: insert previously read string once more 279 then: insert previously read string once more
213 help help-form during interaction with the user or `nil' 280 help help-form during interaction with the user or `nil'
214 input initial input (string or cons with index) while reading str 281 input initial input (string or cons with index) while reading str
215 v1, v2 local variables for memorising anything you want 282 v1, v2 local variables for memorizing anything you want
216 283
217 When done with skeleton, but before going back to `_'-point call 284 When done with skeleton, but before going back to `_'-point call
218 `skeleton-end-hook' if that is non-`nil'." 285 `skeleton-end-hook' if that is non-`nil'."
219 (and skeleton-regions 286 (and skeleton-regions
220 (setq skeleton-regions 287 (setq skeleton-regions
380 ((null element)) 447 ((null element))
381 ((skeleton-internal-1 (eval element) t)))) 448 ((skeleton-internal-1 (eval element) t))))
382 449
383 450
384 ;; Maybe belongs into simple.el or elsewhere 451 ;; Maybe belongs into simple.el or elsewhere
385 452 ;###autoload
386 (define-skeleton local-variables-section 453 (define-skeleton local-variables-section
387 "Insert a local variables section. Use current comment syntax if any." 454 "Insert a local variables section. Use current comment syntax if any."
388 ()
389 '(save-excursion
390 (if (re-search-forward page-delimiter nil t)
391 (error "Not on last page.")))
392 comment-start "Local Variables:" comment-end \n
393 comment-start "mode: "
394 (completing-read "Mode: " obarray 455 (completing-read "Mode: " obarray
395 (lambda (symbol) 456 (lambda (symbol)
396 (if (commandp symbol) 457 (if (commandp symbol)
397 (string-match "-mode$" (symbol-name symbol)))) 458 (string-match "-mode$" (symbol-name symbol))))
398 t) 459 t)
460 '(save-excursion
461 (if (re-search-forward page-delimiter nil t)
462 (error "Not on last page.")))
463 comment-start "Local Variables:" comment-end \n
464 comment-start "mode: " str
399 & -5 | '(kill-line 0) & -1 | comment-end \n 465 & -5 | '(kill-line 0) & -1 | comment-end \n
400 ( (completing-read (format "Variable, %s: " skeleton-subprompt) 466 ( (completing-read (format "Variable, %s: " skeleton-subprompt)
401 obarray 467 obarray
402 (lambda (symbol) 468 (lambda (symbol)
403 (or (eq symbol 'eval) 469 (or (eq symbol 'eval)
404 (user-variable-p symbol))) 470 (user-variable-p symbol)))
405 t) 471 t)
406 comment-start str ": " 472 comment-start str ": "
407 (read-from-minibuffer "Expression: " nil read-expression-map nil 473 (read-from-minibuffer "Expression: " nil read-expression-map nil
408 'read-expression-history) | _ 474 'read-expression-history) | _
409 comment-end \n) 475 comment-end \n)
410 resume: 476 resume:
411 comment-start "End:" comment-end) 477 comment-start "End:" comment-end \n)
412 478
413 ;; Variables and command for automatically inserting pairs like () or "". 479 ;; Variables and command for automatically inserting pairs like () or "".
414 480
415 (defvar skeleton-pair nil 481 (defvar skeleton-pair nil
416 "*If this is nil pairing is turned off, no matter what else is set. 482 "*If this is nil pairing is turned off, no matter what else is set.
437 503
438 ;;;###autoload 504 ;;;###autoload
439 (defun skeleton-pair-insert-maybe (arg) 505 (defun skeleton-pair-insert-maybe (arg)
440 "Insert the character you type ARG times. 506 "Insert the character you type ARG times.
441 507
442 With no ARG, if `skeleton-pair' is non-nil, and if 508 With no ARG, if `skeleton-pair' is non-nil, pairing can occur. If the region
443 `skeleton-pair-on-word' is non-nil or we are not before or inside a 509 is visible the pair is wrapped around it depending on `skeleton-autowrap'.
510 Else, if `skeleton-pair-on-word' is non-nil or we are not before or inside a
444 word, and if `skeleton-pair-filter' returns nil, pairing is performed. 511 word, and if `skeleton-pair-filter' returns nil, pairing is performed.
445 512
446 If a match is found in `skeleton-pair-alist', that is inserted, else 513 If a match is found in `skeleton-pair-alist', that is inserted, else
447 the defaults are used. These are (), [], {}, <> and `' for the 514 the defaults are used. These are (), [], {}, <> and `' for the
448 symmetrical ones, and the same character twice for the others." 515 symmetrical ones, and the same character twice for the others."
449 (interactive "*P") 516 (interactive "*P")
450 (if (or arg 517 (let ((mark (and skeleton-autowrap
451 overwrite-mode 518 (or (eq last-command 'mouse-drag-region)
452 (not skeleton-pair) 519 (and (boundp 'transient-mark-mode)
453 (if (not skeleton-pair-on-word) (looking-at "\\w")) 520 transient-mark-mode mark-active))))
454 (funcall skeleton-pair-filter)) 521 (skeleton-end-hook))
455 (self-insert-command (prefix-numeric-value arg)) 522 (if (or arg
456 (self-insert-command 1) 523 (not skeleton-pair)
457 (if skeleton-abbrev-cleanup 524 (and (not mark)
458 () 525 (or overwrite-mode
459 ;; (preceding-char) is stripped of any Meta-stuff in last-command-char 526 (if (not skeleton-pair-on-word) (looking-at "\\w"))
460 (if (setq arg (assq (preceding-char) skeleton-pair-alist)) 527 (funcall skeleton-pair-filter))))
461 ;; typed char is inserted (car is no real interactor) 528 (self-insert-command (prefix-numeric-value arg))
462 (let (skeleton-end-hook) 529 (setq last-command-char (logand last-command-char 255))
463 (skeleton-insert arg)) 530 (or skeleton-abbrev-cleanup
464 (save-excursion 531 (skeleton-insert
465 (insert (or (cdr (assq (preceding-char) 532 (cons nil (or (assq last-command-char skeleton-pair-alist)
466 '((?( . ?)) 533 (assq last-command-char '((?( _ ?))
467 (?[ . ?]) 534 (?[ _ ?])
468 (?{ . ?}) 535 (?{ _ ?})
469 (?< . ?>) 536 (?< _ ?>)
470 (?` . ?')))) 537 (?` _ ?')))
471 last-command-char))))))) 538 `(,last-command-char _ ,last-command-char)))
539 (if mark -1))))))
472 540
473 541
474 ;;; ;; A more serious example can be found in sh-script.el 542 ;; A more serious example can be found in sh-script.el
475 ;;; ;; The quote before (defun prevents this from being byte-compiled. 543 ;;; (defun mirror-mode ()
476 ;;;(defun mirror-mode () 544 ;; "This major mode is an amusing little example of paired insertion.
477 ;;; "This major mode is an amusing little example of paired insertion. 545 ;;All printable characters do a paired self insert, while the other commands
478 ;;;All printable characters do a paired self insert, while the other commands 546 ;;work normally."
479 ;;;work normally." 547 ;; (interactive)
480 ;;; (interactive) 548 ;; (kill-all-local-variables)
481 ;;; (kill-all-local-variables) 549 ;; (make-local-variable 'skeleton-pair)
482 ;;; (make-local-variable 'pair) 550 ;; (make-local-variable 'skeleton-pair-on-word)
483 ;;; (make-local-variable 'pair-on-word) 551 ;; (make-local-variable 'skeleton-pair-filter)
484 ;;; (make-local-variable 'pair-filter) 552 ;; (make-local-variable 'skeleton-pair-alist)
485 ;;; (make-local-variable 'pair-alist) 553 ;; (setq major-mode 'mirror-mode
486 ;;; (setq major-mode 'mirror-mode 554 ;; mode-name "Mirror"
487 ;;; mode-name "Mirror" 555 ;; skeleton-pair-on-word t
488 ;;; pair-on-word t 556 ;; ;; in the middle column insert one or none if odd window-width
489 ;;; ;; in the middle column insert one or none if odd window-width 557 ;; skeleton-pair-filter (lambda ()
490 ;;; pair-filter (lambda () 558 ;; (if (>= (current-column)
491 ;;; (if (>= (current-column) 559 ;; (/ (window-width) 2))
492 ;;; (/ (window-width) 2)) 560 ;; ;; insert both on next line
493 ;;; ;; insert both on next line 561 ;; (next-line 1)
494 ;;; (next-line 1) 562 ;; ;; insert one or both?
495 ;;; ;; insert one or both? 563 ;; (= (* 2 (1+ (current-column)))
496 ;;; (= (* 2 (1+ (current-column))) 564 ;; (window-width))))
497 ;;; (window-width)))) 565 ;; ;; mirror these the other way round as well
498 ;;; ;; mirror these the other way round as well 566 ;; skeleton-pair-alist '((?) _ ?()
499 ;;; pair-alist '((?) _ ?() 567 ;; (?] _ ?[)
500 ;;; (?] _ ?[) 568 ;; (?} _ ?{)
501 ;;; (?} _ ?{) 569 ;; (?> _ ?<)
502 ;;; (?> _ ?<) 570 ;; (?/ _ ?\\)
503 ;;; (?/ _ ?\\) 571 ;; (?\\ _ ?/)
504 ;;; (?\\ _ ?/) 572 ;; (?` ?` _ "''")
505 ;;; (?` ?` _ "''") 573 ;; (?' ?' _ "``"))
506 ;;; (?' ?' _ "``")) 574 ;; ;; in this mode we exceptionally ignore the user, else it's no fun
507 ;;; ;; in this mode we exceptionally ignore the user, else it's no fun 575 ;; skeleton-pair t)
508 ;;; pair t) 576 ;; (let ((map (make-vector 256 'skeleton-pair-insert-maybe))
509 ;;; (let ((map (make-keymap)) 577 ;; (i 0))
510 ;;; (i ? )) 578 ;; (use-local-map `(keymap ,map))
511 ;;; (use-local-map map) 579 ;; (while (< i ? )
512 ;;; (setq map (car (cdr map))) 580 ;; (aset map i nil)
513 ;;; (while (< i ?\^?) 581 ;; (aset map (+ i 128) nil)
514 ;;; (aset map i 'skeleton-pair-insert-maybe) 582 ;; (setq i (1+ i))))
515 ;;; (setq i (1+ i)))) 583 ;; (run-hooks 'mirror-mode-hook))
516 ;;; (run-hooks 'mirror-mode-hook)) 584
585 (provide 'skeleton)
517 586
518 ;; skeleton.el ends here 587 ;; skeleton.el ends here