3

Background

I am using Emacsclient to open files in a Emacs server. The server configuration depends on the content of a JSON configuration file. A Perl script can read the config file and write a suitable Emacs Lisp hashtable load file, which the server can read to update its configuration.

I would like to avoid running the Perl script when there has been no modification to the JSON file. So I am thinking about setting a global variable my-config-last-mod in the server, and check that against the current last-modification time of the JSON file. If there is a difference, the Perl script should run to update the server config.

Question

How to compare file modification timestamps in Emacs?

Here is what I have in mind:

(defvar my-config-last-mod nil)
(defun my-update-config ()
  (let* ((config-fn "myconfig.json")
         (last-mod (shell-command-to-string (concat "stat -c %y " config-fn)))
         (fixed-case t)
         (literal t)
         (reload-config t))
    ;; trim space at end
    (when (string-match "\\([[:space:]]\\|\n\\)*\\'" last-mod)
      (setq last-mod (replace-match "" fixed-case literal last-mod)))
    (when my-config-last-mod
      (when (my-compare-time-stamps my-config-last-mod last-mod)
        (setq reload-config nil)))
    (when reload-config
      (setq my-config-last-mod last-mod)
      (shell-command-to-string "my_update_config"))))

Is it possible to write my-compare-time-stamps in pure Lisp, or would I have to use an external program?

1 Answer 1

5

The function you are looking for is file-attributes. The help text is fairly detailed but you will be wanting:

4. Last access time, as a list of integers (HIGH LOW USEC PSEC) in the
 same style as (current-time).
 (See a note below about access time on FAT-based filesystems.)
5. Last modification time, likewise.  This is the time of the last
 change to the file's contents.
6. Last status change time, likewise.  This is the time of last change
 to the file's attributes: owner and group, access mode bits, etc.

So something like:

(defvar my-config-file
  "~/test.txt"
  "Path to my config file")

(defvar my-config-last-mod
  (nth 5 (file-attributes my-config-file))
  "Last modification time for my config file")

(defun my-config-updated-p ()
  "Check if my config file has been updated since I last checked"
  (time-less-p my-config-last-mod
               (nth 5 (file-attributes my-config-file))))

(defun my-do-something ()
  "Do something with my config"
  (when (my-config-updated-p)
    (setq my-config-last-mod
          (nth 5 (file-attributes my-config-file)))
    (message "do stuff")))
1
  • For the passengers: after Emacs 26.1, there is (file-attribute-modification-time ...) instead of (nth 5 ...) for more readability. Commented Feb 26, 2021 at 23:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.