| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 |
|
|---|
| 32 |
|
|---|
| 33 |
|
|---|
| 34 |
|
|---|
| 35 |
|
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 |
|
|---|
| 40 |
|
|---|
| 41 |
|
|---|
| 42 |
|
|---|
| 43 |
|
|---|
| 44 |
|
|---|
| 45 |
|
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 |
|
|---|
| 49 |
|
|---|
| 50 |
|
|---|
| 51 |
|
|---|
| 52 |
|
|---|
| 53 |
|
|---|
| 54 |
(defgroup auto-insert nil |
|---|
| 55 |
"Automatic mode-dependent insertion of text into new files." |
|---|
| 56 |
:prefix "auto-insert-" |
|---|
| 57 |
:group 'files |
|---|
| 58 |
:group 'convenience) |
|---|
| 59 |
|
|---|
| 60 |
|
|---|
| 61 |
(defcustom auto-insert 'not-modified |
|---|
| 62 |
"*Controls automatic insertion into newly found empty files. |
|---|
| 63 |
Possible values: |
|---|
| 64 |
nil do nothing |
|---|
| 65 |
t insert if possible |
|---|
| 66 |
other insert if possible, but mark as unmodified. |
|---|
| 67 |
Insertion is possible when something appropriate is found in |
|---|
| 68 |
`auto-insert-alist'. When the insertion is marked as unmodified, you can |
|---|
| 69 |
save it with \\[write-file] RET. |
|---|
| 70 |
This variable is used when the function `auto-insert' is called, e.g. |
|---|
| 71 |
when you do (add-hook 'find-file-hook 'auto-insert). |
|---|
| 72 |
With \\[auto-insert], this is always treated as if it were t." |
|---|
| 73 |
:type '(choice (const :tag "Insert if possible" t) |
|---|
| 74 |
(const :tag "Do nothing" nil) |
|---|
| 75 |
(other :tag "insert if possible, mark as unmodified." |
|---|
| 76 |
not-modified)) |
|---|
| 77 |
:group 'auto-insert) |
|---|
| 78 |
|
|---|
| 79 |
(defcustom auto-insert-query 'function |
|---|
| 80 |
"*Non-nil means ask user before auto-inserting. |
|---|
| 81 |
When this is `function', only ask when called non-interactively." |
|---|
| 82 |
:type '(choice (const :tag "Don't ask" nil) |
|---|
| 83 |
(const :tag "Ask if called non-interactively" function) |
|---|
| 84 |
(other :tag "Ask" t)) |
|---|
| 85 |
:group 'auto-insert) |
|---|
| 86 |
|
|---|
| 87 |
(defcustom auto-insert-prompt "Perform %s auto-insertion? " |
|---|
| 88 |
"*Prompt to use when querying whether to auto-insert. |
|---|
| 89 |
If this contains a %s, that will be replaced by the matching rule." |
|---|
| 90 |
:type 'string |
|---|
| 91 |
:group 'auto-insert) |
|---|
| 92 |
|
|---|
| 93 |
|
|---|
| 94 |
(defcustom auto-insert-alist |
|---|
| 95 |
'((("\\.\\([Hh]\\|hh\\|hpp\\)\\'" . "C / C++ header") |
|---|
| 96 |
(upcase (concat (file-name-nondirectory |
|---|
| 97 |
(substring buffer-file-name 0 (match-beginning 0))) |
|---|
| 98 |
"_" |
|---|
| 99 |
(substring buffer-file-name (1+ (match-beginning 0))))) |
|---|
| 100 |
"#ifndef " str \n |
|---|
| 101 |
"#define " str "\n\n" |
|---|
| 102 |
_ "\n\n#endif") |
|---|
| 103 |
|
|---|
| 104 |
(("\\.\\([Cc]\\|cc\\|cpp\\)\\'" . "C / C++ program") |
|---|
| 105 |
nil |
|---|
| 106 |
"#include \"" |
|---|
| 107 |
(let ((stem (file-name-sans-extension buffer-file-name))) |
|---|
| 108 |
(cond ((file-exists-p (concat stem ".h")) |
|---|
| 109 |
(file-name-nondirectory (concat stem ".h"))) |
|---|
| 110 |
((file-exists-p (concat stem ".hh")) |
|---|
| 111 |
(file-name-nondirectory (concat stem ".hh"))))) |
|---|
| 112 |
& ?\" | -10) |
|---|
| 113 |
|
|---|
| 114 |
(("[Mm]akefile\\'" . "Makefile") . "makefile.inc") |
|---|
| 115 |
|
|---|
| 116 |
(html-mode . (lambda () (sgml-tag "html"))) |
|---|
| 117 |
|
|---|
| 118 |
(plain-tex-mode . "tex-insert.tex") |
|---|
| 119 |
(bibtex-mode . "tex-insert.tex") |
|---|
| 120 |
(latex-mode |
|---|
| 121 |
;; should try to offer completing read for these |
|---|
| 122 |
"options, RET: " |
|---|
| 123 |
"\\documentclass[" str & ?\] | -1 |
|---|
| 124 |
?{ (read-string "class: ") "}\n" |
|---|
| 125 |
("package, %s: " |
|---|
| 126 |
"\\usepackage[" (read-string "options, RET: ") & ?\] | -1 ?{ str "}\n") |
|---|
| 127 |
_ "\n\\begin{document}\n" _ |
|---|
| 128 |
"\n\\end{document}") |
|---|
| 129 |
|
|---|
| 130 |
(("/bin/.*[^/]\\'" . "Shell-Script mode magic number") |
|---|
| 131 |
lambda () |
|---|
| 132 |
(if (eq major-mode default-major-mode) |
|---|
| 133 |
(sh-mode))) |
|---|
| 134 |
|
|---|
| 135 |
(ada-mode . ada-header) |
|---|
| 136 |
|
|---|
| 137 |
(("\\.[1-9]\\'" . "Man page skeleton") |
|---|
| 138 |
"Short description: " |
|---|
| 139 |
".\\\" Copyright (C), " (substring (current-time-string) -4) " " |
|---|
| 140 |
(getenv "ORGANIZATION") | (progn user-full-name) |
|---|
| 141 |
" |
|---|
| 142 |
.\\\" You may distribute this file under the terms of the GNU Free |
|---|
| 143 |
.\\\" Documentation License. |
|---|
| 144 |
.TH " (file-name-sans-extension (file-name-nondirectory (buffer-file-name))) |
|---|
| 145 |
" " (file-name-extension (buffer-file-name)) |
|---|
| 146 |
" " (format-time-string "%Y-%m-%d ") |
|---|
| 147 |
"\n.SH NAME\n" |
|---|
| 148 |
(file-name-sans-extension (file-name-nondirectory (buffer-file-name))) |
|---|
| 149 |
" \\- " str |
|---|
| 150 |
"\n.SH SYNOPSIS |
|---|
| 151 |
.B " (file-name-sans-extension (file-name-nondirectory (buffer-file-name))) |
|---|
| 152 |
"\n" |
|---|
| 153 |
_ |
|---|
| 154 |
" |
|---|
| 155 |
.SH DESCRIPTION |
|---|
| 156 |
.SH OPTIONS |
|---|
| 157 |
.SH FILES |
|---|
| 158 |
.SH \"SEE ALSO\" |
|---|
| 159 |
.SH BUGS |
|---|
| 160 |
.SH AUTHOR |
|---|
| 161 |
" (user-full-name) |
|---|
| 162 |
'(if (search-backward "&" (line-beginning-position) t) |
|---|
| 163 |
(replace-match (capitalize (user-login-name)) t t)) |
|---|
| 164 |
'(end-of-line 1) " <" (progn user-mail-address) ">\n") |
|---|
| 165 |
|
|---|
| 166 |
(("\\.el\\'" . "Emacs Lisp header") |
|---|
| 167 |
"Short description: " |
|---|
| 168 |
";;; " (file-name-nondirectory (buffer-file-name)) " --- " str " |
|---|
| 169 |
|
|---|
| 170 |
;; Copyright (C) " (substring (current-time-string) -4) " " |
|---|
| 171 |
(getenv "ORGANIZATION") | (progn user-full-name) " |
|---|
| 172 |
|
|---|
| 173 |
;; Author: " (user-full-name) |
|---|
| 174 |
'(if (search-backward "&" (line-beginning-position) t) |
|---|
| 175 |
(replace-match (capitalize (user-login-name)) t t)) |
|---|
| 176 |
'(end-of-line 1) " <" (progn user-mail-address) "> |
|---|
| 177 |
;; Keywords: " |
|---|
| 178 |
'(require 'finder) |
|---|
| 179 |
|
|---|
| 180 |
'(setq v1 (mapcar (lambda (x) (list (symbol-name (car x)))) |
|---|
| 181 |
finder-known-keywords) |
|---|
| 182 |
v2 (mapconcat (lambda (x) (format "%12s: %s" (car x) (cdr x))) |
|---|
| 183 |
finder-known-keywords |
|---|
| 184 |
"\n")) |
|---|
| 185 |
((let ((minibuffer-help-form v2)) |
|---|
| 186 |
(completing-read "Keyword, C-h: " v1 nil t)) |
|---|
| 187 |
str ", ") & -2 " |
|---|
| 188 |
|
|---|
| 189 |
;; This file is free software; you can redistribute it and/or modify |
|---|
| 190 |
;; it under the terms of the GNU General Public License as published by |
|---|
| 191 |
;; the Free Software Foundation; either version 3, or (at your option) |
|---|
| 192 |
;; any later version. |
|---|
| 193 |
|
|---|
| 194 |
;; This file is distributed in the hope that it will be useful, |
|---|
| 195 |
;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 196 |
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 197 |
;; GNU General Public License for more details. |
|---|
| 198 |
|
|---|
| 199 |
;; You should have received a copy of the GNU General Public License |
|---|
| 200 |
;; along with GNU Emacs; see the file COPYING. If not, write to |
|---|
| 201 |
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|---|
| 202 |
;; Boston, MA 02110-1301, USA. |
|---|
| 203 |
|
|---|
| 204 |
;;; Commentary: |
|---|
| 205 |
|
|---|
| 206 |
;; " _ " |
|---|
| 207 |
|
|---|
| 208 |
;;; Code: |
|---|
| 209 |
|
|---|
| 210 |
|
|---|
| 211 |
|
|---|
| 212 |
\(provide '" |
|---|
| 213 |
(file-name-sans-extension (file-name-nondirectory (buffer-file-name))) |
|---|
| 214 |
") |
|---|
| 215 |
;;; " (file-name-nondirectory (buffer-file-name)) " ends here\n")) |
|---|
| 216 |
"A list specifying text to insert by default into a new file. |
|---|
| 217 |
Elements look like (CONDITION . ACTION) or ((CONDITION . DESCRIPTION) . ACTION). |
|---|
| 218 |
CONDITION may be a regexp that must match the new file's name, or it may be |
|---|
| 219 |
a symbol that must match the major mode for this element to apply. |
|---|
| 220 |
Only the first matching element is effective. |
|---|
| 221 |
Optional DESCRIPTION is a string for filling `auto-insert-prompt'. |
|---|
| 222 |
ACTION may be a skeleton to insert (see `skeleton-insert'), an absolute |
|---|
| 223 |
file-name or one relative to `auto-insert-directory' or a function to call. |
|---|
| 224 |
ACTION may also be a vector containing several successive single actions as |
|---|
| 225 |
described above, e.g. [\"header.insert\" date-and-author-update]." |
|---|
| 226 |
:type 'sexp |
|---|
| 227 |
:group 'auto-insert) |
|---|
| 228 |
|
|---|
| 229 |
|
|---|
| 230 |
|
|---|
| 231 |
(defcustom auto-insert-directory "~/insert/" |
|---|
| 232 |
"*Directory from which auto-inserted files are taken. |
|---|
| 233 |
The value must be an absolute directory name; |
|---|
| 234 |
thus, on a GNU or Unix system, it must end in a slash." |
|---|
| 235 |
:type 'directory |
|---|
| 236 |
:group 'auto-insert) |
|---|
| 237 |
|
|---|
| 238 |
|
|---|
| 239 |
|
|---|
| 240 |
(defun auto-insert () |
|---|
| 241 |
"Insert default contents into new files if variable `auto-insert' is non-nil. |
|---|
| 242 |
Matches the visited file name against the elements of `auto-insert-alist'." |
|---|
| 243 |
(interactive) |
|---|
| 244 |
(and (not buffer-read-only) |
|---|
| 245 |
(or (eq this-command 'auto-insert) |
|---|
| 246 |
(and auto-insert |
|---|
| 247 |
(bobp) (eobp))) |
|---|
| 248 |
(let ((alist auto-insert-alist) |
|---|
| 249 |
case-fold-search cond desc action) |
|---|
| 250 |
(goto-char 1) |
|---|
| 251 |
|
|---|
| 252 |
(while alist |
|---|
| 253 |
(if (atom (setq cond (car (car alist)))) |
|---|
| 254 |
(setq desc cond) |
|---|
| 255 |
(setq desc (cdr cond) |
|---|
| 256 |
cond (car cond))) |
|---|
| 257 |
(if (if (symbolp cond) |
|---|
| 258 |
(eq cond major-mode) |
|---|
| 259 |
(and buffer-file-name |
|---|
| 260 |
(string-match cond buffer-file-name))) |
|---|
| 261 |
(setq action (cdr (car alist)) |
|---|
| 262 |
alist nil) |
|---|
| 263 |
(setq alist (cdr alist)))) |
|---|
| 264 |
|
|---|
| 265 |
|
|---|
| 266 |
(and action |
|---|
| 267 |
(if (stringp action) |
|---|
| 268 |
(file-readable-p (concat auto-insert-directory action)) |
|---|
| 269 |
t) |
|---|
| 270 |
(if auto-insert-query |
|---|
| 271 |
(or (if (eq auto-insert-query 'function) |
|---|
| 272 |
(eq this-command 'auto-insert)) |
|---|
| 273 |
(y-or-n-p (format auto-insert-prompt desc))) |
|---|
| 274 |
t) |
|---|
| 275 |
(mapcar |
|---|
| 276 |
(lambda (action) |
|---|
| 277 |
(if (stringp action) |
|---|
| 278 |
(if (file-readable-p |
|---|
| 279 |
(setq action (concat auto-insert-directory action))) |
|---|
| 280 |
(insert-file-contents action)) |
|---|
| 281 |
(save-window-excursion |
|---|
| 282 |
|
|---|
| 283 |
|
|---|
| 284 |
(switch-to-buffer (current-buffer)) |
|---|
| 285 |
(if (and (consp action) |
|---|
| 286 |
(not (eq (car action) 'lambda))) |
|---|
| 287 |
(skeleton-insert action) |
|---|
| 288 |
(funcall action))))) |
|---|
| 289 |
(if (vectorp action) |
|---|
| 290 |
action |
|---|
| 291 |
(vector action)))) |
|---|
| 292 |
(and (buffer-modified-p) |
|---|
| 293 |
(not (eq this-command 'auto-insert)) |
|---|
| 294 |
(set-buffer-modified-p (eq auto-insert t))))) |
|---|
| 295 |
|
|---|
| 296 |
|
|---|
| 297 |
nil) |
|---|
| 298 |
|
|---|
| 299 |
|
|---|
| 300 |
|
|---|
| 301 |
(defun define-auto-insert (condition action &optional after) |
|---|
| 302 |
"Associate CONDITION with (additional) ACTION in `auto-insert-alist'. |
|---|
| 303 |
Optional AFTER means to insert action after all existing actions for CONDITION, |
|---|
| 304 |
or if CONDITION had no actions, after all other CONDITIONs." |
|---|
| 305 |
(let ((elt (assoc condition auto-insert-alist))) |
|---|
| 306 |
(if elt |
|---|
| 307 |
(setcdr elt |
|---|
| 308 |
(if (vectorp (cdr elt)) |
|---|
| 309 |
(vconcat (if after (cdr elt)) |
|---|
| 310 |
(if (vectorp action) action (vector action)) |
|---|
| 311 |
(if after () (cdr elt))) |
|---|
| 312 |
(if after |
|---|
| 313 |
(vector (cdr elt) action) |
|---|
| 314 |
(vector action (cdr elt))))) |
|---|
| 315 |
(if after |
|---|
| 316 |
(nconc auto-insert-alist (list (cons condition action))) |
|---|
| 317 |
(setq auto-insert-alist (cons (cons condition action) |
|---|
| 318 |
auto-insert-alist)))))) |
|---|
| 319 |
|
|---|
| 320 |
|
|---|
| 321 |
(define-minor-mode auto-insert-mode |
|---|
| 322 |
"Toggle Auto-insert mode. |
|---|
| 323 |
With prefix ARG, turn Auto-insert mode on if and only if ARG is positive. |
|---|
| 324 |
Returns the new status of Auto-insert mode (non-nil means on). |
|---|
| 325 |
|
|---|
| 326 |
When Auto-insert mode is enabled, when new files are created you can |
|---|
| 327 |
insert a template for the file depending on the mode of the buffer." |
|---|
| 328 |
:global t :group 'auto-insert |
|---|
| 329 |
(if auto-insert-mode |
|---|
| 330 |
(add-hook 'find-file-hook 'auto-insert) |
|---|
| 331 |
(remove-hook 'find-file-hook 'auto-insert))) |
|---|
| 332 |
|
|---|
| 333 |
(provide 'autoinsert) |
|---|
| 334 |
|
|---|
| 335 |
|
|---|
| 336 |
|
|---|
| 337 |
|
|---|