From 79e0e7e405e90e58f1c40be3f3e54149bc625814 Mon Sep 17 00:00:00 2001 From: Micheal Smith Date: Thu, 11 Dec 2025 05:42:32 -0600 Subject: [PATCH] Some buffer and performance changes. Spiffed up ibuffer. --- README.org | 346 +++++++++++++++++++-------------------------- config.org | 3 +- config/files.org | 2 +- config/gc.org | 5 +- config/general.org | 11 +- config/ibuffer.org | 126 +++++++++++++++++ config/style.org | 11 ++ 7 files changed, 294 insertions(+), 210 deletions(-) create mode 100644 config/ibuffer.org diff --git a/README.org b/README.org index 21b8b63..fa63d56 100644 --- a/README.org +++ b/README.org @@ -218,8 +218,9 @@ Magic Hack) to handle this. It seems to work pretty well. #+begin_src emacs-lisp ;; Garbage collection (use-package gcmh - :ensure t - :hook (after-init . gcmh-mode) + :demand t + :init + (gcmh-mode) :custom (gcmh-idle-delay 'auto) (gcmh-auto-idle-delay-factor 10)) @@ -383,18 +384,25 @@ There are a lot of solutions for editing files, and projects remotely. At the m #+begin_src emacs-lisp (use-feature tramp :config + (setq tramp-ssh-controlmaster-options + (concat + "-o ControlPath=/tmp/ssh-ControlPath-%%r@%%h:%%p " + "-o ControlMaster=auto -o ControlPersist=yes")) ;; Enable full-featured Dirvish over TRAMP on ssh connections ;; https://www.gnu.org/software/tramp/#Improving-performance-of-asynchronous-remote-processes (connection-local-set-profile-variables 'remote-direct-async-process '((tramp-direct-async-process . t))) (connection-local-set-profiles - '(:application tramp :protocol "ssh") + '(:application tramp :protocol "rsync") 'remote-direct-async-process) + (setq magit-tramp-pipe-stty-settings 'pty) + (with-eval-after-load 'compile + (remove-hook 'compilation-mode-hook #'tramp-compile-disable-ssh-controlmaster-options)) ;; Tips to speed up connections (setq tramp-verbose 0) (setq tramp-chunksize 2000) - (setq tramp-ssh-controlmaster-options nil)) + (setq tramp-copy-size-limit nil)) #+end_src * Blocks, Parentheses and Formatting Oh My! @@ -803,213 +811,132 @@ _SPC_ cancel _o_nly this _d_elete <>) #+end_src -* Buferlo +# #+INCLUDE: "config/bufferlo.org" :minlevel 1 +* IBuffer -The package itself sums it up best. +Buffer management is a constant irritation with any editor. After +having a bit of a performance issue when using [[https://github.com/florommel/bufferlo][bufferlo]] I've decided +to try doing something with emacs's built in IBuffer. -#+begin_quote -Easy-to-use buffer management and workspace persistence tools for Emacs workflow management. -Headbutt your way to productivity and moove ahead with [[https://github.com/florommel/bufferlo][bufferlo]]. -#+end_quote +This is *heavily* inspired, and mostly outright copied from this [[https://olddeuteronomy.github.io/post/emacs-ibuffer-config/][post]] +by [[https://olddeuteronomy.github.io][The Emacs Cat]]. -This is great for keeping tabs seperate. +Icons can make identifying buffers easy at a glance so I think adding +them is pretty handy. #+begin_src emacs-lisp -;; Bufferlo package configuration -(use-package bufferlo +(use-package all-the-icons-ibuffer :ensure t - :demand t - :after (consult orderless) + :after (all-the-icons) + :hook + (ibuffer-mode . all-the-icons-ibuffer-mode)) +#+end_src + +Now for the main part of the configuration. This provides a nice +logical grouping for buffers. As I use this more I might change +the grouping to be a bit less file type oriented, and lean more +towards use case. + +#+begin_src emacs-lisp +(use-package ibuffer :ensure nil :bind - ;; Main transient menu binding - (("C-x B" . bufferlo-transient)) ; Capital B to avoid conflict with switch-to-buffer - - :init - ;; These must be set before bufferlo is loaded - (setq bufferlo-menu-bar-show t) - (setq bufferlo-menu-bar-list-buffers 'ibuffer) - (setq bufferlo-prefer-local-buffers 'tabs) - (setq bufferlo-ibuffer-bind-local-buffer-filter t) - (setq bufferlo-ibuffer-bind-keys t) - + (("C-x B" . ibuffer)) :config - ;; Enable bufferlo mode - (bufferlo-mode 1) - - ;; Optional: Enable bufferlo-anywhere mode for local buffer lists everywhere - (bufferlo-anywhere-mode 1) - - ;; Mode-line configuration - (setq bufferlo-mode-line-prefix "🐃") - (setq bufferlo-mode-line-set-active-prefix "Ⓢ") - (setq bufferlo-mode-line-frame-prefix "Ⓕ") - (setq bufferlo-mode-line-tab-prefix "Ⓣ") - (setq bufferlo-mode-line-left-prefix nil) - (setq bufferlo-mode-line-right-suffix nil) - - ;; Buffer management policies - (setq bufferlo-kill-buffers-prompt t) - (setq bufferlo-kill-modified-buffers-policy 'retain-modified-kill-without-file-name) - (setq bufferlo-delete-frame-kill-buffers-prompt t) - (setq bufferlo-close-tab-kill-buffers-prompt t) - - ;; Bookmark configuration - (setq bufferlo-bookmark-frame-save-on-delete 'when-bookmarked) - (setq bufferlo-bookmark-tab-save-on-close 'when-bookmarked) - (setq bufferlo-bookmark-frame-load-make-frame 'restore-geometry) - (setq bufferlo-bookmark-frame-load-policy 'prompt) - (setq bufferlo-bookmark-frame-duplicate-policy 'prompt) - (setq bufferlo-bookmark-tab-replace-policy 'new) - (setq bufferlo-bookmark-tab-duplicate-policy 'prompt) - (setq bufferlo-bookmarks-save-duplicates-policy 'prompt) - - ;; Auto-save configuration (optional - adjust interval as needed) - (setopt bufferlo-bookmarks-auto-save-interval (* 60 5)) ; 5 minutes - (setq bufferlo-bookmarks-auto-save-messages 'saved) - - ;; Filter configuration for bookmark saving - (setq bufferlo-bookmark-buffers-exclude-filters - (list - (rx bos " " (1+ anything)) ; ignores "invisible" buffers - (rx bos "*" (1+ anything) "*"))) ; ignores "special" buffers - - (setq bufferlo-bookmark-buffers-include-filters - (list - (rx bos "*shell*") - (rx bos "*" (1+ anything) "-shell*") - (rx bos "*eshell*") - (rx bos "*" (1+ anything) "-eshell*"))) - - ;; New tabs start with scratch buffer - (setq tab-bar-new-tab-choice "*scratch*") - - ;; New frames start with scratch buffer - (add-hook 'after-make-frame-functions #'bufferlo-switch-to-scratch-buffer) - - ;; Consult integration - (defvar my:bufferlo-consult--source-local-buffers - (list :name "Bufferlo Local Buffers" - :narrow ?l - :category 'buffer - :face 'consult-buffer - :history 'buffer-name-history - :state #'consult--buffer-state - :default t - :items (lambda () (consult--buffer-query - :predicate #'bufferlo-local-buffer-p - :sort 'visibility - :as #'buffer-name))) - "Local Bufferlo buffer candidate source for `consult-buffer'.") - - (defvar my:bufferlo-consult--source-other-buffers - (list :name "Bufferlo Other Buffers" - :narrow ?o - :category 'buffer - :face 'consult-buffer - :history 'buffer-name-history - :state #'consult--buffer-state - :items (lambda () (consult--buffer-query - :predicate #'bufferlo-non-local-buffer-p - :sort 'visibility - :as #'buffer-name))) - "Non-local Bufferlo buffer candidate source for `consult-buffer'.") - - (defvar my:bufferlo-consult--source-all-buffers - (list :name "Bufferlo All Buffers" - :narrow ?a - :hidden t - :category 'buffer - :face 'consult-buffer - :history 'buffer-name-history - :state #'consult--buffer-state - :items (lambda () (consult--buffer-query - :sort 'visibility - :as #'buffer-name))) - "All Bufferlo buffer candidate source for `consult-buffer'.") - - ;; Add consult sources in reverse order of display preference - (add-to-list 'consult-buffer-sources 'my:bufferlo-consult--source-all-buffers) - (add-to-list 'consult-buffer-sources 'my:bufferlo-consult--source-other-buffers) - (add-to-list 'consult-buffer-sources 'my:bufferlo-consult--source-local-buffers)) - -;; Transient menu for bufferlo -(use-package transient - :ensure t - :after bufferlo - :config - (transient-define-prefix bufferlo-transient () - "Bufferlo management menu." - ["Buffer Management" - ["Local Buffers" - ("b" "Switch to buffer" bufferlo-switch-to-buffer) - ("B" "List buffers" bufferlo-list-buffers) - ("i" "Ibuffer (local)" bufferlo-ibuffer)] - ["Buffer Operations" - ("c" "Clear local list" bufferlo-clear) - ("r" "Remove buffer" bufferlo-remove) - ("k" "Kill local buffers" bufferlo-kill-buffers) - ("K" "Kill orphan buffers" bufferlo-kill-orphan-buffers)]] - - ["Bookmarks" - ["Frame Bookmarks" - ("fs" "Save frame" bufferlo-bookmark-frame-save) - ("fu" "Update frame" bufferlo-bookmark-frame-save-current) - ("fl" "Load frame" bufferlo-bookmark-frame-load) - ("fr" "Reload frame" bufferlo-bookmark-frame-load-current) - ("fm" "Merge frame" bufferlo-bookmark-frame-load-merge)] - ["Tab Bookmarks" - ("ts" "Save tab" bufferlo-bookmark-tab-save) - ("tu" "Update tab" bufferlo-bookmark-tab-save-current) - ("tl" "Load tab" bufferlo-bookmark-tab-load) - ("tr" "Reload tab" bufferlo-bookmark-tab-load-current)]] - - ["Bookmark Sets & Management" - ["Sets" - ("ss" "Save set" bufferlo-set-save-interactive) - ("su" "Update set" bufferlo-set-save-current-interactive) - ("sl" "Load set" bufferlo-set-load-interactive) - ("sc" "Close set" bufferlo-set-close-interactive) - ("sC" "Clear set" bufferlo-set-clear-interactive) - ("sL" "List sets" bufferlo-set-list-interactive)] - ["General" - ("L" "Load bookmarks" bufferlo-bookmarks-load-interactive) - ("S" "Save bookmarks" bufferlo-bookmarks-save-interactive) - ("C" "Close bookmarks" bufferlo-bookmarks-close-interactive) - ("R" "Raise bookmark" bufferlo-bookmark-raise)]] - - ["Navigation & Utilities" - ["Navigation" - ("/" "Find buffer" bufferlo-find-buffer) - ("." "Find & switch" bufferlo-find-buffer-switch) - ("o" "List orphans" bufferlo-list-orphan-buffers) - ("O" "Ibuffer orphans" bufferlo-ibuffer-orphans)] - ["Project" - ("p" "Isolate project" bufferlo-isolate-project)] - ["Frame/Tab Operations" - ("d" "Delete frame & kill buffers" bufferlo-delete-frame-kill-buffers) - ("x" "Close tab & kill buffers" bufferlo-tab-close-kill-buffers)]] - - ["Quick Actions" - ("q" "Quit" transient-quit-one) - ("" "Quit" transient-quit-one)])) - -;; Optional: Additional helper functions for common workflows -(defun my/bufferlo-switch-project () - "Switch to a project and isolate its buffers." - (interactive) - (call-interactively 'project-switch-project) - (bufferlo-isolate-project)) - -(defun my/bufferlo-new-workspace (name) - "Create a new tab with a specific bookmark name." - (interactive "sWorkspace name: ") - (tab-bar-new-tab) - (bufferlo-bookmark-tab-save name)) - -(defun my/bufferlo-switch-workspace () - "Switch to a saved workspace (tab bookmark)." - (interactive) - (call-interactively 'bufferlo-bookmark-tab-load)) + (setq ibuffer-expert t) + (setq ibuffer-display-summary nil) + (setq ibuffer-use-other-window nil) + (setq ibuffer-show-empty-filter-groups nil) + (setq ibuffer-default-sorting-mode 'filename/process) + (setq ibuffer-title-face 'font-lock-doc-face) + (setq ibuffer-use-header-line t) + (setq ibuffer-default-shrink-to-minimum-size nil) + (setq ibuffer-formats + '((mark modified read-only locked " " + (name 30 30 :left :elide) + " " + (size 9 -1 :right) + " " + (mode 16 16 :left :elide) + " " filename-and-process) + (mark " " + (name 16 -1) + " " filename))) + (setq ibuffer-saved-filter-groups + '(("Main" + ("Directories" (mode . dired-mode)) + ("C++" (or + (mode . c++-mode) + (mode . c++-ts-mode) + (mode . c-mode) + (mode . c-ts-mode) + (mode . c-or-c++-ts-mode))) + ("Python" (or + (mode . python-ts-mode) + (mode . c-mode) + (mode . python-mode))) + ("Build" (or + (mode . make-mode) + (mode . makefile-gmake-mode) + (name . "^Makefile$") + (mode . change-log-mode))) + ("Scripts" (or + (mode . shell-script-mode) + (mode . shell-mode) + (mode . sh-mode) + (mode . lua-mode) + (mode . bat-mode))) + ("Config" (or + (mode . conf-mode) + (mode . conf-toml-mode) + (mode . toml-ts-mode) + (mode . conf-windows-mode) + (name . "^\\.clangd$") + (name . "^\\.gitignore$") + (name . "^Doxyfile$") + (name . "^config\\.toml$") + (mode . yaml-mode))) + ("Web" (or + (mode . mhtml-mode) + (mode . html-mode) + (mode . web-mode) + (mode . nxml-mode))) + ("CSS" (or + (mode . css-mode) + (mode . sass-mode))) + ("JS" (or + (mode . js-mode) + (mode . rjsx-mode))) + ("Markup" (or + (mode . markdown-mode) + (mode . adoc-mode))) + ("Org" (mode . org-mode)) + ("LaTeX" (name . "\.tex$")) + ("Magit" (or + (mode . magit-blame-mode) + (mode . magit-cherry-mode) + (mode . magit-diff-mode) + (mode . magit-log-mode) + (mode . magit-process-mode) + (mode . magit-status-mode))) + ("Apps" (or + (mode . elfeed-search-mode) + (mode . elfeed-show-mode))) + ("Fundamental" (or + (mode . fundamental-mode) + (mode . text-mode))) + ("Emacs" (or + (mode . emacs-lisp-mode) + (name . "^\\*Help\\*$") + (name . "^\\*Custom.*") + (name . "^\\*Org Agenda\\*$") + (name . "^\\*info\\*$") + (name . "^\\*scratch\\*$") + (name . "^\\*Backtrace\\*$") + (name . "^\\*Messages\\*$")))))) + :hook + (ibuffer-mode . (lambda () + (ibuffer-switch-to-saved-filter-groups "Main"))) +) #+end_src * Error Checking @@ -1296,7 +1223,7 @@ certain dependencies. It will function without them however. ("d" "~/Downloads/" "Downloads") ("s" "/ssh:192.168.88.1" "SSH server"))) :config - (dirvish-peek-mode) ; Preview files in minibuffer + ;;(dirvish-peek-mode) ; Preview files in minibuffer (dirvish-side-follow-mode) ; similar to `treemacs-follow-mode' (setq dirvish-mode-line-format '(:left (sort symlink) :right (omit yank index))) @@ -1483,6 +1410,17 @@ I like using catppuccin from time to time as well. (use-package catppuccin-theme :ensure t) #+end_src +* Icons + +Some Icons might spruce things up a bit. Might as well try to have +[[https://github.com/domtronn/all-the-icons.el][all the icons]]! + +#+begin_src emacs-lisp +(use-package all-the-icons + :ensure t + :if (display-graphic-p)) +#+end_src + ** Modeline Doom emacs has a great modeline in my opinion so I'm using theirs almost diff --git a/config.org b/config.org index 441f6ac..ad31a71 100644 --- a/config.org +++ b/config.org @@ -221,7 +221,8 @@ features. #+INCLUDE: "config/hydra.org" :minlevel 1 -#+INCLUDE: "config/bufferlo.org" :minlevel 1 +# #+INCLUDE: "config/bufferlo.org" :minlevel 1 +#+INCLUDE: "config/ibuffer.org" :minlevel 1 #+INCLUDE: "config/error.org" :minlevel 1 diff --git a/config/files.org b/config/files.org index 4416dd3..59add4e 100644 --- a/config/files.org +++ b/config/files.org @@ -37,7 +37,7 @@ certain dependencies. It will function without them however. ("d" "~/Downloads/" "Downloads") ("s" "/ssh:192.168.88.1" "SSH server"))) :config - (dirvish-peek-mode) ; Preview files in minibuffer + ;;(dirvish-peek-mode) ; Preview files in minibuffer (dirvish-side-follow-mode) ; similar to `treemacs-follow-mode' (setq dirvish-mode-line-format '(:left (sort symlink) :right (omit yank index))) diff --git a/config/gc.org b/config/gc.org index 71e5809..80f6f37 100644 --- a/config/gc.org +++ b/config/gc.org @@ -9,8 +9,9 @@ Magic Hack) to handle this. It seems to work pretty well. #+begin_src emacs-lisp ;; Garbage collection (use-package gcmh - :ensure t - :hook (after-init . gcmh-mode) + :demand t + :init + (gcmh-mode) :custom (gcmh-idle-delay 'auto) (gcmh-auto-idle-delay-factor 10)) diff --git a/config/general.org b/config/general.org index fe1c244..882d5d1 100644 --- a/config/general.org +++ b/config/general.org @@ -100,16 +100,23 @@ There are a lot of solutions for editing files, and projects remotely. At the m #+begin_src emacs-lisp (use-feature tramp :config + (setq tramp-ssh-controlmaster-options + (concat + "-o ControlPath=/tmp/ssh-ControlPath-%%r@%%h:%%p " + "-o ControlMaster=auto -o ControlPersist=yes")) ;; Enable full-featured Dirvish over TRAMP on ssh connections ;; https://www.gnu.org/software/tramp/#Improving-performance-of-asynchronous-remote-processes (connection-local-set-profile-variables 'remote-direct-async-process '((tramp-direct-async-process . t))) (connection-local-set-profiles - '(:application tramp :protocol "ssh") + '(:application tramp :protocol "rsync") 'remote-direct-async-process) + (setq magit-tramp-pipe-stty-settings 'pty) + (with-eval-after-load 'compile + (remove-hook 'compilation-mode-hook #'tramp-compile-disable-ssh-controlmaster-options)) ;; Tips to speed up connections (setq tramp-verbose 0) (setq tramp-chunksize 2000) - (setq tramp-ssh-controlmaster-options nil)) + (setq tramp-copy-size-limit nil)) #+end_src diff --git a/config/ibuffer.org b/config/ibuffer.org new file mode 100644 index 0000000..7f1afac --- /dev/null +++ b/config/ibuffer.org @@ -0,0 +1,126 @@ +* IBuffer + +Buffer management is a constant irritation with any editor. After +having a bit of a performance issue when using [[https://github.com/florommel/bufferlo][bufferlo]] I've decided +to try doing something with emacs's built in IBuffer. + +This is *heavily* inspired, and mostly outright copied from this [[https://olddeuteronomy.github.io/post/emacs-ibuffer-config/][post]] +by [[https://olddeuteronomy.github.io][The Emacs Cat]]. + +Icons can make identifying buffers easy at a glance so I think adding +them is pretty handy. + +#+begin_src emacs-lisp +(use-package all-the-icons-ibuffer + :ensure t + :after (all-the-icons) + :hook + (ibuffer-mode . all-the-icons-ibuffer-mode)) +#+end_src + +Now for the main part of the configuration. This provides a nice +logical grouping for buffers. As I use this more I might change +the grouping to be a bit less file type oriented, and lean more +towards use case. + +#+begin_src emacs-lisp +(use-package ibuffer :ensure nil + :bind + (("C-x B" . ibuffer)) + :config + (setq ibuffer-expert t) + (setq ibuffer-display-summary nil) + (setq ibuffer-use-other-window nil) + (setq ibuffer-show-empty-filter-groups nil) + (setq ibuffer-default-sorting-mode 'filename/process) + (setq ibuffer-title-face 'font-lock-doc-face) + (setq ibuffer-use-header-line t) + (setq ibuffer-default-shrink-to-minimum-size nil) + (setq ibuffer-formats + '((mark modified read-only locked " " + (name 30 30 :left :elide) + " " + (size 9 -1 :right) + " " + (mode 16 16 :left :elide) + " " filename-and-process) + (mark " " + (name 16 -1) + " " filename))) + (setq ibuffer-saved-filter-groups + '(("Main" + ("Directories" (mode . dired-mode)) + ("C++" (or + (mode . c++-mode) + (mode . c++-ts-mode) + (mode . c-mode) + (mode . c-ts-mode) + (mode . c-or-c++-ts-mode))) + ("Python" (or + (mode . python-ts-mode) + (mode . c-mode) + (mode . python-mode))) + ("Build" (or + (mode . make-mode) + (mode . makefile-gmake-mode) + (name . "^Makefile$") + (mode . change-log-mode))) + ("Scripts" (or + (mode . shell-script-mode) + (mode . shell-mode) + (mode . sh-mode) + (mode . lua-mode) + (mode . bat-mode))) + ("Config" (or + (mode . conf-mode) + (mode . conf-toml-mode) + (mode . toml-ts-mode) + (mode . conf-windows-mode) + (name . "^\\.clangd$") + (name . "^\\.gitignore$") + (name . "^Doxyfile$") + (name . "^config\\.toml$") + (mode . yaml-mode))) + ("Web" (or + (mode . mhtml-mode) + (mode . html-mode) + (mode . web-mode) + (mode . nxml-mode))) + ("CSS" (or + (mode . css-mode) + (mode . sass-mode))) + ("JS" (or + (mode . js-mode) + (mode . rjsx-mode))) + ("Markup" (or + (mode . markdown-mode) + (mode . adoc-mode))) + ("Org" (mode . org-mode)) + ("LaTeX" (name . "\.tex$")) + ("Magit" (or + (mode . magit-blame-mode) + (mode . magit-cherry-mode) + (mode . magit-diff-mode) + (mode . magit-log-mode) + (mode . magit-process-mode) + (mode . magit-status-mode))) + ("Apps" (or + (mode . elfeed-search-mode) + (mode . elfeed-show-mode))) + ("Fundamental" (or + (mode . fundamental-mode) + (mode . text-mode))) + ("Emacs" (or + (mode . emacs-lisp-mode) + (name . "^\\*Help\\*$") + (name . "^\\*Custom.*") + (name . "^\\*Org Agenda\\*$") + (name . "^\\*info\\*$") + (name . "^\\*scratch\\*$") + (name . "^\\*Backtrace\\*$") + (name . "^\\*Messages\\*$")))))) + :hook + (ibuffer-mode . (lambda () + (ibuffer-switch-to-saved-filter-groups "Main"))) +) +#+end_src diff --git a/config/style.org b/config/style.org index f39a8fc..a11f178 100644 --- a/config/style.org +++ b/config/style.org @@ -23,6 +23,17 @@ I like using catppuccin from time to time as well. (use-package catppuccin-theme :ensure t) #+end_src +* Icons + +Some Icons might spruce things up a bit. Might as well try to have +[[https://github.com/domtronn/all-the-icons.el][all the icons]]! + +#+begin_src emacs-lisp +(use-package all-the-icons + :ensure t + :if (display-graphic-p)) +#+end_src + ** Modeline Doom emacs has a great modeline in my opinion so I'm using theirs almost