#+title: init.el.org #+date: [2025-03-18 Tue] #+lastmod: [2025-03-18 Tue 20:37] #+draft: false #+tags: emacs * My Emacs configuration :PROPERTIES: :header-args: :tangle ~/.emacs.d/init.el :END: More about [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html][the Emacs initialization file]] ~~/.emacs.d/init.el~ is generated from this org file with [[https://orgmode.org/worg/org-contrib/babel/][Org-babel]] How to tangle: ~M-x org-babel-tangle~ or ~C-c C-v t~ My Emacs repository: [[https://git.minded.net/anne/emacs][git.minded.net/anne/emacs]] The source version of this file: [[https://git.minded.net/anne/emacs/src/branch/main/init.el.org?display=source][git.minded.net/anne/emacs/src/branch/main/init.el.org]] Or view this file on my blog: [[https://blog.minded.net/emacs][blog.minded.net/emacs/init.el.org]] ** About me #+begin_src elisp (setq user-full-name "Anne" user-mail-address "anne@minded.net") #+end_src ** System #+begin_src elisp (setq laptop-p (equal (system-name) "siskin")) #+end_src ** Use-package [[https://github.com/jwiegley/use-package]] #+begin_src elisp (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) (package-initialize) (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (require 'use-package) (setq use-package-always-ensure 't) #+end_src ** Reload configuration ~M-x reload-emacs-init~ #+begin_src elisp (defun reload-emacs-init () (interactive) (load-file "~/.emacs.d/init.el") (message "Configuarion reloaded!")) #+end_src ** Customizations file [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Saving-Customizations.html]] You can choose to save customizations somewhere other than your initialization file. #+begin_src elisp (setq custom-file "~/.emacs.d/custom.el") (load custom-file 'noerror 'nomessage) #+end_src ** Lock files [[https://www.gnu.org/software/emacs/manual/html_node/elisp/File-Locks.html]] If create-lockfiles is nil, Emacs does not lock files. #+begin_src elisp :tangle no (setq create-lockfiles nil) #+end_src ** Yes-or-no prompts [[https://www.emacswiki.org/emacs/YesOrNoP]] #+begin_src elispx1 (defalias 'yes-or-no-p 'y-or-n-p) #+end_src ** Keeping buffers up-to-date [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Auto-Revert.html]] #+begin_src elisp (global-auto-revert-mode 1) (setq global-auto-revert-non-file-buffers t) #+end_src ** Looks *** Initial frame configuration [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Initial-Parameters.html]] A bigger frame for the gui of Emacs. #+begin_src elisp (add-to-list 'default-frame-alist '(height . 56)) (add-to-list 'default-frame-alist '(width . 132)) #+end_src *** Frame font [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Frame-Font.html]] #+begin_src elisp (ignore-errors (set-frame-font "Roboto Mono-10")) #+end_src *** Disable startup screen [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Startup-Summary.html]] #+begin_src elisp (setq inhibit-startup-screen nil) #+end_src *** What to display [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Frames.html]] I do like the menu bar after all. #+begin_src elisp (if laptop-p (scroll-bar-mode -1)) (tool-bar-mode -1) ;;(menu-bar-mode -1) (tooltip-mode -1) #+end_src *** Mode line column and line numbers [[https://www.gnu.org/software/emacs/manual/html_node/efaq/Displaying-the-current-line-or-column.html]] #+begin_src elisp (column-number-mode t) #+end_src *** Mood-line [[https://gitlab.com/jessieh/mood-line]] A lightweight, drop-in replacement for the default Emacs mode line configuration. #+begin_src elisp (use-package mood-line :config (mood-line-mode)) (setq mood-line-format mood-line-format-default) #+end_src *** DISABLED Diminish [[https://github.com/myrjola/diminish.el]] Diminish implements hiding or abbreviation of the mode line displays (lighters) of minor-modes. With Mood-line there's no need to diminish #+begin_src elisp :tangle no (use-package diminish :ensure t) #+end_src *** Suppress dialog boxes [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Dialog-Boxes.html]] #+begin_src elisp (setq use-dialog-box nil) #+end_src *** Sentences [[https://www.gnu.org/software/emacs/manual/html_node/efaq/Filling-paragraphs-with-a-single-space.html]] #+begin_src elisp (setq sentence-end-double-space nil) #+end_src *** DISABLED Rainbow delimiters [[https://github.com/Fanael/rainbow-delimiters]] #+begin_src elisp :tangle no (use-package rainbow-delimiters :init (add-hook 'text-mode-hook #'rainbow-delimiters-mode) (add-hook 'prog-mode-hook #'rainbow-delimiters-mode)) #+end_src *** Doom themes [[https://github.com/doomemacs/themes]] #+begin_src elisp (use-package doom-themes :ensure t :config (setq doom-themes-enable-bold t ; if nil, bold is universally disabled doom-themes-enable-italic t ; if nil, italics is universally disabled doom-themes-padded-modeline t) (load-theme 'doom-vibrant t) ;;(setq doom-horizon-brighter-comments nil) (setq doom-themes-treemacs-theme "doom-colors") ; use "doom-colors" for less minimal icon theme (doom-themes-treemacs-config) (doom-themes-org-config) ; corrects (and improves) org-mode's native fontification (custom-set-faces '(font-lock-comment-face ((t (:foreground "#6c6f93" :slant normal)))) '(org-hide ((t (:foreground "grey15")))) '(org-scheduled-today ((t (:foreground "violet")))) '(org-todo ((t (:foreground "magenta")))) '(org-done ((t (:foreground "#9ca0a4" :bold nil :background "grey15")))) '(org-tag ((t (:foreground "teal")))) '(org-link ((t (:bold nil)))))) #+end_src *** all-the-icons [[https://github.com/domtronn/all-the-icons.el]] #+begin_src elisp (use-package all-the-icons :if (display-graphic-p)) (use-package all-the-icons-dired :after all-the-icons :hook (dired-mode . all-the-icons-dired-mode)) #+end_src *** Minibuffer [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Minibuffer-Edit.html]] The variable ~resize-mini-windows~ controls the resizing of the minibuffer. If the value is t, the minibuffer window will also shrink automatically if you remove some lines of text from the minibuffer, down to a minimum of one screen line. The variable ~max-mini-window-height~ controls the maximum height for resizing the minibuffer window. A floating-point number specifies a fraction of the frame’s height; an integer specifies the maximum number of lines; nil means do not resize the minibuffer window automatically. The default value is 0.25. #+begin_src elisp (setq resize-mini-windows t) (setq max-mini-window-height 0.5) #+end_src *** Word wrap [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Visual-Line-Mode.html]] #+begin_src elisp (add-hook 'text-mode-hook 'visual-line-mode) #+end_src ** Editing and moving around *** Mouse support [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Mouse-Input.html]] #+begin_src elisp (xterm-mouse-mode 1) (mouse-wheel-mode 1) (context-menu-mode 1) #+end_src *** xclip [[https://elpa.gnu.org/packages/xclip.html]] This package allows Emacs to copy to and paste from the GUI clipboard when running in text terminal. #+begin_src elisp (use-package xclip :if laptop-p :init (xclip-mode 1)) #+end_src *** Kill-line [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Killing-by-Lines.html]] If non-nil, ~kill-line~ with no arg at start of line kills the whole line. #+begin_src elisp (setq kill-whole-line t) #+end_src *** Indentation [[https://www.gnu.org/software/emacs/manual/html_node/eintr/Indent-Tabs-Mode.html]] #+begin_src elisp (setq-default indent-tabs-mode nil) #+end_src *** Electric pair mode [[https://emacsdocs.org/docs/emacs/Matching]] #+begin_src elisp (electric-pair-mode 1) #+end_src *** Overwrite highlighted region [[https://www.gnu.org/software/emacs/manual/html_node/efaq/Replacing-highlighted-text.html]] #+begin_src elisp (delete-selection-mode t) #+end_src *** Scrolling [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Scrolling.html]] #+begin_src elisp (setq scroll-error-top-bottom t) #+end_src *** Cursor [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Cursor-Display.html]] #+begin_src elisp (global-hl-line-mode t) #+end_src *** Window handling [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Window-Convenience.html]] Winner mode is a global minor mode that records the changes in the window configuration (i.e., how the frames are partitioned into windows), so that you can undo them. #+begin_src elisp (winner-mode 1) #+end_src The Windmove package defines commands for moving directionally between neighboring windows in a frame. #+begin_src elisp (use-package windmove :bind ((" " . windmove-right) (" " . windmove-left) (" " . windmove-up) (" " . windmove-down))) #+end_src ** Crux [[https://github.com/bbatsov/crux]] A Collection of Ridiculously Useful eXtensions for Emacs. crux bundles many useful interactive commands to enhance your overall Emacs experience. #+begin_src elisp (use-package crux :bind ("C-a" . crux-move-beginning-of-line) ("C-c o" . crux-open-with) ("C-k" . crux-kill-whole-line) :config (crux-with-region-or-buffer indent-region) (crux-with-region-or-buffer untabify) (crux-with-region-or-line comment-or-uncomment-region) :hook (before-save-hook . crux-cleanup-buffer-or-region)) #+end_src ** Dired [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Dired.html]] #+begin_src elisp (put 'dired-find-alternate-file 'disabled nil) (setq dired-listing-switches "-agho --group-directories-first") #+end_src ** Kill buffer #+begin_src elisp (global-set-key (kbd "C-x k") 'kill-this-buffer) #+end_src ** Unset C-z Unset C-z which is bound to `suspend-frame' by default. #+begin_src elisp (global-unset-key (kbd "C-z")) #+end_src ** Saving files *** Backups [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Backup.html]] Automatically backup buffers/files into the ~.emacs.d/backup/ directory. #+begin_src elisp (setq backup-directory-alist '(("." . "~/.emacs.d/backups"))) (setq backup-by-copying t ; Don't delink hardlinks version-control t ; Use version numbers on backups delete-old-versions t ; Automatically delete excess backups kept-new-versions 20 ; how many of the newest versions to keep kept-old-versions 5) ; and how many of the old #+end_src *** Auto save [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Auto-Save-Control.html]] #+begin_src elisp (setq auto-save-timeout 20 ; number of seconds idle time before auto-save (default: 30) auto-save-interval 200) ; number of keystrokes between auto-saves (default: 300) #+end_src *** Lastmod time stamp #+begin_src elisp (setq time-stamp-start "\\(^:last_modified: \\\\?[\[<]+\\|^#\\+lastmod: \\\\?[\[<]+\\|^;; lastmod: \\\\?[\[<]+\\)") (setq time-stamp-end "\\\\?[\]>]") (setq time-stamp-format "%Y-%02m-%02d %3a %02H:%02M") (setq time-stamp-limit 12) (add-hook 'before-save-hook 'time-stamp) (setq time-stamp-active t) #+end_src ** Magit [[https://magit.vc/]] [[https://systemcrafters.net/mastering-git-with-magit/introduction/]] #+begin_src elisp (use-package magit :ensure t) #+end_src ** Treemacs [[https://github.com/Alexander-Miller/treemacs]] A tree layout file explorer for Emacs. #+begin_src elisp (use-package treemacs :ensure t :defer t :init (with-eval-after-load 'winum (define-key winum-keymap (kbd "M-0") #'treemacs-select-window)) :config (setq treemacs-show-hidden-files nil) :bind (:map global-map ("M-0" . treemacs-select-window) ("C-x t 1" . treemacs-delete-other-windows) ("C-x t t" . treemacs) ("" . treemacs) ("C-x t d" . treemacs-select-directory) ("C-x t B" . treemacs-bookmark) ("C-x t C-t" . treemacs-find-file) ("C-x t M-t" . treemacs-find-tag))) (use-package treemacs-icons-dired :hook (dired-mode . treemacs-icons-dired-enable-once) :ensure t) (use-package nerd-icons ;; :custom ;; The Nerd Font you want to use in GUI ;; "Symbols Nerd Font Mono" is the default and is recommended ;; but you can use any other Nerd Font if you want ;; (nerd-icons-font-family "Symbols Nerd Font Mono") ) (use-package treemacs-nerd-icons :config (treemacs-load-theme "nerd-icons")) (use-package treemacs-magit :after (treemacs magit) :ensure t) #+end_src ** Which-key [[https://github.com/justbur/emacs-which-key]] which-key is a minor mode for Emacs that displays the key bindings following your currently entered incomplete command (a prefix) in a popup. #+begin_src elisp (use-package which-key :config (which-key-mode) (setq which-key-idle-delay 0.5 which-key-idle-secondary-delay 0.5) (which-key-setup-side-window-bottom)) #+end_src ** Helm [[https://emacs-helm.github.io/helm/]] Helm is an Emacs framework for incremental completions and narrowing selections. It helps to rapidly complete file names, buffer names, or any other Emacs interactions requiring selecting an item from a list of possible choices. #+begin_src elisp (use-package helm :ensure t :config ;;(require 'helm-config) :init (helm-mode 1) (setq helm-split-window-inside-p t) :diminish helm-mode :bind (("M-x" . helm-M-x) ; Evaluate functions ("C-x C-f" . helm-find-files) ; Open or create files ("C-x b" . helm-mini) ; Select buffers ("C-x C-b" . helm-buffers-list) ("C-x C-r" . helm-recentf) ; Select recently saved files ("C-c i" . helm-imenu) ; Select document heading ("M-y" . helm-show-kill-ring) ; Show the kill ring ("C-x c g" . helm-do-grep-ag) :map helm-map ("C-z" . helm-select-action) ("" . helm-execute-persistent-action))) #+end_src ** Org Mode *** Org Mode on my laptop [[https://orgmode.org/org.html]] #+begin_src elisp (use-package org :if laptop-p :bind (("C-c l" . org-store-link) ("C-c a" . org-agenda) ("C-c c" . org-capture)) :config (setq org-directory "~/org" org-default-notes-file "~/org/agenda/inbox.org" org-attach-id-dir "~/org/data/") ;;(setq org-agenda-text-search-extra-files (directory-files-recursively "~/org/" "\\.org$")) (add-to-list 'auto-mode-alist '("\\.org\\'" . org-mode)) (setq org-startup-indented nil org-pretty-entities t org-hide-emphasis-markers t org-hide-leading-stars nil org-startup-with-inline-images t org-image-actual-width '(300) org-tags-column 0 org-log-done 'time org-log-into-drawer t org-deadline-warning-days 7 org-refile-targets '((org-agenda-files :maxlevel . 5)) org-refile-use-outline-path 'file org-outline-path-complete-in-steps nil org-refile-allow-creating-parent-nodes 'confirm) ;;(setq org-blank-before-new-entry (quote ((heading) (plain-list-item)))) (advice-add 'org-refile :after 'org-save-all-org-buffers) (setq org-capture-templates '(("t" "Task" entry (file "~/org/agenda/todo.org") "* TODO %?\n:PROPERTIES:\n:CREATED: %U\n:END:" :empty-lines 1) ("n" "Note" entry (file org-default-notes-file) "* %?\n:PROPERTIES:\n:CREATED: %U\n:END:" :empty-lines 1) ("j" "Journal entry" entry (file+olp+datetree "~/org/journal.org") "* %?" :unnarrowed t :empty-lines-after 1) ("J" "Journal entry on date" entry (file+olp+datetree "~/org/journal.org") "* %?" :time-prompt t :unnarrowed t :empty-lines-after 1) ("m" "Meeting" entry (file+olp+datetree "~/org/agenda/agenda.org") "* %?\n%T" :time-prompt t :tree-type month :empty-lines 1) ("a" "Agenda entry" entry (file+olp+datetree "~/org/agenda/agenda.org") "* %?\n%t" :time-prompt t :tree-type month :empty-lines 1))) (setq org-todo-keywords '((sequence "TODO(t)" "STARTED(s)" "WAITING" "SOMEDAY" "MAYBE" "|" "DONE(d)" "CANCELLED(c)") (sequence "TOREAD(r)" "READING" "|" "READ") (sequence "TOWATCH(w)" "WATCHING" "|" "WATCHED")))) #+end_src *** Org Mode on other systems #+begin_src elisp (use-package org :if (not laptop-p) :bind (("C-c l" . org-store-link) ("C-c a" . org-agenda) ("C-c c" . org-capture)) :config (setq org-directory "~/org" org-default-notes-file "~/org/notes.org" org-agenda-files '("~/org")) (add-to-list 'auto-mode-alist '("\\.org\\'" . org-mode)) (setq org-startup-indented nil org-pretty-entities t org-hide-emphasis-markers t org-hide-leading-stars nil org-startup-with-inline-images t org-image-actual-width '(300) org-tags-column 0 org-log-done 'time org-log-into-drawer t org-deadline-warning-days 7 org-refile-targets '((org-agenda-files :maxlevel . 5)) org-refile-use-outline-path 'file org-outline-path-complete-in-steps nil org-refile-allow-creating-parent-nodes 'confirm) (advice-add 'org-refile :after 'org-save-all-org-buffers) (setq org-capture-templates '(("t" "Task" entry (file org-default-notes-file) "* TODO %?\n:PROPERTIES:\n:CREATED: %U\n:CONTEXT: %a\n:END:" :empty-lines 1) ("n" "Note" entry (file org-default-notes-file) "* %?\n:PROPERTIES:\n:CREATED: %U\n:CONTEXT: %a\n:END:" :empty-lines 1)))) #+end_src *** Helm-org [[https://github.com/emacs-helm/helm-org]] #+begin_src elisp (use-package helm-org :after helm :config (add-to-list 'helm-completing-read-handlers-alist '(org-capture . helm-org-completing-read-tags)) (add-to-list 'helm-completing-read-handlers-alist '(org-set-tags . helm-org-completing-read-tags))) #+end_src *** org-super-agenda [[https://github.com/alphapapa/org-super-agenda]] #+begin_src elisp (use-package org-super-agenda :if laptop-p :after org-agenda :init (setq org-agenda-files '("~/org" "~/org/agenda" "~/org/notes")) ;;(setq org-agenda-text-search-extra-files (directory-files-recursively "~/org/" "\\.org$")) (setq calendar-week-start-day 1) (calendar-set-date-style 'european) (setq calendar-time-display-form '(24-hours ":" minutes (if time-zone " (") time-zone (if time-zone ")"))) (setq org-agenda-format-date (lambda (date) (concat "\n" (org-agenda-format-date-aligned date)))) (setq org-agenda-start-day nil) (setq org-agenda-span 'day) (setq use-agenda-use-time-grid nil) (setq org-agenda-start-on-weekday nil) (setq org-agenda-include-diary nil) (setq org-agenda-tags-column 0) (setq org-agenda-skip-scheduled-if-done t) (setq org-agenda-skip-deadline-if-done t) (setq org-agenda-include-deadlines t) (setq org-agenda-block-separator nil) (setq org-agenda-compact-blocks t) (setq org-agenda-start-with-log-mode nil) (setq org-agenda-sticky t) (setq org-agenda-dim-blocked-tasks nil) (setq org-agenda-custom-commands '(("d" "Daily agenda" ((agenda "" ((org-super-agenda-groups '((:discard (:todo "CANCELLED")) (:discard (:file-path "someday")) (:name none :file-path "days" :file-path "people" :tag "day") (:name "Scheduled" :time-grid t) (:auto-tags t :order 5) (:name "Today" :and (:todo t :scheduled t) :deadline t :order 3) )))))) ("t" "Todo" ((agenda "" ((org-super-agenda-groups '( (:name none :discard (:file-path "days") :discard (:file-path "people") :discard (:tag "day")) (:auto-tags t :order 5) (:name "Today" :and (:todo t :scheduled t :not (:todo "SOMEDAY")) :deadline t :order 3) (:discard (:anything t)) )))) (alltodo "" ((org-agenda-overriding-header "\nUnscheduled") (org-super-agenda-groups '( (:discard (:deadline t) :discard (:scheduled t) :discard (:todo "SOMEDAY") :discard (:file-path "someday")) (:auto-tags t :order 0) (:name "Tags: none" :not (:scheduled t) :and (:file-path "todo") :order 9) (:discard (:anything t)) )))))) ("x" "Daily schedule" ((agenda "" ((org-super-agenda-groups '( (:name none :file-path "days" :file-path "people" :tag "day") (:name none :time-grid nil) (:name none :discard (:todo t)) )))))))) :config (org-super-agenda-mode t)) (if laptop-p (defun pop-to-org-agenda (&optional split) (interactive "P") (org-agenda nil "d") (delete-other-windows) (treemacs) (windmove-right))) (if laptop-p (global-set-key (kbd "") 'pop-to-org-agenda)) #+end_src *** Org-appear [[https://github.com/awth13/org-appear]] Make invisible parts of Org elements appear visible. #+begin_src elisp (use-package org-appear :load-path "~/.emacs.d/etc/elisp/org-appear" :hook (org-mode . org-appear-mode) :init (setq org-appear-autolinks t)) #+end_src Hide emphasis markers by default. #+begin_src elisp (setq org-hide-emphasis-markers t) #+end_src