feat: easy buffer selection and auto open OrgAgenda

This commit is contained in:
Marc Marcos 2026-09-23 11:08:24 +02:00
parent 2803be5007
commit ae7e9d9b4b
Signed by: marc
GPG key ID: 30A62DFAC90731E6

View file

@ -91,22 +91,28 @@
;; -------------------------------------------------------------------
;; Buffer Tabs (LazyVim-style bufferline)
;; -------------------------------------------------------------------
;; Every open buffer is shown as a numbered tab in a bar at the top of
;; each window. Click a tab, or press M-1 .. M-9 (M-0 for the tenth),
;; to switch to it.
;; The numbered tabs at the top of each window show the Org agenda and
;; buffers visiting a file. Emacs' internal `*...*' buffers (scratch,
;; messages, native-compile log, ...) are hidden. Click a tab, or press
;; M-1 .. M-9 (M-0 for the tenth), to switch to it.
(defvar marc/tab-line-order nil
"Stable display order of buffers shown in the tab line.")
(defun marc/tab-line-buffer-p (buffer)
"Return non-nil when BUFFER should be shown as a tab."
(and (buffer-live-p buffer)
(let ((name (buffer-name buffer)))
(and (not (string-prefix-p " " name))
(or (not (string-prefix-p "*" name))
(and (boundp 'org-agenda-buffer-name)
(string= name org-agenda-buffer-name)))))))
(defun marc/tab-line-buffers ()
"Return live, non-hidden buffers in a stable display order."
"Return the buffers to show as tabs, in a stable display order."
(setq marc/tab-line-order
(seq-filter (lambda (b)
(and (buffer-live-p b)
(not (string-prefix-p " " (buffer-name b)))))
marc/tab-line-order))
(seq-filter #'marc/tab-line-buffer-p marc/tab-line-order))
(dolist (b (buffer-list))
(when (and (buffer-live-p b)
(not (string-prefix-p " " (buffer-name b)))
(when (and (marc/tab-line-buffer-p b)
(not (memq b marc/tab-line-order)))
(setq marc/tab-line-order (append marc/tab-line-order (list b)))))
marc/tab-line-order)
@ -132,7 +138,8 @@
:ensure nil
:config
(setq tab-line-tabs-function #'marc/tab-line-buffers
tab-line-tab-name-function #'marc/tab-line-tab-name)
tab-line-tab-name-function #'marc/tab-line-tab-name
tab-line-close-tab-function 'kill-buffer)
(global-tab-line-mode 1)
(dotimes (i 9)
(let ((n (1+ i)))
@ -246,6 +253,8 @@
"pp" '(counsel-projectile-switch-project :which-key "switch project")
"m" '(:ignore t :which-key "magit")
"mm" '(magit-status :which-key "magit status")
"b" '(:ignore t :which-key "buffers")
"bd" '(kill-current-buffer :which-key "close buffer/tab")
"." '(find-file :which-key "find file"))
(general-define-key
@ -548,10 +557,28 @@ jumps to the selected match."
;; A brand-new frame with no file to open (e.g. `emacsclient -c') shows
;; today's agenda. Using `initial-buffer-choice' lets Emacs swap the
;; frame's buffer in place instead of opening a second frame.
(defcustom marc/agenda-keep-files '("todo.org")
"Basenames of agenda files to keep open after building the agenda.
The other files that `org-agenda-list' opens while scanning are killed."
:type '(repeat string)
:group 'org-agenda)
(defun marc/agenda-buffer ()
"Return today's Org agenda buffer, creating it if necessary."
(require 'org-agenda)
(let ((before (buffer-list)))
(org-agenda-list 1)
(dolist (buf (buffer-list))
(let ((file (buffer-file-name buf)))
(when (and (not (memq buf before))
file
(not (buffer-modified-p buf))
(not (get-buffer-window buf))
(member (expand-file-name file)
(mapcar #'expand-file-name (org-agenda-files)))
(not (member (file-name-nondirectory file)
marc/agenda-keep-files)))
(kill-buffer buf)))))
(or (get-buffer org-agenda-buffer-name)
(get-buffer-create "*scratch*")))