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