 `switch-buffer-functions' when it has been changed from
 the last buffer.
 
-This function should be hooked to `post-command-hook'."
-  (unless (eq (current-buffer)
-              switch-buffer-functions--last-buffer)
-    (let ((current (current-buffer))
+This function should be hooked to `buffer-list-update-hook'."
+  (unless switch-buffer-functions--running-p
+    (let ((switch-buffer-functions--running-p t)
+          (current (current-buffer))
           (previous switch-buffer-functions--last-buffer))
-      (setq switch-buffer-functions--last-buffer
-            current)
-      (run-hook-with-args 'switch-buffer-functions
-                          previous
-                          current))))
+      (unless (eq previous
+                  current)
+        (run-hook-with-args 'switch-buffer-functions
+                            previous
+                            current)
+        (setq switch-buffer-functions--last-buffer
+              (current-buffer))))))
 
 ;;;###autoload
-(add-hook 'post-command-hook
+(add-hook 'buffer-list-update-hook
           'switch-buffer-functions-run)
 
 (provide 'switch-buffer-functions)

;;; Commentary:

;; This package provides a hook variable `switch-buffer-functions'.

;; This hook will be run when the current buffer has been changed after each
;; interactive command, i.e. `post-command-hook' is called.

;; When functions are hooked, they will be called with the previous buffer and
;; the current buffer.  For example, if you eval:

  nil
  "The last current buffer.")

(defvar switch-buffer-functions--running-p
  nil
  "Non-nil if currently inside of run `switch-buffer-functions-run'.")

;;;###autoload
(defun switch-buffer-functions-run ()
  "Run `switch-buffer-functions' if needed.
