1

I want to change a magic number (or a time stamp) in a file buffer on each save. The position of the magic number in the buffer can be given through a regex with a keyword or similar.

Is there any package for this? I tried auto-insert which comes with Emacs 26, but this seems to only update on file buffer creation, not on each save.

I preferably would like to enable this on a per-file basis through file local variables.

I tried a custom hack via before-save-hook, but struggled to add a function to this hook through afile variable declaration.

zck
  • 8,984
  • 2
  • 31
  • 65
halloleo
  • 1,215
  • 9
  • 23

2 Answers2

3

C-h f time-stamp:

time-stamp is an autoloaded interactive compiled Lisp function in
`time-stamp.el'.

(time-stamp)

  Probably introduced at or before Emacs version 19.31.

Update the time stamp string(s) in the buffer.
A template in a file can be automatically updated with a new time stamp
every time you save the file.  Add this line to your init file:
    (add-hook 'before-save-hook 'time-stamp)
or customize `before-save-hook' through Custom.

If you want to do this in the local variables section, you need to use the 'eval' functionality. e.g. assuming a .c file:

/* Local Variables: */
/* eval: (add-hook 'before-save-hook 'time-stamp 0 t) */
/* End: */

will cause the local value of before-save-hook to containg time-stamp.

rpluim
  • 4,605
  • 8
  • 22
  • This works, thanks. However I cannot figure out how to set add `time-stamp` to `before-save-hook` *in the file-local variables* at the end of the file. – halloleo Jun 28 '19 at 01:25
  • I'm not sure I understand what you're trying to do with file-local-variables. If you put the 'add-hook' in your init file, 'time-stamp' will run every time you save a buffer. For files which don't have a time-stamp template in the first 8 lines, nothing will be done, for files which do the time-stamp will be updated – rpluim Jun 28 '19 at 08:58
  • Sure, but that's exactly what I want to avoid: That *all* files with the time-stamp template are updated on save. Therfore I thought a buffer local `before-save-hook` set in the file-local variables would do the trick - but I cannot figure out how to add to hooks in the file-local variables... – halloleo Jun 28 '19 at 13:02
  • Cool, `eval` does the trick. Thanks! – halloleo Jun 30 '19 at 08:31
2

Easily done via a file-local variable save-count. The only drawback is that you cannot define the format of the magick number freely but you are bound to the format of file-local variables.

(defvar save-count nil
  "To be used as file-local variable.
Number of times the buffer file has been saved.")

(put 'save-count 'safe-local-variable #'numberp)

(defun start-save-count (&optional remove)
  "Start counting saves for the current buffer file."
  (interactive "P")
  (if remove
      (delete-file-local-variable 'save-count)
    (add-file-local-variable 'save-count 0))
  (normal-mode))

(defun update-save-count ()
  "Increment file local variable `save-count' if its value is a number."
  (when (numberp save-count)
    (cl-incf save-count)
    (save-excursion
      (add-file-local-variable 'save-count save-count))))


(add-hook 'before-save-hook #'update-save-count)

If you do not set the value of save-count to a number you do not get the counter.

That offers you several possibilities:

  • Preferred way: You can call M-x start-save-count. That command adds save-count to the list of file local variables in the current buffer. It also runs normal-mode for that variable to become effective.
  • You can just add a file local variable save-count with numeric value to your file. This will automatically be incremented on saves.
  • You can globally set save-count to a numeric value. In that case all buffers will get such a value on first save.
  • You can set the buffer-local value of save-count with (setq-local save-count 0). Then you get the save count just for that buffer file.
Tobias
  • 32,569
  • 1
  • 34
  • 75
  • Thanks for chiming in, but I want to change a magic number given as characters in the buffer itself - and this number should be updated on every save. I don't need a *variable* with a number... – halloleo Jun 28 '19 at 14:06
  • @halloleo Have you really tried it? The value is stored as value of the file local variable in the file! That **is** a character sequence in the file! – Tobias Jun 28 '19 at 14:08
  • @halloleo I have added a command `start-save-count` to ease the application. Just open any text file where you want to start counting the saves and call `M-x start-save-count`. Everything other will work automatically. – Tobias Jun 28 '19 at 14:23
  • @halloleo Note, the motivation for my answer was 1st: the word *increase* in the title of the question and 2nd: the phrase *magic number* in the text before you added "*(or a time-stamp)*". – Tobias Jun 28 '19 at 16:09
  • Sorry, Tobias, I hadn't tried it. Now I have and indeed it increments the value text of the variable _in_ the buffer. Pretty nifty! – halloleo Jun 30 '19 at 03:24