Doom Emacs configuration
Table of Contents
- 1. Table of Contents TOC_2_org
- 2. Overview
- 3. Default settings
- 4. Improvements
- 4.1. Dired improvements
- 4.2. Projectile improvements
- 4.3. Doom modeline adjustments
- 4.4. Suppress messages in minibuffer
- 4.5. Magit auto save
- 4.6. Scrolling
- 4.7. Open treemacs on startup
- 4.8. Mac change option to control
- 4.9. Display ANSI color codes
- 4.10. Open currently open file in VSCode
- 4.11. Open treemacs after opening project
- 5. Org mode
- 6. Keybindings
- 7. Utilities
- 8. Troubleshooting
1. Table of Contents TOC_2_org
2. Overview
2.1. Introduction
Welcome to my improved Doom Emacs configuration.
This is my actual live configuration. It’s written using the literate programming
concept in mind, using my personalized Doom Emacs editor with org mode.
This webpage has been exported from a single org file, with the help of the readtheorg theme. Using this approach, it costs me nearly zero effort to keep my config in sync with this documentation.
The code blocks in this document are eventually tangled to the /.doom.d/config.el
file, and this file takes the documentation of it.
As this document is always a work in progress, you may find incomplete, non functional or commented config. The configuration is divided between 5 categories with subcategories underneath.
2.2. Dependencies
2.2.1. Emacs
Refer to the getting started guide, in order to install the dependencies that Doom Emacs requires.
Also, install fira code fonts. Mac homebrew instructions below.
brew install cask font-fira-code
2.2.2. Lang
A doom doctor
run yields:
> Checking your enabled modules… > :lang org ! Couldn’t find the pngpaste executable. org-download-clipboard will not work. > :lang sh ! Couldn’t find shellcheck. Shell script linting will not work > :lang web ! Couldn’t find stylelint. Linting for CSS modes will not work. ! Couldn’t find js-beautify. Code formatting in JS/CSS/HTML modes will not work.
Install to fix.
brew install pngpaste shellcheck yarn
And install the following web-mode deps.
yarn global add stylelint stylelint-config-standard js-beautify
The doom doctor should be happy again!
2.3. Keybindings
As a personal cheatsheet, I’ve created a few tables of all the (extra) keybindings this configuration exposes, to make sure I remember and that I can reference them quickly when needed.
2.3.1. Dired
Keybindings related to dired.
Description | Keybinding |
---|---|
Open dired | spc d d |
Open dired in dir of current buffer | spc d j |
Image previews inside dired (need to test) | spc d p |
Dired view file inside dired (need to test) | spc d v |
2.3.2. Registers
Keybindings related to accessing the Emacs register.
Description | Keybinding |
---|---|
Copy to register | spc r c |
Frameset to register | spc r f |
Insert contents of register | spc r i |
Jump to register | spc r j |
List registers | spc r l |
Number to register | spc r n |
Interactively choose a register | spc r r |
View a register | spc r v |
Window configuration to register | spc r w |
Increment register | spc r + |
Point to register | spc r SPC |
2.3.3. Bookmarks
Keybindings related to bookmarks.
Description | Keybinding |
---|---|
Open bookmarks list | spc b h |
2.3.4. Elisp
Keybindings related to executing elisp code.
Description | Keybinding |
---|---|
Evaluate elisp in buffer | spc e b |
Evaluate defun | spc e d |
Evaluate elisp expression | spc e e |
Evaluate last sexpression | spc e l |
Evaluate elisp in region | spc e r |
2.4. Summary
The headings above contains documentation, and the code blocks underneath contain my actual Doom Emacs configuration.
3. Default settings
This heading contains some random configurable emacs settings.
3.1. Username and e-mail
Set your username and e-mail. Some functionality uses this to identify you, e.g. GPG configuration, email clients, file templates and snippets.
(setq user-full-name "hyperfocus" user-mail-address "email@email.com")
3.2. Notebook location
Store the location of my notes notebook for consumption in this config.
(defvar notes-directory "~/Library/CloudStorage/Dropbox/Notebooks/notebook/notes") (defvar notebook-directory "~/Library/CloudStorage/Dropbox/Notebooks/notebook")
3.3. Default theme
Start Doom emacs with a light or dark theme, during the day I prefer the light time, during the night I prefer the dark theme.
(setq doom-theme 'doom-tomorrow-day) ;; (setq doom-theme 'doom-solarized-light) ;; (setq doom-theme 'doom-one-light) ;; (setq doom-theme 'doom-one)
3.4. Default shell
Change default shell used in Emacs to bash, due to the following message displayed by doom doctor
.
Fish (and possibly other non-POSIX shells) is known to inject garbage output into some of the child processes that Emacs spawns. Many Emacs packages/utilities will choke on this output, causing unpredictable issues. To get around this, either:
Add the following to $DOOMDIR/config.el:
(setq shell-file-name (executable-find “bash”))
- Or change your default shell to a POSIX shell (like bash or zsh) and explicitly configure your terminal apps to use the shell you want.
Set default shell to bash
(setq shell-file-name (executable-find "bash"))
If you opt for option 1 and use one of Emacs’ terminal emulators, you will also need to configure them to use Fish, e.g.
(setq-default vterm-shell (executable-find “fish”))
(setq-default explicit-shell-file-name (executable-find “fish”))
Still use fish in other places
(setq-default vterm-shell (executable-find "fish")) (setq-default explicit-shell-file-name (executable-find "fish"))
3.5. Font configuration
The font configuration, very important to properly configure to have a good experience.
Font configuration of my 16 inch Macbook, usually hooked up to a 27 inch 2560x1440 monitor.
(setq doom-font (font-spec :family "Fira Code" :size 18) doom-big-font-increment 6 doom-variable-pitch-font (font-spec :family "Fira Code" :size 18))
3.6. Simple default settings
A few random default settings, most individual setting have been commented inline.
(setq-default delete-by-moving-to-trash t ; Delete files to trash window-combination-resize t ; Take new window space from all other windows (not just current) x-stretch-cursor t) ; Stretch cursor to the glyph width
Change a few variables.
(setq undo-limit 80000000 ; Raise undo-limit to 80Mb evil-want-fine-undo t ; By default while in insert all changes are one big blob. Be more granular truncate-string-ellipsis "…") ; Unicode ellispis are nicer than "...", and also save /precious/ space
Display battery percentage on laptops.
(unless (equal "Battery status not available" (battery)) (display-battery-mode 1)) ; On laptops it's nice to know how much power you have (global-subword-mode 1) ; Iterate through CamelCase words
Enable time in the mode-line.
(display-time-mode 1)
Easily escape after hitting the leader key using the ESC button. The :g
flag stands for global.
(map! :leader :desc "Escape globally" :g "<escape>" #'keyboard-escape-quit)
3.7. Enable auto revert mode
Prevent files from getting outdated by changes outside of Emacs. Also read the related docs.
Global Auto-Revert Mode is a global minor mode that reverts any buffer associated with a file when the file changes on disk. Enable it.
(setq global-auto-revert-mode 1)
Also revert Dired and other non file buffers.
(setq global-auto-revert-non-file-buffers t)
3.8. Disable git modes
Turn off treemacs git mode, I’ll notice what has changed in magit anyways.
(after! treemacs (setq treemacs-git-mode nil)) ; nil, simple, extended, deferred
3.9. Start fullscreen
Start Doom Emacs in full screen.
(add-to-list 'initial-frame-alist '(fullscreen . maximized))
3.10. Default browser
Set the default browser to open links to use Brave
(setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser")
Set the default browser to open links in Microsoft Edge
;; (setq browse-url-browser-function 'browse-url-generic ;; browse-url-generic-program "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge")
Set the default browser to open links to Google Chrome
;; (setq browse-url-browser-function 'browse-url-generic ;; browse-url-generic-program "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome")
3.11. File associations
Associate *.mdx
files with markdown mode
;; Associate .mdx files with markdown-mode (add-to-list 'auto-mode-alist '("\\.mdx\\'" . markdown-mode))
4. Improvements
This heading contains some improvements to the default Doom Emacs experience.
4.1. Dired improvements
A few extra dired keybindings (credits go to distrotubes config).
(map! :leader :desc "Dired" "d d" #'dired :leader :desc "Dired jump to current" "d j" #'dired-jump (:after dired (:map dired-mode-map :leader :desc "Peep-dired image previews" "d p" #'peep-dired :leader :desc "Dired view file" "d v" #'dired-view-file)))
Make ’h’ and ’l’ go back and forward in dired. Much faster to navigate the directory structure!
(evil-define-key 'normal dired-mode-map (kbd "h") 'dired-up-directory (kbd "l") 'dired-open-file) ; use dired-find-file instead if not using dired-open package
If peep-dired is enabled, you will get image previews as you go up/down with ’j’ and ’k’.
(evil-define-key 'normal peep-dired-mode-map (kbd "j") 'peep-dired-next-file (kbd "k") 'peep-dired-prev-file) (add-hook 'peep-dired-hook 'evil-normalize-keymaps)
Get file icons in dired.
(add-hook 'dired-mode-hook 'all-the-icons-dired-mode)
With dired-open plugin, you can launch external programs for certain extensions. For example, I set all .png files to open in ’sxiv’ and all .mp4 files to open in ’mpv’.
(setq dired-open-extensions '(("gif" . "sxiv") ("jpg" . "sxiv") ("png" . "sxiv") ("mkv" . "mpv") ("mp4" . "mpv")))
4.2. Projectile improvements
Improvements inspired from projectile docs.
Also add a Makefile as a project root indicator.
(after! projectile (add-to-list 'projectile-project-root-files "Makefile"))
4.3. Doom modeline adjustments
Don’t display icons for buffer states. It respects doom-modeline-icon
.
(setq doom-modeline-buffer-state-icon nil)
Don’t display buffer modification icon. It respects doom-modeline-icon
and doom-modeline-buffer-state-icon
.
(setq doom-modeline-buffer-modification-icon nil)
Customize a few theme variables to make sure red coloured unsaved buffers are not visible in the modeline, as I’m using super-save package anyways.
(custom-set-faces '(doom-modeline-buffer-modified ((t (:inherit (bold bold))))) '(doom-modeline-buffer-path ((t (:inherit (bold bold))))) '(doom-modeline-evil-normal-state ((t (:inherit bold)))) '(doom-modeline-evil-insert-state ((t (:inherit (bold bold))))) '(doom-modeline-project-dir ((t (:inherit (bold bold))))) '(doom-modeline-highlight ((t (:inherit mode-line-emphasis)))) '(doom-modeline-input-method ((t (:inherit (mode-line-emphasis bold))))) '(doom-modeline-project-root-dir ((t (:inherit (mode-line-emphasis bold))))))
4.4. Suppress messages in minibuffer
Suppress “Beginning of buffer” and “End of buffer” messages, as I find them useless.
(defadvice evil-previous-line (around silencer activate) (condition-case nil ad-do-it ((beginning-of-buffer)))) (defadvice evil-next-line (around silencer activate) (condition-case nil ad-do-it ((end-of-buffer))))
Suppress “Beginning of line” and “End of line” messages, as they’re also useless.
(defadvice evil-backward-char (around silencer activate) (condition-case nil ad-do-it ((beginning-of-line)))) (defadvice evil-forward-char (around silencer activate) (condition-case nil ad-do-it ((end-of-line))))
4.5. Magit auto save
Save all buffers before invoking any magit actions, as an alternative to broken magit-status
super save trigger (which doesn’t work anymore).
(after! magit (setq magit-save-repository-buffers 'dontask))
4.6. Scrolling
Scroll one line at a time (less “jumpy” than defaults), taken from Emacs docs.
(setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) ;; one line at a time (setq mouse-wheel-progressive-speed nil) ;; don't accelerate scrolling (setq mouse-wheel-follow-mouse 't) ;; scroll window under mouse (setq scroll-step 1) ;; keyboard scroll one line at a time
4.7. Open treemacs on startup
After starting Doom it’s the first thing I do, so why not do it automatically each time.
(add-hook 'window-setup-hook #'+treemacs/toggle)
4.8. Mac change option to control
To change the interpretation of Mac keys from within Emacs, you can use several variables, as described on this StackExchange post.
Change right command to control in text-mode
(during multiple modes).
(add-hook 'text-mode-hook (lambda () (when (eq system-type 'darwin) (setq-local mac-right-command-modifier 'control)))) (add-hook 'magit-log-select-mode-hook (lambda () (when (eq system-type 'darwin) (setq-local mac-right-command-modifier 'control)))) (add-hook 'dired-mode-hook (lambda () (when (eq system-type 'darwin) (setq-local mac-right-command-modifier 'control)))) (add-hook 'git-rebase-mode-hook (lambda () (when (eq system-type 'darwin) (setq-local mac-right-command-modifier 'control))))
Bring back the the command modifier to left
as some modes behave like an exception (somehow).
(add-hook 'gfm-mode-hook (lambda () (when (eq system-type 'darwin) (setq-local mac-right-command-modifier 'left)))) (add-hook 'yaml-mode-hook (lambda () (when (eq system-type 'darwin) (setq-local mac-right-command-modifier 'left))))
4.9. Display ANSI color codes
Inspired from this SO post.
(use-package! ansi-color :defer t ;; loads the package when needed :config (defun display-ansi-colors () (interactive) (ansi-color-apply-on-region (point-min) (point-max))))
4.10. Open currently open file in VSCode
Helper function to open currently open file in VSCode (currently changed to VSCode AI editor fork called ’Cursor’).
(defun open-current-file-in-vscode () "Open the current buffer's file in Visual Studio Code." (interactive) (let ((file-path (buffer-file-name))) (if file-path (call-process "cursor" nil 0 nil file-path) (error "Current buffer is not visiting a file."))))
Keybinding to open currently open file in VSCode.
(map! :leader :desc "Open in VSCode" "ov" #'open-current-file-in-vscode)
4.11. Open treemacs after opening project
Automatically open treemacs after opening new project.
(add-hook 'projectile-after-switch-project-hook #'+treemacs/toggle)
5. Org mode
This heading contains settings related to improving the org mode experience.
5.1. Default org folder
If you use org and don’t want your org files in the default location below, change ’org-directory’. It must be set before org loads!
(setq org-directory notebook-directory)
5.2. Create doc skeleton
Let’s define a skeleton with a title
, author
, description
and tags
ready to pop-out where we need it to at the beginning of a new org file.
(define-skeleton generate-new-header-org "Prompt for title, description and tags" nil '(setq title (skeleton-read "Title: ")) '(setq description (skeleton-read "Description: ")) '(setq tags (skeleton-read "tags: ")) "#+TITLE: " title \n "#+AUTHOR: Hyper Focus" \n "#+DESCRIPTION: " description \n "#+TAGS: " tags \n )
5.3. Configure agenda
Setup org agenda folder with multiple org.
(after! org (setq org-agenda-files '(notes-directory notebook-directory)))
Configure custom agenda views, inspired from Emacs From Scratch #6.
(after! org (setq org-agenda-custom-commands '(("d" "Dashboard" ((agenda "" ((org-deadline-warning-days 7))) (todo "NEXT" ((org-agenda-overriding-header "Next Tasks"))) (tags-todo "agenda/ACTIVE" ((org-agenda-overriding-header "Active Projects"))))) ("n" "Next Tasks" ((todo "NEXT" ((org-agenda-overriding-header "Next Tasks"))))) ("W" "Work Tasks" tags-todo "+work") ;; Low-effort next actions ("e" tags-todo "+TODO=\"NEXT\"+Effort<15&+Effort>0" ((org-agenda-overriding-header "Low Effort Tasks") (org-agenda-max-todos 20) (org-agenda-files org-agenda-files))) ("w" "Workflow Status" ((todo "WAIT" ((org-agenda-overriding-header "Waiting on External") (org-agenda-files org-agenda-files))) (todo "REVIEW" ((org-agenda-overriding-header "In Review") (org-agenda-files org-agenda-files))) (todo "PLAN" ((org-agenda-overriding-header "In Planning") (org-agenda-todo-list-sublevels nil) (org-agenda-files org-agenda-files))) (todo "BACKLOG" ((org-agenda-overriding-header "Project Backlog") (org-agenda-todo-list-sublevels nil) (org-agenda-files org-agenda-files))) (todo "READY" ((org-agenda-overriding-header "Ready for Work") (org-agenda-files org-agenda-files))) (todo "ACTIVE" ((org-agenda-overriding-header "Active Projects") (org-agenda-files org-agenda-files))) (todo "COMPLETED" ((org-agenda-overriding-header "Completed Projects") (org-agenda-files org-agenda-files))) (todo "CANC" ((org-agenda-overriding-header "Cancelled Projects") (org-agenda-files org-agenda-files))))))))
5.4. Org variables
A few random variables to improve the org experience.
Add timestamp when task moves to DONE state.
(setq org-log-done 'time)
Fold org log entries into drawer.
(setq org-log-into-drawer t)
5.5. Org to do keywords
Change the to do keywords to something more useful. Also search for the variable in modules/lang/org/config.el
to see the way doom sets it up by default. Anything before the | character are active states, and anything after | are completed states.
(after! org (setq org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!)") (sequence "BACKLOG(b)" "PLAN(p)" "READY(r)" "ACTIVE(a)" "REVIEW(v)" "WAIT(w@/!)" "HOLD(h)" "|" "COMPLETED(c)" "CANC(k@)"))))
5.6. Capture templates
Custom capture template, overwriting the default Doom Emacs workflow as defined in modules/lang/org/config.el.
(after! org (setq org-capture-templates '(("t" "Tasks / Projects") ("tt" "Task" entry (file+olp (concat my-notes-directory "/TODO.org") "Inbox") "* TODO %?\n %U\n %a\n %i" :empty-lines 1))))
5.7. Prettier headings
Prettier org icons.
Nicer looking ellipsis when collapsing a heading.
(after! org (setq org-ellipsis " ▾"))
A few nicer looking org bullet points.
(use-package! org-bullets :after org :hook (org-mode . org-bullets-mode) :custom (org-bullets-bullet-list '("◉" "○" "●" "○" "●" "○" "●")))
5.8. Org pandoc import
Enable org-pandoc-import package.
(use-package! org-pandoc-import :after org)
5.9. Org tree slide
Initialize the usage of org-tree-slide.
(use-package! org-tree-slide :hook ((org-tree-slide-play . efs/presentation-setup) (org-tree-slide-stop . efs/presentation-end)) :commands org-tree-slide-mode :config (setq org-image-actual-width nil) (setq org-tree-slide-header nil) (when (modulep! :editor evil) (map! :map org-tree-slide-mode-map :n [C-right] #'org-tree-slide-move-next-tree :n [C-left] #'org-tree-slide-move-previous-tree) (add-hook 'org-tree-slide-mode-hook #'evil-normalize-keymaps)))
Let’s add the hook code when org-tree-slide-mode
starts
(defun efs/presentation-setup () ;; Hide the mode line (hide-mode-line-mode 1) ;; Enable the simple profile (org-tree-slide-simple-profile) ;; Display images inline (org-display-inline-images) ;; Can also use org-startup-with-inline-images ;; Scale the text. The next line is for basic scaling: (setq text-scale-mode-amount 2.5) (text-scale-mode 1)) ;; This option is more advanced, allows you to scale other faces too ;; (setq-local face-remapping-alist '((default (:height 2.0) variable-pitch) ;; (org-verbatim (:height 1.75) org-verbatim) ;; (org-block (:height 1.25) org-block))))
Let’s add the hook code when org-tree-slide-mode
stops
(defun efs/presentation-end () ;; Show the mode line again (hide-mode-line-mode 0) ;; Turn off text scale mode (or use the next line if you didn't use text-scale-mode) (text-scale-mode 0)) ;; If you use face-remapping-alist, this clears the scaling: ;; (setq-local face-remapping-alist '((default variable-pitch default))))
6. Keybindings
This heading contains configuration to create some extra keybindings for convenience.
6.1. Workspace switcher
This bit of code allows me to keep switching between workspaces, even though I’m in the treemacs buffer.
(define-key! evil-treemacs-state-map "] w" #'+workspace/switch-right "[ w" #'+workspace/switch-left)
6.2. Arrow window navigation
Use the arrows to move around. I actually mostly use leader + hjkl to move between windows, but I figured why not just keep this config, in case I use it from time to time.
(after! evil (map! :map evil-window-map (:leader (:prefix ("w" . "Select Window") :n :desc "Left" "<left>" 'evil-window-left :n :desc "Up" "<up>" 'evil-window-up :n :desc "Down" "<down>" 'evil-window-down :n :desc "Right" "<right>" 'evil-window-right )) ))
6.3. Chezmoi
Add Chezmoi keybindings.
(map! :leader (:prefix-map ("o c" . "Chezmoi") :desc "Chezmoi sync files" "s" #'chezmoi-sync-files :desc "Chezmoi diff all" "d" #'chezmoi-diff :desc "Chezmoi find source file" "f" #'chezmoi-find :desc "Chezmoi open buffer target file" "o" #'chezmoi-open-other))
6.4. Registers
A few shortcuts to register functions for easier access (credits go to distrotubes config.org).
(map! :leader :desc "Copy to register" "r c" #'copy-to-register :leader :desc "Frameset to register" "r f" #'frameset-to-register :leader :desc "Insert contents of register" "r i" #'insert-register :leader :desc "Jump to register" "r j" #'jump-to-register :leader :desc "List registers" "r l" #'list-registers :leader :desc "Number to register" "r n" #'number-to-register :leader :desc "Interactively choose a register" "r r" #'counsel-register :leader :desc "View a register" "r v" #'view-register :leader :desc "Window configuration to register" "r w" #'window-configuration-to-register :leader :desc "Increment register" "r +" #'increment-register :leader :desc "Point to register" "r SPC" #'point-to-register)
6.5. Bookmarks
Keybinding to list all bookmarks (spc b h).
(map! :leader :desc "Bookmark list" "bh" #'list-bookmarks)
6.6. Evaluate elisp
Better keybindings for evaluating elisp functions (inspired from distrotube).
(map! :leader :desc "Evaluate elisp in buffer" "e b" #'eval-buffer :leader :desc "Evaluate defun" "e d" #'eval-defun :leader :desc "Evaluate elisp expression" "e e" #'eval-expression :leader :desc "Evaluate last sexpression" "e l" #'eval-last-sexp :leader :desc "Evaluate elisp in region" "e r" #'eval-region)
6.7. Navigate between buffers
Navigate between buffers using ⌃ (⇧) tab
(map! :nvi "C-<tab>" #'next-buffer) (map! :nvi "C-S-<iso-lefttab>" #'previous-buffer)
Navigate between buffers using ⇧ ← / →
(map! :nvi "S-<right>" #'next-buffer) (map! :nvi "S-<left>" #'previous-buffer)
Navigate between buffers using ⌘ ⇧ [ / ]
(map! :nvi "s-}" #'next-buffer) (map! :nvi "s-{" #'previous-buffer)
Navigate between buffers using ⌥ ⌘ ← / →
(map! :nvi "M-s-<right>" #'next-buffer) (map! :nvi "M-s-<left>" #'previous-buffer)
6.8. Navigate within file
Go up and down within a file using ⌘ ↑ / ↓
(map! :nvi "s-<up>" #'evil-goto-first-line) (map! :nvi "s-<down>" #'evil-goto-line)
6.9. Swap workspace left and right
Swap current workspace to left and right.
(map! :nvi "s-<" #'+workspace/swap-left) (map! :nvi "s->" #'+workspace/swap-right)
6.10. Focus on treemacs
Focus cursor on treemacs.
(map! :nvi "s-e" #'treemacs-select-window)
6.11. Fix jump between treemacs and back
Override default evil-window-next
capability.
(map! :leader :desc "Fix select treemacs window" "w w" #'treemacs-select-window)
7. Utilities
This heading contains configuration of Emacs utilities that improve the experience.
7.1. Super save
Super-save is a super useful package that automatically saves buffers whenever any state events happen.
Enable super save mode.
(use-package! super-save :ensure t :config (super-save-mode +1))
Save all open buffers (useful in the case of making simultaneous edits with grep
).
(setq super-save-all-buffers t)
Add many super save triggers, so the buffer saves during any action when you’ve stopped editing the buffer.
(add-to-list 'super-save-triggers 'evil-window-next) (add-to-list 'super-save-triggers 'evil-window-prev) (add-to-list 'super-save-triggers 'next-buffer) (add-to-list 'super-save-triggers 'previous-buffer) (add-to-list 'super-save-triggers 'switch-to-buffer) (add-to-list 'super-save-triggers 'other-window ) (add-to-list 'super-save-triggers 'treemacs-select-window) (add-to-list 'super-save-triggers 'windmove-up) (add-to-list 'super-save-triggers 'windmove-down) (add-to-list 'super-save-triggers 'windmove-left) (add-to-list 'super-save-triggers 'windmove-right) (add-to-list 'super-save-triggers '+workspace/switch-left) (add-to-list 'super-save-triggers '+workspace/switch-right) (add-to-list 'super-save-triggers '+workspace/switch-to-final) (add-to-list 'super-save-triggers '+workspace/switch-to) (add-to-list 'super-save-triggers '+ivy/projectile-find-file)
Suppress messages in the Messages buffer and echo area.
(setq super-save-silent t)
Enable deleting trailing white spaces before saving (except for the current line).
(setq super-save-delete-trailing-whitespace 'except-current-line)
7.2. Magit forge
Magit forge allows you to manage git issues and other project related settings from within Magit.
Enable magit forge package.
(use-package! forge)
Changed the default auth-sources variable to only include .authinfo
as source, to fix an issue.
(setq auth-sources '("~/.authinfo"))
Show 100 open topics and never show any closed topics, for both issues and pull requests.
(setq forge-topic-list-limit '(100 . 0))
7.3. Web mode
Web mode is an emacs major mode for editing web templates.
Enable JSX syntax highlighting in .js/.jsx files.
(setq web-mode-content-types-alist '(("jsx" . "\\.js[x]?\\'")))
7.4. Denote
Adding notes with denote.
(use-package! denote :custom (denote-directory (expand-file-name notes-directory)) (denote-infer-keywords nil) (denote-history-completion-in-prompts nil) (denote-file-type 'markdown-yaml) ; ('markdown-yaml' or 'org') (denote-save-buffers t) :hook (dired-mode . denote-dired-mode))
Configure consult-denote package.
(use-package! consult-denote :after (denote consult) :ensure t :config ;; (setq consult-denote-grep-command "consult-grep") ;; it can't find "consult-ripgrep" for some reason (consult-denote-mode 1))
Configure denote keybindings.
(map! :leader (:prefix-map ("n d" . "Denote") :desc "Denote create file" "c" #'denote :desc "Denote drawer" "d" #'denote-open-or-create :desc "Denote find" "f" #'consult-denote-find :desc "Denote link" "l" #'denote-link :desc "Denote rename file" "R" #'denote-rename-file ;; :desc "Denote grep" "g" #'consult-denote-grep ; does not yet work :desc "Denote show backlink" "b" #'denote-backlinks :desc "Denote insert dblock" "i b" #'denote-org-dblock-insert-links))
Additional denote keybindings.
(map! :leader (:prefix-map ("o n" . "notes") :desc "Denote drawer" "" #'denote-open-or-create))
7.5. Consult notes
Configure consult-notes package.
(use-package! consult-notes :commands (consult-notes consult-notes-search-in-all-notes) :config (setq consult-notes-file-dir-sources '(("Notes" ?n notes-directory))) ;; ?n is a narrowing key character (when (locate-library "denote") (consult-notes-denote-mode)) (setq consult-notes-denote-files-function (function denote-directory-files)))
7.6. Obsidian
Add function to open markdown files in obsidian app.
(map! :map doom-leader-map "n r o" (λ! (let* ((full-path (buffer-file-name)) (pattern "/notes/\\(.*?\\)\\.md$") (vault-name "notebook") obsidian-uri match) (when (and full-path (string-match pattern full-path)) (setq match (match-string 1 full-path)) (setq obsidian-uri (format "obsidian://open?vault=%s&file=%s" vault-name match)) (start-process "open-obsidian" nil "open" obsidian-uri)))))
7.7. Ebooks
Use Calibre from within Emacs with CalibreDB. Took inspiration from Tecosaurs config.
Enable package and some keybindings.
(use-package! calibredb :commands calibredb :config (setq calibredb-root-dir "~/Dropbox/Ebooks" calibredb-db-dir (expand-file-name "metadata.db" calibredb-root-dir)) (map! :map calibredb-show-mode-map :ne "?" #'calibredb-entry-dispatch :ne "o" #'calibredb-find-file :ne "O" #'calibredb-find-file-other-frame :ne "V" #'calibredb-open-file-with-default-tool :ne "s" #'calibredb-set-metadata-dispatch :ne "e" #'calibredb-export-dispatch :ne "q" #'calibredb-entry-quit :ne "." #'calibredb-open-dired :ne [tab] #'calibredb-toggle-view-at-point :ne "M-t" #'calibredb-set-metadata--tags :ne "M-a" #'calibredb-set-metadata--author_sort :ne "M-A" #'calibredb-set-metadata--authors :ne "M-T" #'calibredb-set-metadata--title :ne "M-c" #'calibredb-set-metadata--comments) (map! :map calibredb-search-mode-map :ne [mouse-3] #'calibredb-search-mouse :ne "RET" #'calibredb-find-file :ne "?" #'calibredb-dispatch :ne "a" #'calibredb-add :ne "A" #'calibredb-add-dir :ne "c" #'calibredb-clone :ne "d" #'calibredb-remove :ne "D" #'calibredb-remove-marked-items :ne "j" #'calibredb-next-entry :ne "k" #'calibredb-previous-entry :ne "l" #'calibredb-virtual-library-list :ne "L" #'calibredb-library-list :ne "n" #'calibredb-virtual-library-next :ne "N" #'calibredb-library-next :ne "p" #'calibredb-virtual-library-previous :ne "P" #'calibredb-library-previous :ne "s" #'calibredb-set-metadata-dispatch :ne "S" #'calibredb-switch-library :ne "o" #'calibredb-find-file :ne "O" #'calibredb-find-file-other-frame :ne "v" #'calibredb-view :ne "V" #'calibredb-open-file-with-default-tool :ne "." #'calibredb-open-dired :ne "b" #'calibredb-catalog-bib-dispatch :ne "e" #'calibredb-export-dispatch :ne "r" #'calibredb-search-refresh-and-clear-filter :ne "R" #'calibredb-search-clear-filter :ne "q" #'calibredb-search-quit :ne "m" #'calibredb-mark-and-forward :ne "f" #'calibredb-toggle-favorite-at-point :ne "x" #'calibredb-toggle-archive-at-point :ne "h" #'calibredb-toggle-highlight-at-point :ne "u" #'calibredb-unmark-and-forward :ne "i" #'calibredb-edit-annotation :ne "DEL" #'calibredb-unmark-and-backward :ne [backtab] #'calibredb-toggle-view :ne [tab] #'calibredb-toggle-view-at-point :ne "M-n" #'calibredb-show-next-entry :ne "M-p" #'calibredb-show-previous-entry :ne "/" #'calibredb-search-live-filter :ne "M-t" #'calibredb-set-metadata--tags :ne "M-a" #'calibredb-set-metadata--author_sort :ne "M-A" #'calibredb-set-metadata--authors :ne "M-T" #'calibredb-set-metadata--title :ne "M-c" #'calibredb-set-metadata--comments))
Use nov to read the epub files.
(use-package! nov :mode ("\\.epub\\'" . nov-mode) :config (map! :map nov-mode-map :n "RET" #'nov-scroll-up) (defun doom-modeline-segment--nov-info () (concat " " (propertize (cdr (assoc 'creator nov-metadata)) 'face 'doom-modeline-project-parent-dir) " " (cdr (assoc 'title nov-metadata)) " " (propertize (format "%d/%d" (1+ nov-documents-index) (length nov-documents)) 'face 'doom-modeline-info))) (advice-add 'nov-render-title :override #'ignore) (defun +nov-mode-setup () (face-remap-add-relative 'variable-pitch :family "Merriweather" :height 1.4 :width 'semi-expanded) (face-remap-add-relative 'default :height 1.3) (setq-local line-spacing 0.2 next-screen-context-lines 4 shr-use-colors nil) (require 'visual-fill-column nil t) (setq-local visual-fill-column-center-text t visual-fill-column-width 80 nov-text-width 100) (visual-fill-column-mode 1) (hl-line-mode -1) (add-to-list '+lookup-definition-functions #'+lookup/dictionary-definition) (setq-local mode-line-format `((:eval (doom-modeline-segment--workspace-name)) (:eval (doom-modeline-segment--window-number)) (:eval (doom-modeline-segment--nov-info)) ,(propertize " %P " 'face 'doom-modeline-buffer-minor-mode) ,(propertize " " 'face (if (doom-modeline--active) 'mode-line 'mode-line-inactive) 'display `((space :align-to (- (+ right right-fringe right-margin) ,(* (let ((width (doom-modeline--font-width))) (or (and (= width 1) 1) (/ width (frame-char-width) 1.0))) (string-width (format-mode-line (cons "" '(:eval (doom-modeline-segment--major-mode)))))))))) (:eval (doom-modeline-segment--major-mode))))) (add-hook 'nov-mode-hook #'+nov-mode-setup))
7.8. Terraform LSP mode
Enable terraform-ls language server.
(after! lsp-mode (lsp-register-client (make-lsp-client :new-connection (lsp-stdio-connection '("/opt/homebrew/bin/terraform-ls" "serve")) :major-modes '(terraform-mode) :server-id 'terraform-ls)) (add-hook 'terraform-mode-hook #'lsp))
Only show lsp-ui-doc popup with mouse
(setq lsp-ui-doc-enable t) (setq lsp-ui-doc-show-with-cursor nil) (setq lsp-ui-doc-show-with-mouse t)
Turn off the echo area documentation.
(setq lsp-eldoc-enable-hover nil)
Disable sideline diagnostics.
(setq lsp-ui-sideline-enable nil)
8. Troubleshooting
8.1. Tramp verbosity
Set Tramp verbosity
(setq tramp-verbose 6)
8.2. Org mode bug
Turn off cache to fix the following bug.
Warning (emacs): org-element–cache: Unregistered buffer modifications detected. Resetting. If this warning appears regularly, please report it to Org mode mailing list (M-x org-submit-bug-report). The buffer is: course.org Current command: nil Backtrace: “ backtrace-to-string(nil) org-element–cache-sync(#<buffer course.org>) apply(org-element–cache-sync #<buffer course.org>) timer-event-handler([t 0 0 599999 nil org-element–cache-sync (#<buffer course.org>) idle 999999]) ”
Turn back to t
to see whether it’s fixed by now.
(setq org-element-use-cache t)