home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / misc / modify.el < prev    next >
Encoding:
Text File  |  1993-06-15  |  23.2 KB  |  606 lines

  1. ;;; modify.el - simple code for maintaining modification tags in files like RCS
  2.  
  3. ;; Author: Lawrence R. Dodd <dodd@roebling.poly.edu>
  4. ;; Maintainer: Lawrence R. Dodd <dodd@roebling.poly.edu>
  5. ;; Created: 28 May 1992
  6. ;; Version: 1.58
  7. ;; Keywords: extensions
  8.  
  9. ;; Copyright (C) 1993 Lawrence R. Dodd
  10. ;;
  11. ;; This program is free software; you can redistribute it and/or modify
  12. ;; it under the terms of the GNU General Public License as published by
  13. ;; the Free Software Foundation; either version 2 of the License, or
  14. ;; (at your option) any later version.
  15. ;;
  16. ;; This program is distributed in the hope that it will be useful,
  17. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. ;; GNU General Public License for more details.
  20. ;;
  21. ;; You should have received a copy of the GNU General Public License
  22. ;; along with this program; if not, write to the Free Software
  23. ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25. ;;; Commentary:
  26.  
  27. (defconst modify-version (substring "!Revision: 1.58 !" 11 -2) 
  28.   "revision number of modify.el - maintains a modification tag in files.  type
  29. M-x modify-submit-report to send a bug report.  available via anonymous ftp
  30. in:
  31.  
  32.    /roebling.poly.edu:/pub/modify.el
  33.    /archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive/misc/modify.el.Z")
  34.  
  35. ;; LCD Archive Entry:
  36. ;; modify|Lawrence R. Dodd|dodd@roebling.poly.edu|
  37. ;; Simple code for maintaining modification tags in files like RCS.|
  38. ;; 16-Jun-1993|1.58|~/misc/modify.el.Z|
  39.  
  40. ;;; Based on code posted by merlyn@iWarp.intel.com (Randal L. Schwartz)
  41.  
  42. ;;; !Modified: Wed Jun 16 12:29:47 EDT 1993 by dodd !
  43. ;;; !Id: modify.el,v 1.58 1993/06/16 16:30:37 dodd Exp !
  44. ;;; !Revision: 1.58 ! 
  45.  
  46. ;;;   Lawrence R. Dodd <dodd@roebling.poly.edu>
  47. ;;;   Department of Chemical Engineering
  48. ;;;   Polymer Research Institute
  49. ;;;   Polytechnic University 
  50. ;;;   Brooklyn, New York, 11201 USA
  51.  
  52. ;;; BUG REPORTS: 
  53. ;;; 
  54. ;;; just type M-x modify-submit-report to generate a bug report template
  55. ;;; (requires Barry Warsaw's reporter.el available at roebling.poly.edu)
  56.  
  57.  
  58. ;;; INSTALLATION AND USAGE: 
  59. ;;;  
  60. ;;; Save as `modify.el' in a directory where emacs can find it. Stick 
  61. ;;; 
  62. ;;;                   (require 'modify) 
  63. ;;;                   
  64. ;;; in your ~/.emacs or the site initialization file.  Next set the variable
  65. ;;; `modify-update' to a value of t, nil, or 'ask for each major mode,
  66. ;;; including the default-major-mode, in their respective mode-hooks -- or
  67. ;;; make it a default by editing the value in this file or sticking _one_ of
  68. ;;; the following in your ~/.emacs file.
  69. ;;;  
  70. ;;;      (setq-default modify-update t)    ; update, never query
  71. ;;;      (setq-default modify-update nil)  ; never update
  72. ;;;      (setq-default modify-update 'ask) ; query (1st time only)
  73. ;;;  
  74. ;;; This variable has a unique value for each buffer it is visiting.  Do the
  75. ;;; same for `modify-insert-tag' and `modify-insert-offset.' 
  76. ;;; 
  77. ;;; The complete list of user-defined variables is:
  78. ;;;  
  79. ;;;       modify-tag
  80. ;;;       modify-tag-regexp
  81. ;;;       modify-maximum-point
  82. ;;;       modify-date-switches
  83. ;;;       modify-date-switches-repeat
  84. ;;;  
  85. ;;; the user-defined buffer-local variables are
  86. ;;;  
  87. ;;;       modify-update
  88. ;;;       modify-insert-tag
  89. ;;;       modify-insert-offset
  90. ;;; 
  91. ;;; to find out more about these variables, load this file, put your cursor at 
  92. ;;; the end of any of the above lines, and hit C-h v [RET].
  93. ;;;  
  94. ;;; the interactive function is
  95. ;;; 
  96. ;;;       (modify-insert-tag)
  97. ;;;  
  98. ;;; to find out more about this function, load this file, put your cursor
  99. ;;; inside the `()' of the above line, and hit C-h f [RET].
  100.  
  101. ;;; RCS CAVEAT: 
  102. ;;; 
  103. ;;; Obviously, modifications to a file that has been checked out using RCS
  104. ;;; will cause the modified tags to be updated.  Those that use of Sebastian
  105. ;;; Kremer's rcs.el and GNU diff may wish to define the value of the variable
  106. ;;; `rcsdiff-switches' to ignore the differences due to the modified tag.
  107. ;;; This can be done as follows
  108. ;;;  
  109. ;;; (setq rcsdiff-switches (list (concat "-I\\$" modify-tag-regexp ":?.*\\$")))
  110. ;;;  
  111. ;;; note:
  112. ;;; 
  113. ;;;    diff -I REGEXP ignores changes that match REGEXP
  114. ;;; 
  115. ;;;    Thus, the regular expression `"\\$" modify-tag-regexp ":?.*\\$"'
  116. ;;;    matches occurrences of the modify.el tag (expanded or unexpanded) and
  117. ;;;    suppresses these differences.  For context or unified differences,
  118. ;;;    place a `c' or a `u' switch in front of the `I' switch.  The `list' in
  119. ;;;    the above definition allows the command line to be edited; this may be
  120. ;;;    removed if the user desires.
  121.  
  122. ;;; DESCRIPTION: 
  123. ;;;  
  124. ;;; Once installed, this code will update a time stamp string, like the one in
  125. ;;; the header of this file, in a manner similar to the way RCS updates its
  126. ;;; tags.
  127. ;;;  
  128. ;;; If you stick the string "$\Modified$" anywhere near the top of a file,
  129. ;;; this code will replace it with "$\Modified: time_saved by user_name $"
  130. ;;; when the filed is first saved.  [Note `\Modified' is really the contents
  131. ;;; of the variable `modify-tag' which defaults to the string "Modified."]  It
  132. ;;; will then update the time and user name each subsequent saving of the
  133. ;;; file.  It will update all occurrences up to `modify-maximum-point' beyond
  134. ;;; the last update or the beginning of the buffer.
  135. ;;; 
  136. ;;; If `modify-date-switches' is non-nil then the string is passed as
  137. ;;; switches to the UNIX `date' command.  Thus, for most date commands, if set
  138. ;;; to "-u" modify.el will use Universal Coordinated Time or GMT.  Just like
  139. ;;; RCS!  You may also set it to the null string "" in which case the result
  140. ;;; of the command `date' will be used (i.e., containing the local time zone).
  141. ;;; The variable `modify-date-switches-repeat' is used for all tags after the
  142. ;;; first one.
  143. ;;; 
  144. ;;; Finally, if the variables `modify-insert-tag' and `modify-update' are t,
  145. ;;; and the $\Modified$ tag does not exist in the header of the file, then
  146. ;;; this code will make the top line (plus the value of
  147. ;;; `modify-insert-offset') of the file $\Modified: current_time by user_name
  148. ;;; $ which, if necessary, is prefixed and postfixed by the correct comment
  149. ;;; characters for the current major mode.
  150.  
  151.  
  152. ;;; Change log:
  153. ;;;  
  154. ;;; 1.29 - 
  155. ;;;   lrd: use comment-end in for automatic insertion of tag, 
  156. ;;;   suggested by Brian McAllister <mcallister@mit.edu> 
  157. ;;; 1.30 - 
  158. ;;;   lrd: doc mod 
  159. ;;; 1.31 - 
  160. ;;;   lrd: put new-line after comment-end.  Thanks to Brian McAllister 
  161. ;;;   <mcallister@mit.edu>.
  162. ;;; 1.32 - 
  163. ;;;   lrd: make maximum search a variable instead of always 2000 
  164. ;;; 1.33 -
  165. ;;;   lrd: doc mod 
  166. ;;; 1.34 - 
  167. ;;;   lrd: allow for repeat replacements of modify-tag up to 
  168. ;;;   modify-maximum-point.  allow modify-date-switches(-repeat) to be null 
  169. ;;;   strings "". removed `update-last-edit-date-save-buffer'
  170. ;;; 1.35 - 
  171. ;;;   lrd: modified variable doc strings 
  172. ;;; 1.36 -
  173. ;;;   lrd: doc mod 
  174. ;;; 1.37 - 
  175. ;;;   lrd: `limit' needs to be redefined after each replacement in case the 
  176. ;;;   point has moved beyond old value.  define so that `limit' is the minimum 
  177. ;;;   of `point-max' and the point of the last substitution plus 
  178. ;;;   `modify-maximum-point.'  use save-point for substitution because 
  179. ;;;   save-excursion loses value of point sometimes.
  180. ;;; 1.38 - 
  181. ;;;   lrd: removed `save-point' was more annoying than was `save-excursion.'
  182. ;;; 1.39 -
  183. ;;;   lrd: added LCD information. 
  184. ;;; 1.40 -
  185. ;;;   lrd: added doc about `rcsdiff-switches' 
  186. ;;; 1.41 - 
  187. ;;;   lrd: fixed bug -- if $modify-tag$ occurred _after_ a $modify-tag: date$
  188. ;;;   occurring at top of file
  189. ;;; 1.42 - 
  190. ;;;   lrd: applied Radey Shouman's <rshouman@hermes.chpc.utexas.edu> patch. 
  191. ;;;   they enhance modify.el as follows: 
  192. ;;;     (1) update-last-edit-date is now set to t after the first query to 
  193. ;;;         `Replace Modify Tag?' -- no need to keep asking the user. 
  194. ;;;     (2) automatic insertion of the modify tag is done more carefully now. 
  195. ;;;         if the user has `update-last-edit-date' to set 'ask then modify.el 
  196. ;;;         will now also ask before inserting even if `modify-insert-tag' is 
  197. ;;;         set to t.
  198. ;;;     (3) if new variable `modify-tag-regexp' is non-nil then it can be a 
  199. ;;;         regular expression to be used in place of `modify-tag.'  in effect
  200. ;;;         the modify tag may now be a regular expression.
  201. ;;; 1.43 - 
  202. ;;;   lrd: doc mod; added kludge note.
  203. ;;; 1.44 - 
  204. ;;;   lrd: modified doc string for `modify-insert-tag' thanks to Radey Shouman
  205. ;;;   <rshouman@hermes.chpc.utexas.edu>.  Modified header.  Renamed
  206. ;;;   `update-last-edit-date' to `modify-tag-hook' so if someone sees it in
  207. ;;;   the write-file-hooks list they will have some idea what it does.
  208. ;;; 1.45 - 
  209. ;;;   lrd: added in test of `update-last-edit-date' in insertion code.
  210. ;;; 1.46 - 
  211. ;;;   lrd: added Radey Shouman's patch.  `modify-insert-tag' can now be 'ask 
  212. ;;;   just like `update-last-edit-date.'  changed doc strings for both.
  213. ;;; 1.47 - 
  214. ;;;   lrd: simplified the search and replacing in `modify-tag-hook' and 
  215. ;;;   created new function `modify-insert-tag' which does the actual 
  216. ;;;   insertion -- this may be called interactively.
  217. ;;; 1.48 - 
  218. ;;;   lrd: (modify-insert-tag): make buffer writable, if necessary; doc mod.
  219. ;;; 1.49 - 
  220. ;;;   lrd: added to doc string of `modify-date-switches'
  221. ;;; 1.50 - 
  222. ;;;   lrd: defined `modify-insert-offset' and changed (modify-insert-tag) to
  223. ;;;   skip these many lines from the top of file.  Useful for script files
  224. ;;;   that need a `#! /shell' at the top of the file.  Thanks to Chan Wilson
  225. ;;;   <cwilson@sgi.com> for suggesting this.  with a non-nil argument
  226. ;;;   (modify-insert-tag) will stick the modify tag at point.
  227. ;;; 1.51 - 
  228. ;;;   lrd: changed doc string for `modify-insert-offset'
  229. ;;; 1.52 - 
  230. ;;;   lrd: doc mod
  231. ;;; 1.53 - 
  232. ;;;   lrd: (modify-insert-tag): fail safe check for `#!'
  233. ;;; 1.54 - 
  234. ;;;   lrd: doc mod
  235. ;;; 1.55 - 
  236. ;;;   lrd: (modify-insert-tag): don't stick tag before `%!' in a PostScript 
  237. ;;;   file.
  238. ;;; 1.56 - 
  239. ;;;   lrd: (modify-submit-report): use Barry Warsaw's reporter.el
  240. ;;; 1.57 -
  241. ;;;   lrd: use GNU standard for doc string and header, use add-hook if 
  242. ;;;   available. 
  243. ;;; 1.58 -
  244. ;;;   lrd: changed `update-last-edit-date' to `modify-update' as this is 
  245. ;;;   suggested (very strongly) by the GNU standard.
  246.  
  247.  
  248. ;;; Code:
  249.  
  250. ;;; user defined variables 
  251. (defvar modify-tag "Modified"
  252.   "*string representing label of tag to be updated.  The modified string will
  253. be \"$modify-tag: time by user $\".  See also `modify-tag-regexp.'")
  254.  
  255. (defvar modify-tag-regexp nil
  256.     "*regexp matching any label of tag to be replaced.  defaults to
  257. the result of \(regexp-quote modify-tag\).")
  258.  
  259. (or modify-tag-regexp
  260.     (setq modify-tag-regexp (regexp-quote modify-tag)))
  261.  
  262. ;;; buffer locals 
  263. (defvar modify-insert-tag nil
  264.   "*t says to attempt inserting tag in buffer if not found.  buffer local.  if
  265. this is t and `modify-update' is t then tag automatically inserted.  if
  266. `modify-update' is non-nil, but not t, and this variable is non-nil then ask
  267. the user once and only once whether to insert a modification tag at the top of
  268. the file.  if this variable and/or `modify-update' is nil then insertion will
  269. never be attempted.")
  270. (make-variable-buffer-local 'modify-insert-tag)
  271. (put 'modify-insert-tag 'permanent-local t) ; for v19 Emacs
  272. (put 'modify-insert-tag 'preserved t)       ; for kill-fix.el
  273.  
  274. (defvar modify-update nil
  275.   "*t says buffer should have its modification tag automatically updated.  nil
  276. says buffer will not have its modification tag updated.  if non-nil but not t,
  277. then ask user once and only once whether to update modify tag.  buffer
  278. local.")
  279. (make-variable-buffer-local 'modify-update)
  280. (put 'modify-update 'permanent-local t) ; for v19 Emacs
  281. (put 'modify-update 'preserved t)       ; for kill-fix.el
  282.  
  283. (defvar modify-insert-offset 0
  284.   "*number of lines from top of buffer that modify tag should be inserted.
  285. see also `modify-insert-tag' and `modify-insert-tag'. buffer local.
  286.  
  287. set to more than one in mode hooks for files that have a shell pathname such
  288. as `#!/bin/sh' on the first line.  For example, define this to be some
  289. positive integer in `csh-mode-hook' for csh-mode.el, in `perl-mode-hook' for
  290. perl.el, and in the function `awk-mode' for awk-mode.el.")
  291. (make-variable-buffer-local 'modify-insert-offset)
  292. (put 'modify-insert-offset 'permanent-local t) ; for v19 Emacs
  293. (put 'modify-insert-offset 'preserved t)       ; for kill-fix.el
  294.  
  295. ;;; switches for Unix `date' command
  296.  
  297. (defvar modify-date-switches nil
  298.   "*string of switches passed to local Unix date command for first tag found.
  299. nil says use the emacs lisp function `current-time-string.'  See also
  300. `modify-date-switches-repeat.'
  301.  
  302. For example, with a value of \"-u\" modify.el would use Universal Coordinated
  303. Time \(i.e., Greenwhich Mean Time\) in its time stamp (just like RCS)
  304.  
  305.              ;;; $\\Modified: Sat Feb 27 17:10:12 GMT 1993 by dodd $
  306.  
  307. Please note `\\Modified' is really the contents of the variable `modify-tag'
  308. which defaults to the string \"Modified\".  If you use GNU date then you may
  309. set this or `modify-date-switches-repeat' to \"+%c\"")
  310.  
  311. (defvar modify-date-switches-repeat modify-date-switches
  312.  
  313.   "*string of switches passed to local Unix date command for second tag.
  314. set to the value of `modify-date-switches' by default.  nil says use the emacs
  315. lisp function.  See also the variable `modify-date-switches.'
  316.  
  317. This variables exists so that it can be set to something like \"+%c\" for use
  318. with the GNU version of date (or just plain \"\" for all versions of date) to
  319. show local time, with timezone, on any repeat substitutions.  This allows
  320. scenarios such as this inside files
  321.  
  322.              ;;; $\\Modified: Sat Feb 27 17:10:12 GMT 1993 by dodd $
  323.              ;;; $\\Modified: Sat Feb 27 12:10:12 EST 1993 by dodd $ 
  324.  
  325. showing the modified time in _both_ GMT and local time.  An unexpected feature
  326. of this is that their difference tells you how far you are from Greenwich,
  327. England!
  328.  
  329. Please note `\\Modified' is really the contents of the variable `modify-tag'
  330. which defaults to the string \"Modified\".")
  331.  
  332. (defvar modify-maximum-point 2000
  333.   "*Integer for maximum number of characters from buffer top to search for tag.
  334. the default is 2000 characters.")
  335.  
  336.  
  337. ;;; the work horse 
  338. (defun modify-tag-hook ()
  339.  
  340.   "Update modify tag while writing out a modified file.  Installed by
  341. modify.el and intended to be used as one of the `write-file-hooks' values.
  342.  
  343. Does _not_ write out file.  The return value is nil unconditionally."
  344.   
  345.   ;; if the variable is nil then we will exit
  346.   (if modify-update
  347.          
  348.       (let (limit originally_locked case-fold-search
  349.  
  350.                   ;; define regular expression search string
  351.                   ;; will match both expanded or unexpanded tag
  352.                   (search-string
  353.                    (concat
  354.                     ;; from leading $ to end of modify-tag-regexp
  355.                     "\\(\\$" modify-tag-regexp "\\)"
  356.                     ;; may or may not be expanded, i.e., `:' may not exist
  357.                     "\\(:?\\)"
  358.                     ;; everything up to final $
  359.                     "[^\n\\$]*"
  360.                     ;; the final $
  361.                     "\\(\\$\\)"))
  362.  
  363.                   ;; define replacement string
  364.                   ;; will create expanded tag
  365.                   (replacement-string
  366.                    (concat
  367.                     ;; from leading $ to end of modify-tag-regexp plus `: '
  368.                     "\\1: "
  369.                     ;; date and user
  370.                     (modify-current-time-string)
  371.                     " by " (user-login-name)
  372.                     ;; the final $
  373.                     " \\3")))
  374.  
  375.         ;; IF WE CAN LOCATE IT...
  376.         (if (and
  377.              
  378.              ;; can we locate the tag? - meat of package 
  379.              ;; search is case-sensitive
  380.              
  381.              (save-excursion
  382.  
  383.                ;; set the limit of our search to be the user-defined variable 
  384.                ;; or the entire buffer, whichever is smaller
  385.                (setq limit (min modify-maximum-point (point-max)))
  386.  
  387.                (goto-char (point-min))
  388.  
  389.                ;; can we find the tag?
  390.                (re-search-forward search-string limit t))
  391.              
  392.              ;; we found that tag, now if `modify-update' is not explicitly
  393.              ;; equal to t, then we must ask
  394.              (or (eq t modify-update)
  395.                  ;; reset value of variable
  396.                  (setq modify-update (y-or-n-p "Replace Modify Tag? ")))
  397.              )
  398.             
  399.             ;; ...THEN REPLACE IT
  400.             (save-excursion
  401.  
  402.               ;; make buffer writable if necessary
  403.               (setq originally_locked (if buffer-read-only (toggle-read-only)))
  404.  
  405.               ;; make the replacement 
  406.               (replace-match replacement-string t)
  407.  
  408.               ;; need to redefine `limit' in case the point is beyond old value
  409.               (setq limit (min (+ (point) modify-maximum-point) (point-max))) 
  410.  
  411.               ;; now repeat until `limit' is reached
  412.  
  413.               ;; define local value of `modify-date-switches'
  414.               (let* ((modify-date-switches modify-date-switches-repeat)
  415.                      (replacement-string
  416.                       (concat "\\1: " (modify-current-time-string) " by "
  417.                               (user-login-name) " \\3")))
  418.                 
  419.                 ;; search, replace, and redefine `limit'
  420.                 (while (re-search-forward search-string limit t)
  421.                   (replace-match replacement-string t)
  422.                   (setq limit (min (+ (point) modify-maximum-point)
  423.                                    (point-max)))))
  424.  
  425.               ;; if the buffer was originally read-only, then make it so again
  426.               (if originally_locked (toggle-read-only)))
  427.  
  428.           ;; ...ELSE SHOULD WE INSERT IT?
  429.  
  430.           ;; Scenarios
  431.  
  432.           ;; if either `modify-update' or `modify-insert-tag' are set to nil
  433.           ;; then insertion will _not_ be done.
  434.  
  435.           ;; if, and only if, both `modify-update' and `modify-insert-tag' are
  436.           ;; set to t then insertion be done automatically.
  437.  
  438.           ;; if either `modify-update' or `modify-insert-tag' is set to 'ask
  439.           ;; (and the other is t) then user will be queried and both will be
  440.           ;; set to the reply (i.e., to either t or nil).
  441.  
  442.           (if (and
  443.  
  444.                ;; 1. check for a non-nil value -- could be t or 'ask
  445.                modify-update
  446.  
  447.                ;; 2. check for a non-nil value -- could be t or 'ask
  448.                (if (listp modify-insert-tag)
  449.                    (and (memq major-mode modify-insert-tag)
  450.                         (setq modify-insert-tag t))
  451.                  modify-insert-tag)
  452.  
  453.                ;; 3. check if both have a t value
  454.                (or (and (eq t modify-insert-tag)
  455.                         (eq t modify-update))
  456.  
  457.                    ;; one (or both) is 'ask 
  458.                    ;; query user and set value of both variables to result
  459.                    (setq modify-update
  460.                          (setq modify-insert-tag
  461.                                (y-or-n-p "Insert Modify Tag? ")))))
  462.  
  463.               ;; insert tag
  464.               (modify-insert-tag nil)))))
  465.  
  466.   ;; force nil return value - we do _not_ write out the file
  467.   nil)
  468.  
  469.  
  470. (defun modify-current-time-string ()
  471.  
  472.   "Return current time as a human-readable string.  Reduces to
  473. `current-time-string' if `modify-date-switches' is nil, otherwise passes that
  474. string as switches to Unix date command."
  475.  
  476.   (if modify-date-switches
  477.  
  478.       ;; switches are non-nil use Unix date
  479.       (let (string temp-buffer)
  480.         
  481.         (save-excursion
  482.           
  483.           ;; create a clean temporary buffer 
  484.           (setq temp-buffer (get-buffer-create "*modify current time output*"))
  485.           (set-buffer temp-buffer)
  486.           (erase-buffer)
  487.           
  488.           ;; call the date with switches and stick the output in buffer
  489.           ;; allow for the special case of a null string since this confuses 
  490.           ;; most versions of `date'
  491.  
  492.           (if (string= modify-date-switches "")
  493.               (call-process "date" nil t nil)
  494.             (call-process "date" nil t nil modify-date-switches))
  495.           
  496.           ;; define string as everything in the buffer -- except the newline 
  497.           (setq string (buffer-substring 1 (1- (point-max))))
  498.           
  499.           ;; remove temporary buffer
  500.           (kill-buffer temp-buffer))
  501.         
  502.         ;; return string
  503.         string)
  504.     
  505.     ;; use elisp routine to return string
  506.     (current-time-string)))
  507.  
  508.  
  509. (defun modify-insert-tag (arg)
  510.  
  511.   "Insert modify tag at top of buffer plus `modify-insert-offset' lines down.
  512. called by `modify-tag-hook' but also may be called interactively.  If argument
  513. ARG is non-nil then place modify tag at point in current buffer, ignoring the
  514. value of `modify-insert-offset.'
  515.  
  516. Regardless of the value of `modify-insert-offset,' this routine will never
  517. place a modify tag before a line that begins with `#!' this is done in order
  518. to avoid screwing up shell scripts."
  519.  
  520.   (interactive "P")
  521.  
  522.   ;; make readable if necessary
  523.   (let ((originally_locked (if buffer-read-only (toggle-read-only))))
  524.     
  525.     (save-excursion
  526.  
  527.       ;; no argument? go to top of buffer
  528.       (if (not arg) (progn (goto-char (point-min))
  529.                            ;; skip forward 0 or more lines
  530.                            (forward-line modify-insert-offset)))
  531.  
  532.       ;; are we still looking at a `#!' or `%!'?  if so, move forward
  533.       (if (looking-at "^[#%]?!") (forward-line 1))
  534.  
  535.       ;; insert modify tag
  536.       (insert-string
  537.        (concat comment-start "$" modify-tag ": "
  538.                (modify-current-time-string) " by " (user-login-name)
  539.                " $" comment-end "\n")))
  540.     
  541.     ;; if the buffer was originally read-only, then make it so again
  542.     (if originally_locked (toggle-read-only))))
  543.  
  544. ;;; prepend to write-file-hooks - checking first whether or not it is already
  545. ;;; there
  546.  
  547. (if (fboundp 'add-hook)
  548.  
  549.     ;; use v19's add-hook
  550.     (add-hook 'write-file-hooks 'modify-tag-hook)
  551.  
  552.   ;; Contributed by Ken Laprade <laprade@trantor.harris-atd.com>
  553.   ;; Really should use some sort of add-hook - 16 Feb 93 - KCL
  554.   (or (and (listp write-file-hooks) (not (eq (car write-file-hooks) 'lambda)))
  555.       (setq write-file-hooks (list write-file-hooks)))
  556.  
  557.   (or (memq 'modify-tag-hook write-file-hooks)
  558.       (setq write-file-hooks (append '(modify-tag-hook) write-file-hooks))))
  559.  
  560.  
  561. ;;;; BUG REPORTS
  562.  
  563. ;;; this section is provided for reports.
  564. ;;; using Barry A. Warsaw's reporter.el
  565.  
  566. (defconst modify-help-address "dodd@roebling.poly.edu"
  567.   "Address(es) accepting submission of reports on modify.el.")
  568.  
  569. (defconst modify-maintainer "Larry"
  570.   "First name(s) of people accepting submission of reports on modify.el.")
  571.  
  572. (defconst modify-file "modify.el"
  573.   "Name of file containing emacs lisp code.")
  574.  
  575. (defconst modify-variable-list
  576.   (list 'modify-tag
  577.         'modify-tag-regexp
  578.         'modify-maximum-point
  579.         'modify-date-switches
  580.         'modify-date-switches-repeat)
  581.   "list of variables to be appended to reports sent by `modify-submit-report.'")
  582.  
  583. (defun modify-submit-report ()
  584.  
  585.   "submit via reporter.el a bug report on program.  send report on
  586. `modify-file' version `modify-version,' to `modify-maintainer' at address
  587. `modify-help-address' listing variables `modify-variable-list' in the
  588. message."
  589.  
  590.   (interactive)
  591.  
  592.   (require 'reporter)
  593.  
  594.   (reporter-submit-bug-report
  595.    modify-help-address                     ; address
  596.    (concat modify-file " " modify-version) ; pkgname
  597.    modify-variable-list                    ; varlist
  598.    nil nil                                 ; pre-hooks and post-hooks
  599.    (concat "Yo, " modify-maintainer "!"))) ; salutation
  600.  
  601.  
  602. ;;; provide package
  603. (provide 'modify)
  604.  
  605. ;;; modify.el ends here
  606.