5

I'm trying to develop a git hook that warns me if any files that belong to a repo are unsaved in the editor. For that I need a list of open files/buffers and their state, so basically a non-interactive version of (list-buffers).

I run Emacs in server mode so I know I can do emacsclient -e '(command)', but how do I dump the list of current buffers?

1 Answer 1

6

The function buffer-list returns a list of buffers. Call buffer-modified-p to test if a buffer has been modified and buffer-file-name to test if a buffer is visiting a file.

The following snippet from the code of save-buffers-kill-emacs tests if there are any unsaved open files.

(memq t (mapcar (function
                  (lambda (buf) (and (buffer-file-name buf)
                                     (buffer-modified-p buf))))
                (buffer-list)))

Rather than enumerate all buffers, you may be better off testing only the buffers that are visiting files that are about to be committed. You can call find-buffer-visiting to get the buffer visiting a particular file, if any. Thus, given a list of file names in filenames:

(let ((unsaved 0))
  (mapc (lambda (filename)
          (let ((buffer (find-buffer-visiting filename)))
            (when filename
              (setq unsaved (1+ unsaved))
              (princ (concat "File not saved: " filename "\n")))))
        filenames)
  (when (> unsaved 0)
    (printc "There were unsaved files, aborting\n")))

In Emacs 24, it's possible to make emacsclient exit with a nonzero status, but this doesn't look easy: you have to send the die command to the appropriate client of which there can be many. Anyway emacsclient could also fail because there's no running Emacs, which is a success condition for you. So I suggest to check whether emacsclient emits output on stdout.

files=
for x; do
  files="$files \"`absolute_path "$x" | sed 's/[\\\\\\\"]/\\\\&/g'`\""
done
unsaved=$(emacsclient -e '(let ((filenames ('"$files"'))) …)' 2>/dev/null)
if [ -n "$unsaved" ]; then
  echo "$unsaved"
  exit 1
fi

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.