I had already some lines of code when KaushalModi mentioned minibuffer-line
. Maybe, you should use that mode. If you like you can steal some ideas from the following code to get the updates on buffer-changing operations.
It works. But, it is not very efficient.
For an example you could use buffer-list-update-hook
instead of post-command-hook
.
You can also plug buffer-file-name
into minibuffer-buffer-list-filter
instead of identity
. This way emacs only shows file buffers.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Show buffer list in minibuffer
(defcustom minibuffer-buffer-list-filter 'identity
"Function for filtering the buffer names shown in the minibuffer window."
:group 'notify
:type 'sexp)
(defun substring-no-properties-safe (str from &optional to)
"Like `substring-no-properties' but does not fail on args out of range."
(let ((n (length str)))
(substring-no-properties str (min from (max (1- n) 0)) (when to (min to n)))))
(defun minibuffer-buffer-list ()
"Show buffer list in minibuffer window."
(substring-no-properties-safe
(mapconcat 'buffer-name
(cl-delete-if-not minibuffer-buffer-list-filter
(cl-delete-if (lambda (buf) (eq (aref (buffer-name buf) 0) #x20))
(buffer-list)))
" | ")
0 (1- (window-width (minibuffer-window)))))
(defcustom notify-function 'minibuffer-buffer-list
"The string returned by this function is displayed in minibuffer."
:group 'notify
:type 'sexp)
(defcustom notify-idle-time 1
"Time in seconds until showing buffers in minibuffer."
:group 'notify
:type 'number)
(defvar notify-idle-timer nil)
(defun notify-text-p ()
"Check whether text in current buffer has the :notification text property."
(get-text-property (point-min) :notification))
(defmacro notify-with-minibuffer (&rest body)
"Run BODY in minibuffer when there is one."
(declare '(debug &rest body) '(indent 1))
`(let ((minibuffer (window-buffer (minibuffer-window))))
(when minibuffer
(with-current-buffer minibuffer
,@body))))
(defun notify-clear ()
"Clear notification from active minibuffer."
(notify-with-minibuffer
(when (notify-text-p)
(with-silent-modifications
(erase-buffer)))))
(defun notify-run (&optional frame)
"Run `notify-function' if minibuffer is empty and emacs is idle for `notify-idle-time' seconds."
(notify-with-minibuffer
(when (and (null (active-minibuffer-window))
(or (eq (length (buffer-string)) 0)
(notify-text-p)))
(with-silent-modifications
(erase-buffer)
(insert (propertize
(funcall notify-function)
:notification t)))
)))
(define-minor-mode notify-mode
"Show whatever `notify-function' wants us to show after `notify-idle-time' in minibuffer."
nil nil nil
(if notify-mode
(progn
(setq notify-idle-timer (run-with-idle-timer notify-idle-time t 'notify-run))
(add-hook 'post-command-hook 'notify-run)
(add-hook 'window-size-change-functions 'notify-run))
(if (timerp notify-idle-timer)
(cancel-timer notify-idle-timer))
(notify-clear)
(remove-hook 'post-command-hook 'notify-run)
(remove-hook 'window-size-change-functions 'notify-run))
:global 't)
The documentation on the echo area motivates the following implementation.
Especially the functions notify-p
, notify-run
and notify-clear
have changed.
(require 'cl-lib)
(defcustom minibuffer-buffer-list-filter 'identity
"Function for filtering the buffer names shown in the minibuffer window."
:group 'notify
:type 'sexp)
(defun substring-no-properties-safe (str from &optional to)
"Like `substring-no-properties' but does not fail on args out of range."
(let ((n (length str)))
(substring-no-properties str (min from (max (1- n) 0)) (when to (min to n)))))
(defun notify-buffer-list ()
"Show buffer list in minibuffer window."
(substring-no-properties-safe
(mapconcat 'buffer-name
(cl-delete-if-not minibuffer-buffer-list-filter
(cl-delete-if (lambda (buf) (eq (aref (buffer-name buf) 0) #x20))
(buffer-list)))
" | ")
0 (1- (window-width (minibuffer-window)))))
(defcustom notify-function 'notify-buffer-list
"The string returned by this function is displayed in minibuffer."
:group 'notify
:type 'sexp)
(defcustom notify-idle-time 1
"Time in seconds until showing buffers in minibuffer."
:group 'notify
:type 'number)
(defvar notify-idle-timer nil)
(defun notify-p ()
"Check whether the message buffer is ready for updating the notification.
That means either it is empty or contains already an old notification."
(when (null (active-minibuffer-window))
(let ((msg (current-message)))
(or (null msg)
(get-text-property 0 :notification msg)))))
(defun notify-clear ()
"Clear notification from active minibuffer."
(when (notify-p)
(message nil)))
(defun notify-run (&optional frame)
"Run `notify-function' if minibuffer is empty and emacs is idle for `notify-idle-time' seconds."
(when (notify-p)
(let (message-log-max) ;; inhibit copy to message buffer
(message "%s" (propertize
(funcall notify-function)
:notification t)))))
(define-minor-mode notify-mode
"Show whatever `notify-function' wants us to show after `notify-idle-time' in minibuffer."
nil nil nil
:global t
(if notify-mode
(progn
(setq notify-idle-timer (run-with-idle-timer notify-idle-time t 'notify-run))
(add-hook 'post-command-hook 'notify-run)
(add-hook 'window-size-change-functions 'notify-run))
(if (timerp notify-idle-timer)
(cancel-timer notify-idle-timer))
(remove-hook 'window-size-change-functions 'notify-run)
(remove-hook 'post-command-hook 'notify-run)
(notify-clear)))
mode-line-format
when a buffer is created or deleted. But if you just want the buffer names on demand, then just useC-x b TAB
(thenC-g
, if you don't want to switch buffers).minibuffer-line-format
variable to show you the buffer list. You will need to install theminibuffer-line
package from GNU ELPA.