Skip to content

Latest commit

 

History

History
1763 lines (1566 loc) · 83.5 KB

config.org

File metadata and controls

1763 lines (1566 loc) · 83.5 KB

Doom Emacs Config

Forword

This org document is used as documentation, explanations and config files for my Doom Emacs setup. I recommend using this file to configure your Doom Emacs too, if you decide to build upon this configuration. Using Emacs’s Org-Mode is adviced but if you don’t want to do so, you can export the code blocks with ntangle. Maybe I will add a user script to do so in the future but this will have to do for now.

I use Arch on an M1 mac btw 😉 so you should have a good look at the required packages and maybe substitute some of them for there better counterpart, but as far as I’m convinced all of the packages that are being used, none of them isn’t capable of running on x86_64 architecture.

I also want to mention that this repo was build on Derek Taylor dotfiles and customized to fit my needs but you shout check out the original, especially if you have any problems getting my config to work.

Table Of Content

Installation

As mentioned in Forword the packages for this repo where chosen for ARM64 so in some cases these are worse alternative’s then there x86_64 counterpart. I recommend using all the dotfiles together but it is possible to just use Doom Emacs with some additional personal changes.

Curl-Skript

curl https://raw.githubusercontent.com/Moerliy/dotfiles/main/.config/doom/install-wizard.sh | bash

1.Clone

If you don’t have existing dotfiles you can clone my hole repository (for that you should have a look at my README in my dotfiles directory) or just Doom Emacs:

git clone --no-checkout https://github.com/Moerliy/dotfiles.git
cd dotfiles
git sparse-checkout init --cone
git sparse-checkout set .config/doom
git checkout origin/master
cp -r .config/doom ~/.config/doom

2.Packages

This download all the imports down below:

#!/bin/bash
yay -Syu --noconfirm --needed emacs-nativecomp hunspell hunspell-en_us libvterm languagetool nodejs npm pnpm vue yarn lldb gdb unzip docker docker-compose docker-machine editorconfig-checker sqlite ripgrep git wl-clipboard clang ccls go gopls jdk11-openjdk texlive-most gnuplot marked python pyright rubocop rustup mpd mpc maim scrot gnome-screenshot rust-analyzer tidy stylelint python-pipenv curl gcc make ncurses man-pages xdg-utils dockerfile-language-server wordnet-cli cmake-language-server proselint ktlint shellcheck-bin js-beautify ttf-jetbrains-mono python-grip-git python-pytest python-nose python-black python-pyflakes python-isort

# pip installs aren't working anymore
#pip install python-language-server

# rustup component
rustup default stable
rustup component add clippy-preview rustfmt-preview

# cargo installs
cargo install cargo-check

# gomistalls
go install github.com/x-motemen/gore/cmd/gore@latest
go install golang.org/x/tools/gopls@latest
go install github.com/stamblerre/gocode@latest
go install golang.org/x/tools/cmd/godoc@latest
go install golang.org/x/tools/cmd/goimports@latest
go install golang.org/x/tools/cmd/gorename@latest
go install golang.org/x/tools/cmd/guru@latest
go install github.com/cweill/gotests/gotests@latest
go install github.com/fatih/gomodifytags@latest

sudo npm install -g vue-tsc

# ghcup installs
#if ! command -v ghcup &> $HOME/.ghcup/bin/ghcup; then
#    curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
#fi
#ghcup install ghc latest
#ghcup install cabal latest
#ghcup install hls latest

Packman Installs

  • libvterm terminal emulator library
  • languagetool Open Source proofreading software
  • hunspell
  • hunspell-en_us
  • nodejs JavaScript runtime environment
  • npm JavaScript package manager
  • pnpm JavaScript package manager
  • yarn JavaScript package manager
  • lldb debugger
  • gdb GNU debugger
  • unzip extracting and viewing files in .zip archives
  • docker lightweight container
  • docker-compose development environments using Docker
  • docker-machine Machine management for a container-centric world
  • editorconfig-checker A tool to verify that your files are in harmony with your .editorconfig
  • sqlite A C library that implements an SQL database engine
  • ripgreb searches the current directory for a regex pattern
  • git version control system
  • wl-clipboard clipboard utilities
  • clang compiler front-end for the C family of languages
  • ccls C/C++/Objective-C language server
  • go open source programming language
  • gopls Go language server
  • jdk11-openjdk OpenJDK Java 11 development kit
  • texlive-core TeX Live core distribution
  • texlive-bin TeX Live binaries (dependency of texlive-core)
  • texlive-science TeX Live - Typesetting for mathematics, natural and computer sciences
  • texlive-latexextra TeX Live - Large collection of add-on packages for LaTeX
  • gnuplot Plotting Utility
  • marked markdown parser
  • pip package installer for Python
  • pyright Static Type Checker for Python
  • rubocop Ruby static code analyzer
  • rustup Rust toolchain installer
  • mpd Music Player Daemon
  • mpc Minimalist command line interface to MPD
  • maim utility that takes screenshots
  • scrot screen capture utility (only X11)
  • gnome-screenshot Screenshot utility
  • rust-analyzer modular compiler frontend for the Rust language
  • tidy tidy down HTML code
  • stylelint CSS linter
  • python-pipenv Sacred Marriage of Pipfile, Pip, & Virtualenv
  • curl transferring data specified with URL syntax
  • gcc GNU Compiler Collection - C and C++ frontends
  • make GNU make utility to maintain groups of programs
  • ncurses System V Release 4.0 curses emulation library
  • man-pages Linux man pages
  • xdg-utils Command line tools that assist applications with a variety of desktop integration tasks

Yay Installs

Pip Installs

  • pytest write small tests
  • nose loading and running features of unittest
  • black Python code formatter
  • pyflakes checks Python source files for errors
  • isort isort is a Python utility / library to sort imports alphabetically
  • python-language-server Python LSP
  • grip render a local readme file

Ghcup Installs (requires ghcup)

  • ghc Haskell Compiler
  • cabal building and packaging Haskell libraries and programs
  • hls Haskell language server

Rustup Installs

Cargo Installs

Go Installs

  • gore Go REPL
  • gopls Go language server
  • godoc directory contains most of the code for running a godoc server
  • goimports Go import lines, adding missing ones and removing unreferenced ones
  • gorename gorename command performs precise type-safe renaming of identifiers in Go source code
  • guru answering questions about Go source code
  • gotests Go tests
  • gomodifytags Go tool to modify/update field tags

npm Installs

  • vue-tsc

Beacon

Never lose your cursor. When you scroll, your cursor will shine. This is a global minor-mode. Turn it on everywhere with:

(beacon-mode 1)

Bookmarks and buffers

Doom Emacs uses SPC b for keybindings related to bookmarks and buffers.

Bookmarks

Is somewhat like registers in that they record positions you can jump to. Unlike registers, they have long names, and they persist automatically from one Emacs session to the next. The prototypical use of bookmarks is to record where you were reading in various files.

(map! :leader
      (:prefix ("b". "buffer")
       :desc "List bookmarks" "L" #'list-bookmarks
       :desc "Save current bookmarks to bookmark file" "w" #'bookmark-save))

Buffers

Regarding buffers, the text you are editing in Emacs resides in an object called a buffer. Each time you visit a file, a buffer is used to hold the file’s text. Each time you invoke Dired, a buffer is used to hold the directory listing. Ibuffer is a program that lists all of your Emacs buffers, allowing you to navigate between them and filter them.

COMMANDDESCRIPTIONKEYBINDING
ibufferLaunch ibufferSPC b i
kill-bufferKill current bufferSPC b k
next-bufferGoto next bufferSPC b n
previous-bufferGoto previous bufferSPC b p
save-bufferSave current bufferSPC b s

Global Auto Revert

A buffer can get out of sync with respect to its visited file on disk if that file is changed by another program. To keep it up to date, you can enable Auto Revert mode by typing M-x auto-revert-mode, or you can set it to be turned on globally with ‘global-auto-revert-mode’. I have also turned on Global Auto Revert on non-file buffers, which is especially useful for ‘dired’ buffers.

(global-auto-revert-mode 1)
(setq global-auto-revert-non-file-buffers t)

Keybindings within ibuffer mode

COMMANDDESCRIPTIONKEYBINDING
ibuffer-mark-forwardMark the bufferm
ibuffer-unmark-forwardUnmark the bufferu
ibuffer-do-kill-on-deletion-marksKill the marked buffersx
ibuffer-filter-by-contentIbuffer filter by contentf c
ibuffer-filter-by-directoryIbuffer filter by directoryf d
ibuffer-filter-by-filenameIbuffer filter by filename (full path)f f
ibuffer-filter-by-modeIbuffer filter by modef m
ibuffer-filter-by-nameIbuffer filter by namef n
ibuffer-filter-disableDisable ibuffer filterf x
ibuffer-do-kill-linesHide marked buffersg h
ibuffer-updateRestore hidden buffersg H
(evil-define-key 'normal ibuffer-mode-map
  (kbd "f c") 'ibuffer-filter-by-content
  (kbd "f d") 'ibuffer-filter-by-directory
  (kbd "f f") 'ibuffer-filter-by-filename
  (kbd "f m") 'ibuffer-filter-by-mode
  (kbd "f n") 'ibuffer-filter-by-name
  (kbd "f x") 'ibuffer-filter-disable
  (kbd "g h") 'ibuffer-do-kill-lines
  (kbd "g H") 'ibuffer-update)

Calendar

Let’s make a 12-month calendar available so we can have a calendar app that, when we click on time/date in xmobar, we get a nice 12-month calendar to view.

;; https://stackoverflow.com/questions/9547912/emacs-calendar-show-more-than-3-months
(defun dt/year-calendar (&optional year)
  (interactive)
  (require 'calendar)
  (let* (
      (current-year (number-to-string (nth 5 (decode-time (current-time)))))
      (month 0)
      (year (if year year (string-to-number (format-time-string "%Y" (current-time))))))
    (switch-to-buffer (get-buffer-create calendar-buffer))
    (when (not (eq major-mode 'calendar-mode))
      (calendar-mode))
    (setq displayed-month month)
    (setq displayed-year year)
    (setq buffer-read-only nil)
    (erase-buffer)
    ;; horizontal rows
    (dotimes (j 4)
      ;; vertical columns
      (dotimes (i 3)
        (calendar-generate-month
          (setq month (+ month 1))
          year
          ;; indentation / spacing between months
          (+ 5 (* 25 i))))
      (goto-char (point-max))
      (insert (make-string (- 10 (count-lines (point-min) (point-max))) ?\n))
      (widen)
      (goto-char (point-max))
      (narrow-to-region (point-max) (point-max)))
    (widen)
    (goto-char (point-min))
    (setq buffer-read-only t)))

(defun dt/scroll-year-calendar-forward (&optional arg event)
  "Scroll the yearly calendar by year in a forward direction."
  (interactive (list (prefix-numeric-value current-prefix-arg)
                     last-nonmenu-event))
  (unless arg (setq arg 0))
  (save-selected-window
    (if (setq event (event-start event)) (select-window (posn-window event)))
    (unless (zerop arg)
      (let* (
              (year (+ displayed-year arg)))
        (dt/year-calendar year)))
    (goto-char (point-min))
    (run-hooks 'calendar-move-hook)))

(defun dt/scroll-year-calendar-backward (&optional arg event)
  "Scroll the yearly calendar by year in a backward direction."
  (interactive (list (prefix-numeric-value current-prefix-arg)
                     last-nonmenu-event))
  (dt/scroll-year-calendar-forward (- (or arg 1)) event))

(map! :leader
      :desc "Scroll year calendar backward" "<left>" #'dt/scroll-year-calendar-backward
      :desc "Scroll year calendar forward" "<right>" #'dt/scroll-year-calendar-forward)

(defalias 'year-calendar 'dt/year-calendar)

Let’s also play around with calfw.

(use-package! calfw)
(use-package! calfw-org)

Centaur-tabs

To use tabs in Doom Emacs, be sure to uncomment “tabs” in Doom’s init.el. Displays tabs at the top of the window similar to tabbed web browsers such as Firefox. I don’t actually use tabs in Emacs. I placed this in my config to help others who may want tabs. In the default configuration of Doom Emacs, SPC t is used for “toggle” keybindings, so I choose SPC t c to toggle centaur-tabs. The g prefix for keybindings is used for a bunch of evil keybindings in Doom, but g plus the arrow keys were not used, so I thought I would bind those for tab navigation. I did leave the default g t and g T intact tho if you prefer to use those for centaur-tabs-forward/backward.

COMMANDDESCRIPTIONKEYBINDING
centaur-tabs-modeToggle tabs globallySPC t c
centaur-tabs-local-modeToggle tabs local displaySPC t C
centaur-tabs-forwardNext tabg <right> or g t
centaur-tabs-backwardPrevious tabg <left> or g T
centaur-tabs-forward-groupNext tab groupg <down>
centaur-tabs-backward-groupPrevious tab groupg <up>
(setq centaur-tabs-set-bar 'over
      centaur-tabs-set-icons t
      centaur-tabs-gray-out-icons 'buffer
      centaur-tabs-height 24
      centaur-tabs-set-modified-marker t
      centaur-tabs-style "bar"
      centaur-tabs-modified-marker "")
(map! :leader
      :desc "Toggle tabs globally" "t c" #'centaur-tabs-mode
      :desc "Toggle tabs local display" "t C" #'centaur-tabs-local-mode)
(evil-define-key 'normal centaur-tabs-mode-map (kbd "g <right>") 'centaur-tabs-forward        ; default Doom binding is 'g t'
                                               (kbd "g <left>")  'centaur-tabs-backward       ; default Doom binding is 'g T'
                                               (kbd "g <down>")  'centaur-tabs-forward-group
                                               (kbd "g <up>")    'centaur-tabs-backward-group)

Clippy

Gives us a popup box with “Clippy”, the paper clip”. You can make him say various things by calling ‘clippy-say’ function. The more useful functions of clippy are the two describe functions provided: clippy-describe-function and clippy-describe-variable. Hit the appropriate keybinding while the point is over a function/variable to call it. A popup with helpful clippy will appear, telling you about the function/variable (using describe-function and describe-variable respectively).

COMMANDDESCRIPTIONKEYBINDING
clippy-describe-functionClippy describes function under pointSPC c h f
clippy-describe-variableClippy describes variable under pointSPC c h v
(map! :leader
      (:prefix ("c h" . "Help info from Clippy")
       :desc "Clippy describes function under point" "f" #'clippy-describe-function
       :desc "Clippy describes variable under point" "v" #'clippy-describe-variable))

Dired

Is the file manager within Emacs. Below, I setup keybindings for image previews peep-dired. Doom Emacs does not use SPC d for any of its keybindings, so I’ve chosen the format of SPC d plus 'key'.

Keybindings To Open Dired

COMMANDDESCRIPTIONKEYBINDING
diredOpen dired file managerSPC d d
dired-jumpJump to current directory in diredSPC d j

Keybindings Within Dired

Basic Dired Commands

COMMANDDESCRIPTIONKEYBINDING
dired-view-fileView file in diredSPC d v
dired-up-directoryGo up in directory treeh
dired-find-fileGo down in directory tree (or open if file)l
dired-next-lineMove down to next linej
dired-previous-lineMove up to previous linek
dired-markMark file at pointm
dired-unmarkUnmark file at pointu
dired-do-copyCopy current file or marked filesC
dired-do-renameRename current file or marked filesR
dired-hide-detailsToggle detailed listings on/off(
dired-git-info-modeToggle git information on/off)
dired-create-directoryCreate new empty directory+
dired-diffCompare file at point with another=
dired-subtree-toggleToggle viewing subtree at pointTAB

Dired Commands Using Regex

COMMANDDESCRIPTIONKEYBINDING
dired-mark-files-regexpMark files using regex% m
dired-do-copy-regexpCopy files using regex% C
dired-do-rename-regexpRename files using regex% R
dired-mark-files-regexpMark all files using regex* %

File Permissions And Ownership

COMMANDDESCRIPTIONKEYBINDING
dired-do-chgrpChange the group of marked filesg G
dired-do-chmodChange the mode of marked filesM
dired-do-chownChange the owner of marked filesO
dired-do-renameRename file or all marked filesR
(map! :leader
      (:prefix ("d" . "dired")
       :desc "Open dired" "d" #'dired
       :desc "Dired jump to current" "j" #'dired-jump)
      (:after dired
       (:map dired-mode-map
        :desc "Peep-dired image previews" "d p" #'peep-dired
        :desc "Dired view file" "d v" #'dired-view-file)))

(evil-define-key 'normal dired-mode-map
  (kbd "M-RET") 'dired-display-file
  (kbd "h") 'dired-up-directory
  (kbd "l") 'dired-open-file ; use dired-find-file instead of dired-open.
  (kbd "m") 'dired-mark
  (kbd "t") 'dired-toggle-marks
  (kbd "u") 'dired-unmark
  (kbd "C") 'dired-do-copy
  (kbd "D") 'dired-do-delete
  (kbd "J") 'dired-goto-file
  (kbd "M") 'dired-do-chmod
  (kbd "O") 'dired-do-chown
  (kbd "P") 'dired-do-print
  (kbd "R") 'dired-do-rename
  (kbd "T") 'dired-do-touch
  (kbd "Y") 'dired-copy-filenamecopy-filename-as-kill ; copies filename to kill ring.
  (kbd "Z") 'dired-do-compress
  (kbd "+") 'dired-create-directory
  (kbd "-") 'dired-do-kill-lines
  (kbd "% l") 'dired-downcase
  (kbd "% m") 'dired-mark-files-regexp
  (kbd "% u") 'dired-upcase
  (kbd "* %") 'dired-mark-files-regexp
  (kbd "* .") 'dired-mark-extension
  (kbd "* /") 'dired-mark-directories
  (kbd "; d") 'epa-dired-do-decrypt
  (kbd "; e") 'epa-dired-do-encrypt)
;; 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")))

Keybindings Within Dired With Peep-Dired-Mode Enabled

If peep-dired is enabled, you will get image previews as you go up/down with j and k

COMMANDDESCRIPTIONKEYBINDING
peep-diredToggle previews within diredSPC d p
peep-dired-next-fileMove to next file in peep-dired-modej
peep-dired-prev-fileMove to previous file in peep-dired-modek
(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)

Making Deleted Files Go To Trash Can

(setq delete-by-moving-to-trash t
      trash-directory "~/Papierkorb/")

Doom theme

Setting the theme to doom-one. To try out new themes, I set a keybinding for counsel-load-theme with SPC h t.

(setq doom-theme 'doom-one)
(map! :leader
      :desc "Load new theme" "h t" #'counsel-load-theme)

Transparency

With Emacs 29, true transparency has been added.

(add-to-list 'default-frame-alist '(alpha-background . 90))

Elfeed

An RSS newsfeed reader for Emacs.

(use-package! elfeed-goodies)
(elfeed-goodies/setup)
(setq elfeed-goodies/entry-pane-size 0.5)
(add-hook 'elfeed-show-mode-hook 'visual-line-mode)
(evil-define-key 'normal elfeed-show-mode-map
  (kbd "J") 'elfeed-goodies/split-show-next
  (kbd "K") 'elfeed-goodies/split-show-prev)
(evil-define-key 'normal elfeed-search-mode-map
  (kbd "J") 'elfeed-goodies/split-show-next
  (kbd "K") 'elfeed-goodies/split-show-prev)
(setq elfeed-feeds (quote
                    (("https://www.reddit.com/r/linux.rss" reddit linux)
                     ("https://www.reddit.com/r/commandline.rss" reddit commandline)
                     ("https://www.reddit.com/r/distrotube.rss" reddit distrotube)
                     ("https://www.reddit.com/r/emacs.rss" reddit emacs)
                     ("https://www.gamingonlinux.com/article_rss.php" gaming linux)
                     ("https://hackaday.com/blog/feed/" hackaday linux)
                     ("https://opensource.com/feed" opensource linux)
                     ("https://linux.softpedia.com/backend.xml" softpedia linux)
                     ("https://itsfoss.com/feed/" itsfoss linux)
                     ("https://www.zdnet.com/topic/linux/rss.xml" zdnet linux)
                     ("https://www.phoronix.com/rss.php" phoronix linux)
                     ("http://feeds.feedburner.com/d0od" omgubuntu linux)
                     ("https://www.computerworld.com/index.rss" computerworld linux)
                     ("https://www.networkworld.com/category/linux/index.rss" networkworld linux)
                     ("https://www.techrepublic.com/rssfeeds/topic/open-source/" techrepublic linux)
                     ("https://betanews.com/feed" betanews linux)
                     ("http://lxer.com/module/newswire/headlines.rss" lxer linux)
                     ("https://distrowatch.com/news/dwd.xml" distrowatch linux))))

Emms

One of the media players available for Emacs is emms, which stands for Emacs Multimedia System. By default, Doom Emacs does not use SPC a so the format I use for these bindings is SPC a plus key.

COMMANDDESCRIPTIONKEYBINDING
emms-playlist-mode-goSwitch to the playlist bufferSPC a a
emms-pausePause the trackSPC a x
emms-stopStop the trackSPC a s
emms-previousPlay previous track in playlistSPC a p
emms-nextPlay next track in playlistSPC a n
(emms-all)
(emms-default-players)
(emms-mode-line 1)
(emms-playing-time 1)
(setq emms-source-file-default-directory "~/Music/"
      emms-playlist-buffer-name "*Music*"
      emms-info-asynchronously t
      emms-source-file-directory-tree-function 'emms-source-file-directory-tree-find)
(map! :leader
      (:prefix ("a" . "EMMS audio player")
       :desc "Go to emms playlist" "a" #'emms-playlist-mode-go
       :desc "Emms pause track" "x" #'emms-pause
       :desc "Emms stop track" "s" #'emms-stop
       :desc "Emms play previous track" "p" #'emms-previous
       :desc "Emms play next track" "n" #'emms-next))

Emojis

“Emojify” is an Emacs extension to display emojis. It can display github style emojis like 😄 or plain ASCII ones like :).

(use-package emojify
  :hook (after-init . global-emojify-mode))

Erc

Is a built-in Emacs IRC client.

COMMANDDESCRIPTIONKEYBINDING
erc-tlsLaunch ERC using more secure TLS connectionSPC e E
(map! :leader
      (:prefix ("e". "evaluate/ERC/EWW")
       :desc "Launch ERC with TLS connection" "E" #'erc-tls))

(setq erc-prompt (lambda () (concat "[" (buffer-name) "]"))
      erc-server "irc.libera.chat"
      erc-nick "distrotube"
      erc-user-full-name "Derek Taylor"
      erc-track-shorten-start 24
      erc-autojoin-channels-alist '(("irc.libera.chat" "#archlinux" "#linux" "#emacs"))
      erc-kill-buffer-on-part t
      erc-fill-column 100
      erc-fill-function 'erc-fill-static
      erc-fill-static-center 20
      ;; erc-auto-query 'bury
      )

(defun i-wanna-be-social ()
  "Connect to IM networks using bitlbee."
  (interactive)
  (erc :server "localhost" :port 6667 :nick "distrotube" :password ""))

Evaluate E-Lisp Expressions

Changing some keybindings from their defaults to better fit with Doom Emacs, and to avoid conflicts with my window managers which sometimes use the control key in their keybindings. By default, Doom Emacs does not use SPC e for anything, so I choose to use the format SPC e plus key for these (I also use SPC e for ‘eww’ keybindings).

COMMANDDESCRIPTIONKEYBINDING
eval-bufferEvaluate elisp in bufferSPC e b
eval-defunEvaluate the defun containing or after pointSPC e d
eval-expressionEvaluate an elisp expressionSPC e e
eval-last-sexpEvaluate elisp expression before pointSPC e l
eval-regionEvaluate elisp in regionSPC e r
(map! :leader
      (:prefix ("e". "evaluate/ERC/EWW")
       :desc "Evaluate elisp in buffer" "b" #'eval-buffer
       :desc "Evaluate defun" "d" #'eval-defun
       :desc "Evaluate elisp expression" "e" #'eval-expression
       :desc "Evaluate last sexpression" "l" #'eval-last-sexp
       :desc "Evaluate elisp in region" "r" #'eval-region))

Eww

Is the ‘Emacs Web Wowser’, the builtin browser in Emacs. Below I set URLs to open in a specific browser (eww) with browse-url-browser-function. By default, Doom Emacs does not use SPC e for anything, so I choose to use the format SPC e plus key for these (I also use SPC e for ‘eval’ keybindings). I chose to use SPC s w for eww-search-words because Doom Emacs uses SPC s for ‘search’ commands.

;; (setq browse-url-browser-function 'eww-browse-url)
(setq browse-url-browser-function 'browse-url-generic
      browse-url-generic-program "firefox")
(map! :leader
      :desc "Search web for text between BEG/END"
      "s w" #'eww-search-words
      (:prefix ("e" . "evaluate/ERC/EWW")
       :desc "Eww web browser" "w" #'eww
       :desc "Eww reload page" "R" #'eww-reload))

EXWM

(autoload 'exwm-enable "exwm-config.el")

Fonts

Settings related to fonts within Doom Emacs:

  • doom-font – standard monospace font that is used for most things in Emacs.
  • doom-variable-pitch-font – variable font which is useful in some Emacs plugins.
  • doom-big-font – used in doom-big-font-mode; useful for presentations.
  • font-lock-comment-face – for comments.
  • font-lock-keyword-face – for keywords with special significance like ‘setq’ in elisp.
(setq doom-font (font-spec :family "JetBrains Mono" :size 15)
      doom-variable-pitch-font (font-spec :family "JetBrains Mono" :size 15)
      doom-big-font (font-spec :family "JetBrains Mono" :size 24))
(after! doom-themes
  (setq doom-themes-enable-bold t
        doom-themes-enable-italic t))
(custom-set-faces!
  '(font-lock-comment-face :slant italic)
  '(font-lock-keyword-face :slant italic))

Insert date

Some custom functions to insert the date. The function insert-todays-date can be used one of three different ways:

  • just the keybinding without the universal argument prefix
  • with one universal argument prefix
  • with two universal argument prefixes.

The universal argument prefix is SPC-u in Doom Emacs (C-u in standard GNU Emacs). The function insert-any-date only outputs to one format, which is the same format as insert-todays-date without a prefix.

COMMANDEXAMPLE OUTPUTKEYBINDING
dt/insert-todays-dateFriday, November 19, 2021SPC i d t
dt/insert-todays-date11-19-2021SPC u SPC i d t
dt/insert-todays-date2021-11-19SPC u SPC u SPC i d t
dt/insert-any-dateFriday, November 19, 2021SPC i d a
(defun dt/insert-todays-date (prefix)
  (interactive "P")
  (let ((format (cond
                 ((not prefix) "%A, %B %d, %Y")
                 ((equal prefix '(4)) "%m-%d-%Y")
                 ((equal prefix '(16)) "%Y-%m-%d"))))
    (insert (format-time-string format))))

(require 'calendar)
(defun dt/insert-any-date (date)
  "Insert DATE using the current locale."
  (interactive (list (calendar-read-date)))
  (insert (calendar-date-string date)))

(map! :leader
      (:prefix ("i d" . "Insert date")
        :desc "Insert any date" "a" #'dt/insert-any-date
        :desc "Insert todays date" "t" #'dt/insert-todays-date))

Ivy

Is a generic completion mechanism for Emacs.

Ivy-Posframe

Ivy-posframe is an ivy extension, which lets ivy use posframe to show its candidate menu. Some of the settings below involve:

  • ivy-posframe-display-functions-alist – sets the display position for specific programs
  • ivy-posframe-height-alist – sets the height of the list displayed for specific programs

Available functions (positions) for ivy-posframe-display-functions-alist

  • ivy-posframe-display-at-frame-center
  • ivy-posframe-display-at-window-center
  • ivy-posframe-display-at-frame-bottom-left
  • ivy-posframe-display-at-window-bottom-left
  • ivy-posframe-display-at-frame-bottom-window-center
  • ivy-posframe-display-at-point
  • ivy-posframe-display-at-frame-top-center

NOTE: If the setting for ivy-posframe-display is set to ‘nil’ (false), anything that is set to ivy-display-function-fallback will just default to their normal position in Doom Emacs (usually a bottom split). However, if this is set to ‘t’ (true), then the fallback position will be centered in the window.

(setq ivy-posframe-display-functions-alist
      '((swiper                     . ivy-posframe-display-at-point)
        (complete-symbol            . ivy-posframe-display-at-point)
        (counsel-M-x                . ivy-display-function-fallback)
        (counsel-esh-history        . ivy-posframe-display-at-window-center)
        (counsel-describe-function  . ivy-display-function-fallback)
        (counsel-describe-variable  . ivy-display-function-fallback)
        (counsel-find-file          . ivy-display-function-fallback)
        (counsel-recentf            . ivy-display-function-fallback)
        (counsel-register           . ivy-posframe-display-at-frame-bottom-window-center)
        (dmenu                      . ivy-posframe-display-at-frame-top-center)
        (nil                        . ivy-posframe-display))
      ivy-posframe-height-alist
      '((swiper . 20)
        (dmenu . 20)
        (t . 10)))
(ivy-posframe-mode 1) ; 1 enables posframe-mode, 0 disables it.

Ivy Keybindings

By default, Doom Emacs does not use SPC v, so the format I use for these bindings is SPC v plus key.

(map! :leader
      (:prefix ("v" . "Ivy")
       :desc "Ivy push view" "v p" #'ivy-push-view
       :desc "Ivy switch view" "v s" #'ivy-switch-view))

Line Settings

I set comment-line to SPC TAB TAB which is a rather comfortable keybinding for me. The standard Emacs keybinding for comment-line is C-x C-;. The other keybindings are for commands that toggle on/off various line-related settings. Doom Emacs uses SPC t for “toggle” commands, so I choose SPC t plus key for those bindings.

COMMANDDESCRIPTIONKEYBINDING
comment-lineComment or uncomment linesSPC TAB TAB
hl-line-modeToggle line highlighting in current frameSPC t h
global-hl-line-modeToggle line highlighting globallySPC t H
doom/toggle-line-numbersToggle line numbersSPC t l
toggle-truncate-linesToggle truncate linesSPC t t
(setq display-line-numbers-type t)
(map! :leader
      :desc "Comment or uncomment lines" "TAB TAB" #'comment-line
      (:prefix ("t" . "toggle")
       :desc "Toggle line numbers" "l" #'doom/toggle-line-numbers
       :desc "Toggle line highlight in frame" "h" #'hl-line-mode
       :desc "Toggle line highlight globally" "H" #'global-hl-line-mode
       :desc "Toggle truncate lines" "t" #'toggle-truncate-lines))

Markdown

(custom-set-faces
 '(markdown-header-face ((t (:inherit font-lock-function-name-face :weight bold :family "variable-pitch"))))
 '(markdown-header-face-1 ((t (:inherit markdown-header-face :height 1.7))))
 '(markdown-header-face-2 ((t (:inherit markdown-header-face :height 1.6))))
 '(markdown-header-face-3 ((t (:inherit markdown-header-face :height 1.5))))
 '(markdown-header-face-4 ((t (:inherit markdown-header-face :height 1.4))))
 '(markdown-header-face-5 ((t (:inherit markdown-header-face :height 1.3))))
 '(markdown-header-face-6 ((t (:inherit markdown-header-face :height 1.2)))))

Minimap

A minimap sidebar displaying a smaller version of the current buffer on either the left or right side. It highlights the currently shown region and updates its position automatically. Be aware that this minimap program does not work in Org documents. This is not unusual though because I have tried several minimap programs and none of them can handle Org.

COMMANDDESCRIPTIONKEYBINDING
minimap-modeToggle minimap-modeSPC t m
(setq minimap-window-location 'right)
(map! :leader
      (:prefix ("t" . "toggle")
       :desc "Toggle minimap-mode" "m" #'minimap-mode))

Modeline

The modeline is the bottom status bar that appears in Emacs windows. For more information on what is available to configure in the Doom modeline, check out their Git.

(set-face-attribute 'mode-line nil :font "Ubuntu Mono-13")
(setq doom-modeline-height 30     ;; sets modeline height
      doom-modeline-bar-width 5   ;; sets right bar width
      doom-modeline-persp-name t  ;; adds perspective name to modeline
      doom-modeline-persp-icon t) ;; adds folder icon next to persp name

Mouse Support

Adding mouse support in the terminal version of Emacs.

(xterm-mouse-mode 1)

Neotree

Is a file tree viewer. When you open neotree, it jumps to the current file thanks to neo-smart-open. The neo-window-fixed-size setting makes the neotree width be adjustable. Doom Emacs had no keybindings set for neotree. Since Doom Emacs uses SPC t for ‘toggle’ keybindings, I used SPC t n for toggle-neotree.

COMMANDDESCRIPTIONKEYBINDING
neotree-toggleToggle neotreeSPC t n
neotree- dirOpen directory in neotreeSPC d n
(after! neotree
  (setq neo-smart-open t
        neo-window-fixed-size nil))
(after! doom-themes
  (setq doom-neotree-enable-variable-pitch t)
  (remove-hook 'doom-load-theme-hook #'doom-themes-neotree-config))
(map! :leader
      :desc "Toggle neotree file viewer" "t n" #'neotree-toggle
      :desc "Open directory in neotree" "d n" #'neotree-dir)

Open Specific Files

Keybindings to open files that I work with all the time using the find-file command, which is the interactive file search that opens with C-x C-f in GNU Emacs or SPC f f in Doom Emacs. These keybindings use find-file non-interactively since we specify exactly what file to open. The format I use for these bindings is ‘SPC =’ plus ‘key’ since Doom Emacs does not use ‘SPC =’.

PATH TO FILEDESCRIPTIONKEYBINDING
~/Org/agenda.orgEdit agenda fileSPC = a
~/.config/doom/config.orgEdit doom config.orgSPC = c
~/.config/doom/init.elEdit doom init.elSPC = i
~/.config/doom/packages.elEdit doom packages.elSPC = p
~/.config/doom/eshell/aliasesEdit eshell aliasesSPC = e a
~/.config/doom/eshell/profileEdit eshell profileSPC = e p
(map! :leader
      (:prefix ("=" . "open file")
       :desc "Edit agenda file" "a" #'(lambda () (interactive) (find-file "~/NextCloud/Documents/Org/agenda.org"))
       :desc "Edit doom config.org" "c" #'(lambda () (interactive) (find-file "~/.config/doom/config.org"))
       :desc "Edit doom init.el" "i" #'(lambda () (interactive) (find-file "~/.config/doom/init.el"))
       :desc "Edit doom packages.el" "p" #'(lambda () (interactive) (find-file "~/.config/doom/packages.el"))))
(map! :leader
      (:prefix ("= e" . "open eshell files")
       :desc "Edit eshell aliases" "a" #'(lambda () (interactive) (find-file "~/.config/doom/eshell/aliases"))
       :desc "Edit eshell profile" "p" #'(lambda () (interactive) (find-file "~/.config/doom/eshell/profile"))))

Org Mode

I wrapped most of this block in (after! org). Without this, my settings might be evaluated too early, which will result in my settings being overwritten by Doom’s defaults. I have also enabled org-journal, org-superstar and org-roam by adding (+journal +pretty +roam2) to the org section of my Doom Emacs init.el.

NOTE: I have the location of my Org directory and Roam directory in $HOME/NextCloud/Documents/ which is a Nextcloud folder that allows me to instantly sync all of my Org work between my home computer and my office computer.

(map! :leader
      :desc "Org babel tangle" "m B" #'org-babel-tangle)
(after! org
  (setq org-directory "~/NextCloud/Documents/Org/"
        org-agenda-files '("~/NextCloud/Documents/Org/agenda.org")
        org-default-notes-file (expand-file-name "notes.org" org-directory)
        org-ellipsis ""
        org-superstar-headline-bullets-list '("" "" "" "" "" "" "")
        org-superstar-itembullet-alist '((?+ . ?➤) (?- . ?✦)) ; changes +/- symbols in item lists
        org-log-done 'time
        org-hide-emphasis-markers t
        ;; ex. of org-link-abbrev-alist in action
        ;; [[arch-wiki:Name_of_Page][Description]]
        org-link-abbrev-alist    ; This overwrites the default Doom org-link-abbrev-list
          '(("google" . "http://www.google.com/search?q=")
            ("arch-wiki" . "https://wiki.archlinux.org/index.php/")
            ("ddg" . "https://duckduckgo.com/?q=")
            ("wiki" . "https://en.wikipedia.org/wiki/"))
        org-table-convert-region-max-lines 20000
        org-todo-keywords        ; This overwrites the default Doom org-todo-keywords
          '((sequence
             "TODO(t)"           ; A task that is ready to be tackled
             "BLOG(b)"           ; Blog writing assignments
             "GYM(g)"            ; Things to accomplish at the gym
             "PROJ(p)"           ; A project that contains other tasks
             "VIDEO(v)"          ; Video assignments
             "WAIT(w)"           ; Something is holding up this task
             "|"                 ; The pipe necessary to separate "active" states and "inactive" states
             "DONE(d)"           ; Task has been completed
             "CANCELLED(c)" )))) ; Task has been cancelled

Org Fonts

I have created an interactive function for each color scheme M-x dt/org-colors-*. These functions will set appropriate colors and font attributes for org-level fonts and the org-table font.

(defun dt/org-colors-doom-one ()
  "Enable Doom One colors for Org headers."
  (interactive)
  (dolist
      (face
       '((org-level-1 1.7 "#51afef" ultra-bold)
         (org-level-2 1.6 "#c678dd" extra-bold)
         (org-level-3 1.5 "#98be65" bold)
         (org-level-4 1.4 "#da8548" semi-bold)
         (org-level-5 1.3 "#5699af" normal)
         (org-level-6 1.2 "#a9a1e1" normal)
         (org-level-7 1.1 "#46d9ff" normal)
         (org-level-8 1.0 "#ff6c6b" normal)))
    (set-face-attribute (nth 0 face) nil :font doom-variable-pitch-font :weight (nth 3 face) :height (nth 1 face) :foreground (nth 2 face)))
    (set-face-attribute 'org-table nil :font doom-font :weight 'normal :height 1.0 :foreground "#bfafdf"))

(defun dt/org-colors-dracula ()
  "Enable Dracula colors for Org headers."
  (interactive)
  (dolist
      (face
       '((org-level-1 1.7 "#8be9fd" ultra-bold)
         (org-level-2 1.6 "#bd93f9" extra-bold)
         (org-level-3 1.5 "#50fa7b" bold)
         (org-level-4 1.4 "#ff79c6" semi-bold)
         (org-level-5 1.3 "#9aedfe" normal)
         (org-level-6 1.2 "#caa9fa" normal)
         (org-level-7 1.1 "#5af78e" normal)
         (org-level-8 1.0 "#ff92d0" normal)))
    (set-face-attribute (nth 0 face) nil :font doom-variable-pitch-font :weight (nth 3 face) :height (nth 1 face) :foreground (nth 2 face)))
    (set-face-attribute 'org-table nil :font doom-font :weight 'normal :height 1.0 :foreground "#bfafdf"))

(defun dt/org-colors-gruvbox-dark ()
  "Enable Gruvbox Dark colors for Org headers."
  (interactive)
  (dolist
      (face
       '((org-level-1 1.7 "#458588" ultra-bold)
         (org-level-2 1.6 "#b16286" extra-bold)
         (org-level-3 1.5 "#98971a" bold)
         (org-level-4 1.4 "#fb4934" semi-bold)
         (org-level-5 1.3 "#83a598" normal)
         (org-level-6 1.2 "#d3869b" normal)
         (org-level-7 1.1 "#d79921" normal)
         (org-level-8 1.0 "#8ec07c" normal)))
    (set-face-attribute (nth 0 face) nil :font doom-variable-pitch-font :weight (nth 3 face) :height (nth 1 face) :foreground (nth 2 face)))
    (set-face-attribute 'org-table nil :font doom-font :weight 'normal :height 1.0 :foreground "#bfafdf"))

(defun dt/org-colors-monokai-pro ()
  "Enable Monokai Pro colors for Org headers."
  (interactive)
  (dolist
      (face
       '((org-level-1 1.7 "#78dce8" ultra-bold)
         (org-level-2 1.6 "#ab9df2" extra-bold)
         (org-level-3 1.5 "#a9dc76" bold)
         (org-level-4 1.4 "#fc9867" semi-bold)
         (org-level-5 1.3 "#ff6188" normal)
         (org-level-6 1.2 "#ffd866" normal)
         (org-level-7 1.1 "#78dce8" normal)
         (org-level-8 1.0 "#ab9df2" normal)))
    (set-face-attribute (nth 0 face) nil :font doom-variable-pitch-font :weight (nth 3 face) :height (nth 1 face) :foreground (nth 2 face)))
    (set-face-attribute 'org-table nil :font doom-font :weight 'normal :height 1.0 :foreground "#bfafdf"))

(defun dt/org-colors-nord ()
  "Enable Nord colors for Org headers."
  (interactive)
  (dolist
      (face
       '((org-level-1 1.7 "#81a1c1" ultra-bold)
         (org-level-2 1.6 "#b48ead" extra-bold)
         (org-level-3 1.5 "#a3be8c" bold)
         (org-level-4 1.4 "#ebcb8b" semi-bold)
         (org-level-5 1.3 "#bf616a" normal)
         (org-level-6 1.2 "#88c0d0" normal)
         (org-level-7 1.1 "#81a1c1" normal)
         (org-level-8 1.0 "#b48ead" normal)))
    (set-face-attribute (nth 0 face) nil :font doom-variable-pitch-font :weight (nth 3 face) :height (nth 1 face) :foreground (nth 2 face)))
    (set-face-attribute 'org-table nil :font doom-font :weight 'normal :height 1.0 :foreground "#bfafdf"))

(defun dt/org-colors-oceanic-next ()
  "Enable Oceanic Next colors for Org headers."
  (interactive)
  (dolist
      (face
       '((org-level-1 1.7 "#6699cc" ultra-bold)
         (org-level-2 1.6 "#c594c5" extra-bold)
         (org-level-3 1.5 "#99c794" bold)
         (org-level-4 1.4 "#fac863" semi-bold)
         (org-level-5 1.3 "#5fb3b3" normal)
         (org-level-6 1.2 "#ec5f67" normal)
         (org-level-7 1.1 "#6699cc" normal)
         (org-level-8 1.0 "#c594c5" normal)))
    (set-face-attribute (nth 0 face) nil :font doom-variable-pitch-font :weight (nth 3 face) :height (nth 1 face) :foreground (nth 2 face)))
    (set-face-attribute 'org-table nil :font doom-font :weight 'normal :height 1.0 :foreground "#bfafdf"))

(defun dt/org-colors-palenight ()
  "Enable Palenight colors for Org headers."
  (interactive)
  (dolist
      (face
       '((org-level-1 1.7 "#82aaff" ultra-bold)
         (org-level-2 1.6 "#c792ea" extra-bold)
         (org-level-3 1.5 "#c3e88d" bold)
         (org-level-4 1.4 "#ffcb6b" semi-bold)
         (org-level-5 1.3 "#a3f7ff" normal)
         (org-level-6 1.2 "#e1acff" normal)
         (org-level-7 1.1 "#f07178" normal)
         (org-level-8 1.0 "#ddffa7" normal)))
    (set-face-attribute (nth 0 face) nil :font doom-variable-pitch-font :weight (nth 3 face) :height (nth 1 face) :foreground (nth 2 face)))
    (set-face-attribute 'org-table nil :font doom-font :weight 'normal :height 1.0 :foreground "#bfafdf"))

(defun dt/org-colors-solarized-dark ()
  "Enable Solarized Dark colors for Org headers."
  (interactive)
  (dolist
      (face
       '((org-level-1 1.7 "#268bd2" ultra-bold)
         (org-level-2 1.6 "#d33682" extra-bold)
         (org-level-3 1.5 "#859900" bold)
         (org-level-4 1.4 "#b58900" semi-bold)
         (org-level-5 1.3 "#cb4b16" normal)
         (org-level-6 1.2 "#6c71c4" normal)
         (org-level-7 1.1 "#2aa198" normal)
         (org-level-8 1.0 "#657b83" normal)))
    (set-face-attribute (nth 0 face) nil :font doom-variable-pitch-font :weight (nth 3 face) :height (nth 1 face) :foreground (nth 2 face)))
    (set-face-attribute 'org-table nil :font doom-font :weight 'normal :height 1.0 :foreground "#bfafdf"))

(defun dt/org-colors-solarized-light ()
  "Enable Solarized Light colors for Org headers."
  (interactive)
  (dolist
      (face
       '((org-level-1 1.7 "#268bd2" ultra-bold)
         (org-level-2 1.6 "#d33682" extra-bold)
         (org-level-3 1.5 "#859900" bold)
         (org-level-4 1.4 "#b58900" semi-bold)
         (org-level-5 1.3 "#cb4b16" normal)
         (org-level-6 1.2 "#6c71c4" normal)
         (org-level-7 1.1 "#2aa198" normal)
         (org-level-8 1.0 "#657b83" normal)))
    (set-face-attribute (nth 0 face) nil :font doom-variable-pitch-font :weight (nth 3 face) :height (nth 1 face) :foreground (nth 2 face)))
    (set-face-attribute 'org-table nil :font doom-font :weight 'normal :height 1.0 :foreground "#bfafdf"))

(defun dt/org-colors-tomorrow-night ()
  "Enable Tomorrow Night colors for Org headers."
  (interactive)
  (dolist
      (face
       '((org-level-1 1.7 "#81a2be" ultra-bold)
         (org-level-2 1.6 "#b294bb" extra-bold)
         (org-level-3 1.5 "#b5bd68" bold)
         (org-level-4 1.4 "#e6c547" semi-bold)
         (org-level-5 1.3 "#cc6666" normal)
         (org-level-6 1.2 "#70c0ba" normal)
         (org-level-7 1.1 "#b77ee0" normal)
         (org-level-8 1.0 "#9ec400" normal)))
    (set-face-attribute (nth 0 face) nil :font doom-variable-pitch-font :weight (nth 3 face) :height (nth 1 face) :foreground (nth 2 face)))
    (set-face-attribute 'org-table nil :font doom-font :weight 'normal :height 1.0 :foreground "#bfafdf"))

;; Load our desired dt/org-colors-* theme on startup
(dt/org-colors-doom-one)

Org-Export

We need ox-man for “Org eXporting” to manpage format and ox-gemini for exporting to gemtext (for the gemini protocol).

NOTE: I also enable ox-publish for converting an Org site into an HTML site, but that is done in init.el (org +publish).

(use-package ox-man)
(use-package ox-gemini)

Org-Journal (Not Setup)

(setq org-journal-dir "~/NextCloud/Documents/Org/journal/"
      org-journal-date-prefix "* "
      org-journal-time-prefix "** "
      org-journal-date-format "%B %d, %Y (%A) "
      org-journal-file-format "%Y-%m-%d.org")

Org-publish (Not Setup)

(setq org-publish-use-timestamps-flag nil)
(setq org-export-with-broken-links t)
(setq org-publish-project-alist
      '(("distro.tube without manpages"
         :base-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/"
         :base-extension "org"
         :publishing-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/html/"
         :recursive t
         :exclude "org-html-themes/.*\\|man-org/man*"
         :publishing-function org-html-publish-to-html
         :headline-levels 4             ; Just the default for this project.
         :auto-preamble t)
         ("man0p"
         :base-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/man-org/man0p/"
         :base-extension "org"
         :publishing-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/html/man-org/man0p/"
         :recursive t
         :publishing-function org-html-publish-to-html
         :headline-levels 4             ; Just the default for this project.
         :auto-preamble t)
         ("man1"
         :base-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/man-org/man1/"
         :base-extension "org"
         :publishing-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/html/man-org/man1/"
         :recursive t
         :publishing-function org-html-publish-to-html
         :headline-levels 4             ; Just the default for this project.
         :auto-preamble t)
         ("man1p"
         :base-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/man-org/man1p/"
         :base-extension "org"
         :publishing-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/html/man-org/man1p/"
         :recursive t
         :publishing-function org-html-publish-to-html
         :headline-levels 4             ; Just the default for this project.
         :auto-preamble t)
         ("man2"
         :base-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/man-org/man2/"
         :base-extension "org"
         :publishing-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/html/man-org/man2/"
         :recursive t
         :publishing-function org-html-publish-to-html
         :headline-levels 4             ; Just the default for this project.
         :auto-preamble t)
         ("man3"
         :base-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/man-org/man3/"
         :base-extension "org"
         :publishing-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/html/man-org/man3/"
         :recursive t
         :publishing-function org-html-publish-to-html
         :headline-levels 4             ; Just the default for this project.
         :auto-preamble t)
         ("man3p"
         :base-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/man-org/man3p/"
         :base-extension "org"
         :publishing-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/html/man-org/man3p/"
         :recursive t
         :publishing-function org-html-publish-to-html
         :headline-levels 4             ; Just the default for this project.
         :auto-preamble t)
         ("man4"
         :base-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/man-org/man4/"
         :base-extension "org"
         :publishing-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/html/man-org/man4/"
         :recursive t
         :publishing-function org-html-publish-to-html
         :headline-levels 4             ; Just the default for this project.
         :auto-preamble t)
         ("man5"
         :base-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/man-org/man5/"
         :base-extension "org"
         :publishing-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/html/man-org/man5/"
         :recursive t
         :publishing-function org-html-publish-to-html
         :headline-levels 4             ; Just the default for this project.
         :auto-preamble t)
         ("man6"
         :base-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/man-org/man6/"
         :base-extension "org"
         :publishing-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/html/man-org/man6/"
         :recursive t
         :publishing-function org-html-publish-to-html
         :headline-levels 4             ; Just the default for this project.
         :auto-preamble t)
         ("man7"
         :base-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/man-org/man7/"
         :base-extension "org"
         :publishing-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/html/man-org/man7/"
         :recursive t
         :publishing-function org-html-publish-to-html
         :headline-levels 4             ; Just the default for this project.
         :auto-preamble t)
         ("man8"
         :base-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/man-org/man8/"
         :base-extension "org"
         :publishing-directory "~/NextCloud/Documents/gitlab-repos/distro.tube/html/man-org/man8/"
         :recursive t
         :publishing-function org-html-publish-to-html
         :headline-levels 4             ; Just the default for this project.
         :auto-preamble t)
         ("org-static"
         :base-directory "~/Org/website"
         :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf"
         :publishing-directory "~/public_html/"
         :recursive t
         :exclude ".*/org-html-themes/.*"
         :publishing-function org-publish-attachment)
         ("dtos.dev"
         :base-directory "~/NextCloud/Documents/gitlab-repos/dtos.dev/"
         :base-extension "org"
         :publishing-directory "~/NextCloud/Documents/gitlab-repos/dtos.dev/html/"
         :recursive t
         :publishing-function org-html-publish-to-html
         :headline-levels 4             ; Just the default for this project.
         :auto-preamble t)

      ))

Org-Appear

Org mode provides a way to toggle visibility of hidden elements such as emphasis markers, links, etc. by customizing specific variables

(use-package! org-appear
;;  :hook (org-mode . org-appear-mode)
  :config
  (setq org-appear-autolinks t))
(map! :leader
      (:prefix ("t" . "toggle")
       :desc "Toggle Org-appear" "a" #'org-appear-mode))

Org-auto-tangle

org-auto-tangle allows you to add the option #+auto_tangle: t in your Org file so that it automatically tangles when you save the document.

(use-package! org-auto-tangle
  :defer t
  :hook (org-mode . org-auto-tangle-mode)
  :config
  (setq org-auto-tangle-default t))

Org-Babel

;;(org-babel-do-load-languages
;; 'org-babel-load-languages
;; '((java . t)))

Password Store

Uses the standard Unix password store “pass”.

(use-package! password-store)

Perspective

It provides multiple named workspaces (or “perspectives”) in Emacs, similar to having multiple desktops in window managers like Awesome and XMonad. Each perspective has its own buffer list and its own window layout, making it easy to work on many separate projects without getting lost in all the buffers. Switching to a perspective activates its window configuration, and when in a perspective, only its buffers are available (by default). Doom Emacs uses SPC some_key for binding some of the perspective commands, so I used this binging format for the perspective bindings that I created..

COMMANDDESCRIPTIONKEYBINDING
persp-switchSwitch to perspective NAMESPC DEL
persp-switch-to-bufferSwitch to buffer in perspectiveSPC ,
persp-nextSwitch to next perspectiveSPC ]
persp-prevSwitch to previous perspectiveSPC [
persp-add-bufferAdd a buffer to current perspectiveSPC +
persp-remove-by-nameRemove perspective by nameSPC -
+workspace/switch-to-{0-9}Switch to workspace nSPC 0-9
(map! :leader
      :desc "Switch to perspective NAME" "DEL" #'persp-switch
      :desc "Switch to buffer in perspective" "," #'persp-switch-to-buffer
      :desc "Switch to next perspective" "]" #'persp-next
      :desc "Switch to previous perspective" "[" #'persp-prev
      :desc "Add a buffer current perspective" "+" #'persp-add-buffer
      :desc "Remove perspective by name" "-" #'persp-remove-by-name)

Rainbow Mode

Rainbox mode displays the actual color for any hex value color. It’s such a nice feature that I wanted it turned on all the time, regardless of what mode I am in. The following creates a global minor mode for rainbow-mode and enables it (exception: org-agenda-mode since rainbow-mode destroys all highlighting in org-agenda).

(define-globalized-minor-mode global-rainbow-mode rainbow-mode
  (lambda ()
    (when (not (memq major-mode
                (list 'org-agenda-mode)))
     (rainbow-mode 1))))
(global-rainbow-mode 1 )

Registers

Emacs registers are compartments where you can save text, rectangles and positions for later use. Once you save text or a rectangle in a register, you can copy it into the buffer once or many times; once you save a position in a register, you can jump back to that position once or many times. The default GNU Emacs keybindings for these commands (with the exception of counsel-register) involves C-x r followed by one or more other keys. I wanted to make this a little more user friendly, and since I am using Doom Emacs, I choose to replace the C-x r part of the key chords with SPC r.

COMMANDDESCRIPTIONKEYBINDING
copy-to-registerCopy to registerSPC r c
frameset-to-registerFrameset to registerSPC r f
insert-registerInsert contents of registerSPC r i
jump-to-registerJump to registerSPC r j
list-registersList registersSPC r l
number-to-registerNumber to registerSPC r n
counsel-registerInteractively choose a registerSPC r r
view-registerView a registerSPC r v
window-configuration-to-registerWindow configuration to registerSPC r w
increment-registerIncrement registerSPC r +
point-to-registerPoint to registerSPC r SPC
(map! :leader
      (:prefix ("r" . "registers")
       :desc "Copy to register" "c" #'copy-to-register
       :desc "Frameset to register" "f" #'frameset-to-register
       :desc "Insert contents of register" "i" #'insert-register
       :desc "Jump to register" "j" #'jump-to-register
       :desc "List registers" "l" #'list-registers
       :desc "Number to register" "n" #'number-to-register
       :desc "Interactively choose a register" "r" #'counsel-register
       :desc "View a register" "v" #'view-register
       :desc "Window configuration to register" "w" #'window-configuration-to-register
       :desc "Increment register" "+" #'increment-register
       :desc "Point to register" "SPC" #'point-to-register))

Shells

Settings for the various shells and terminal emulators within Emacs.

  • shell-file-name – sets the shell to be used in M-x shell, M-x term, M-x ansi-term and M-x vterm.
  • eshell-aliases-file – sets an aliases file for the eshell.
(setq shell-file-name "/bin/fish"
      vterm-max-scrollback 5000)
(setq eshell-rc-script "~/.config/doom/eshell/profile"
      eshell-aliases-file "~/.config/doom/eshell/aliases"
      eshell-history-size 5000
      eshell-buffer-maximum-lines 5000
      eshell-hist-ignoredups t
      eshell-scroll-to-bottom-on-input t
      eshell-destroy-buffer-when-process-dies t
      eshell-visual-commands'("bash" "fish" "htop" "ssh" "top" "zsh"))
(map! :leader
      :desc "Eshell" "e s" #'eshell
      :desc "Eshell popup toggle" "e t" #'+eshell/toggle
      :desc "Counsel eshell history" "e h" #'counsel-esh-history
      :desc "Vterm popup toggle" "v t" #'+vterm/toggle)

Splits

I set splits to default to opening on the right using prefer-horizontal-split. I set a keybinding for clone-indirect-buffer-other-window for when I want to have the same document in two splits. The text of the indirect buffer is always identical to the text of its base buffer; changes made by editing either one are visible immediately in the other. But in all other respects, the indirect buffer and its base buffer are completely separate. For example, I can fold one split but other will be unfolded.

(defun prefer-horizontal-split ()
  (set-variable 'split-height-threshold nil t)
  (set-variable 'split-width-threshold 40 t)) ; make this as low as needed
(add-hook 'markdown-mode-hook 'prefer-horizontal-split)
(map! :leader
      :desc "Clone indirect buffer other window" "b c" #'clone-indirect-buffer-other-window)

Start Page

Instead of using Doom’s Dashboard or the Emacs Dashboard program, I have decided to just set an custom start file as my “dashboard” since it allows me more customization options. I have added to the start-mode-hook the argument read-only-mode. This is to prevent accidental editing of the start file, and to prevent clashes with the start-mode specific keybindings. You can toggle on/off read-only-mode with SPC t r.

(setq initial-buffer-choice "~/.config/doom/start.org")

(define-minor-mode start-mode
  "Provide functions for custom start page."
  :lighter " start"
  :keymap (let ((map (make-sparse-keymap)))
          ;;(define-key map (kbd "M-z") 'eshell)
            (evil-define-key 'normal start-mode-map
              (kbd "1") '(lambda () (interactive) (find-file "~/.config/doom/config.org"))
              (kbd "2") '(lambda () (interactive) (find-file "~/.config/doom/init.el"))
              (kbd "3") '(lambda () (interactive) (find-file "~/.config/doom/packages.el"))
              (kbd "4") '(lambda () (interactive) (find-file "~/.config/doom/eshell/aliases"))
              (kbd "5") '(lambda () (interactive) (find-file "~/.config/doom/eshell/profile")))
          map))

(add-hook 'start-mode-hook 'read-only-mode) ;; make start.org read-only; use 'SPC t r' to toggle off read-only.
(provide 'start-mode)

Winner Mode

Winner mode has been included with GNU Emacs since version 20. This is a global minor mode and, when activated, it allows you to “undo” (and “redo”) changes in the window configuration with the key commands ‘SCP w <left>’ and ‘SPC w <right>’.

(map! :leader
      (:prefix ("w" . "window")
       :desc "Winner redo" "<right>" #'winner-redo
       :desc "Winner undo" "<left>" #'winner-undo))

Zap To Char

Emacs provides a zap-to-char command that kills from the current point to a character. It is bound to M-z in standard GNU Emacs but since Doom Emacs uses SPC as its leader key and does not have SPC z binded to anything, it just makes since to use it for zap-to-char. Note that zap-to-char can be used with the universal argument SPC u to modify its behavior. Examples of zap-to-char usage are listed in the table below:

KEYBINDINGWHAT IS DOES
SPC z edeletes all chars to the next occurrence of ‘e’
SPC u 2 SPC z edeletes all chars to the second occurrence of ‘e’
SPC u - SPC z edeletes all chars to the previous occurrence of ‘e’
SPC u - 2 SPC z edeletes all chars to the second previous occurrence of ‘e’
SPC u 1 0 0 SPC u SPC z edeletes all chars to the 100th occurrence of ‘e’

TIP: The universal argument SPC u can only take a single integer by default. If you need to use a multi-digit number (like 100 in the last example in the table above), then you must terminate the universal argument with another SPC u after typing the number.

zap-up-to-char is an alternative command that does not zap the char specified. It is binded to SPC Z. It can also be used in conjunction with the universal argument SPC u in similar fashion to the the zap-to-char examples above.

NOTE: Vim (evil mode) has similar functionality builtin. You can delete to the next occurrence of ‘e’ by using ‘dte’ in normal. To delete to the next occurrence of ‘e’ including the ‘e’, then you would use ‘dfe’. And you can modify ‘dt’ and ‘df’ by prefixing them with numbers, so ‘2dte’ would delete to the second occurrence of ‘e’.

(map! :leader
      :desc "Zap to char" "z" #'zap-to-char
      :desc "Zap up to char" "Z" #'zap-up-to-char)

Flyspell Users

Flyspell will run a series of predicate functions to determine if a word should be spell checked. You can add your own with set-flyspell-predicate!:

Flyspell predicates take no arguments and must return a boolean to determine if the word at point should be spell checked. For example:

(set-flyspell-predicate! '(markdown-mode gfm-mode)
  (let ((faces (doom-enlist (get-text-property (point) 'face))))
    (or (and (memq 'font-lock-comment-face faces)
             (memq 'markdown-code-face faces))
        (not (cl-loop with unsafe-faces = '(markdown-reference-face
                                            markdown-url-face
                                            markdown-markup-face
                                            markdown-comment-face
                                            markdown-html-attr-name-face
                                            markdown-html-attr-value-face
                                            markdown-html-tag-name-face
                                            markdown-code-face)
                      for face in faces
                      if (memq face unsafe-faces)
                      return t)))))

Dap Debugger

It is for debugging and provides the intreface

KeybindingsDescriptionCommand
SPC D ddap debugdap-debug
SPC D kdap disconnectdap-disconnect
SPC D hdap hydradap-hydra
SPC D ldap debug lastdap-debug-last
SPC D rdap debug recentdap-debug-recent
SPC D tdap delete all sesionsdap-delete-all-session
SPC D edap edit templatedap-debug-edit-template
SPC D bdap breakpoint toggledap-breakpoint-toggle
SPC D pdap breakpoint log messagedap-breakpoint-log-message
SPC D cdap breakpoint condictiondap-breakpoint-condiction
SPC D mdap breakpoint hit conditiondap-breakpoint-hit-condiction
SPC D sdap switch stackframedap-switch-stack-frame
SPC D udap ui
SPC D u rdap ui repldap-ui-repl
SPC D u adap ui expression adddap-ui-expression-add
SPC D u ddap ui expression removedap-ui-expression-remove
(map! :leader
      (:prefix ("D" . "Dap Debugger")
        :desc "Start Debugger" "d" #'dap-debug
        :desc "Kill Debugger" "k" #'dap-disconnect
        :desc "Dap hydra" "h" #'dap-hydra
        :desc "Debug last" "l" #'dap-debug-last
        :desc "Debug recent" "r" #'dap-debug-recent
        :desc "Delete all session" "t" #'dap-delete-all-sessions
        :desc "Edit template" "e" #'dap-debug-edit-template
        :desc "Breakpoint toggle" "b" #'dap-breakpoint-toggle
        :desc "Breakpoint log message" "p" #'dap-breakpoint-log-message
        :desc "Breakpoint condition" "c" #'dap-breakpoint-condiction
        :desc "Breakpoint hit condiction" "m" #'dap-breakpoint-hit-condiction
        :desc "Switch stack frame" "s" #'dap-switch-stack-frame))
(map! :leader
      (:prefix ("D u" . "Dap Debugger UI")
        :desc "UI repl" "r" #'dap-ui-repl
        :desc "UI expression add" "a" #'dap-ui-expression-add
        :desc "UI expression remave" "d" #'dap-ui-expression-remove))

Flycheck

Annoying syntax checking that will make you want to pull your hair out, but you colleges will thank you for it.

(map! :leader
      (:prefix ("F" . "Flycheck")
        :desc "select checker" "s" #'flycheck-select-checker
        :desc "hydra" "h" #'hydra-flycheck/body))
(defhydra hydra-flycheck (:color blue)
  "
  ^
  ^Flycheck^          ^Errors^            ^Checker^
  ^────────^──────────^──────^────────────^───────^─────
  _q_ quit            _p_ previous        _i_ describe
  _M_ manual          _n_ next            _d_ disable
  _v_ verify setup    _f_ check           _m_ mode
  ^^                  _l_ list            _s_ select
  ^^                  ^^                  _D_ lsp default
  ^^                  ^^                  _L_ eslint
  ^^                  ^^                  _N_ next
  "
  ("q" nil)
  ("p" flycheck-previous-error :color pink)
  ("n" flycheck-next-error :color pink)
  ("i" flycheck-describe-checker)
  ("M" flycheck-manual)
  ("d" flycheck-disable-checker)
  ("f" flycheck-buffer)
  ("l" flycheck-list-errors)
  ("m" flycheck-mode)
  ("s" flycheck-select-checker)
  ("D" (flycheck-select-checker 'lsp))
  ("L" (flycheck-select-checker 'javascript-eslint))
  ("N" (flycheck-select-checker (ItemAfter flycheck-checker flycheck--automatically-enabled-checkers)))
  ("v" flycheck-verify-setup))

(defun ItemAfter (item lst)
  (princ item)
  (princ lst)
  (princ (cadr (member item lst)))
  (cadr (member item lst)))

Copitlot

Copilot.el is an Emacs plugin for GitHub Copilot.

Warning: This plugin is unofficial and based on binaries provided by copilot.vim.

Note: You need access to GitHub Copilot to use this plugin.

;; accept completion from copilot and fallback to company
(use-package! copilot
;;  :hook (prog-mode . copilot-mode)
  :bind (("S-TAB" . 'copilot-accept-completion-by-word)
         ("S-<tab>" . 'copilot-accept-completion-by-word)
         :map copilot-completion-map
         ("<tab>" . 'copilot-accept-completion)
         ("TAB" . 'copilot-accept-completion)))
(map! :leader
      (:prefix ("t" . "toggle")
       :desc "Toggle Copitlot" "p" #'copilot-mode))

ChatGPT

Translater

Brings quick an easy translations to Emacs with go-translate.

(use-package! go-translate)
(setq gts-translate-list '(("de" "en")))

(setq gts-default-translator
      (gts-translator
       :picker (gts-prompt-picker)
       :engines (list (gts-bing-engine) (gts-google-engine))
       :render (gts-posframe-pop-render)))

(map! :leader
      (:prefix ("T" . "Translate")
       :desc "Translate region" "r" #'gts-do-translate))

Anki

(use-package anki-editor
  :after org
;;              ("<f11>" . anki-editor-cloze-region-dont-incr)
;;              ("<f10>" . anki-editor-reset-cloze-number)
;;              ("<f9>"  . anki-editor-push-tree))
  :hook (org-capture-after-finalize . anki-editor-reset-cloze-number) ; Reset cloze-number after each capture.
  :config
  (setq anki-editor-create-decks t ;; Allow anki-editor to create a new deck if it doesn't exist
        anki-editor-org-tags-as-anki-tags t)

  (defun anki-editor-cloze-region-auto-incr (&optional arg)
    "Cloze region without hint and increase card number."
    (interactive)
    (anki-editor-cloze-region my-anki-editor-cloze-number "")
    (setq my-anki-editor-cloze-number (1+ my-anki-editor-cloze-number))
    (forward-sexp))
  (defun anki-editor-cloze-region-dont-incr (&optional arg)
    "Cloze region without hint using the previous card number."
    (interactive)
    (anki-editor-cloze-region (1- my-anki-editor-cloze-number) "")
    (forward-sexp))
  (defun anki-editor-reset-cloze-number (&optional arg)
    "Reset cloze number to ARG or 1"
    (interactive)
    (setq my-anki-editor-cloze-number (or arg 1)))
  (defun anki-editor-push-tree ()
    "Push all notes under a tree."
    (interactive)
    (anki-editor-push-notes '(4))
    (anki-editor-reset-cloze-number))
  ;; Initialize
  (anki-editor-reset-cloze-number)
)
(map! :leader
      (:prefix ("A" . "Anki")
       :desc "cloze region increase" "c" #'anki-editor-cloze-region-auto-incr
       :desc "cloze region no increase" "C" #'anki-editor-cloze-region-dont-incr
       :desc "reset cloze number" "r" #'anki-editor-reset-cloze-number
       :desc "push tree" "p" #'anki-editor-push-tree))

;; Org-capture templates
(setq org-my-anki-file "~/NextCloud/Documents/Org/Anki/anki-capture.org")
(add-to-list 'org-capture-templates
             '("a" "Anki basic"
               entry
               (file+headline org-my-anki-file "Dispatch Shelf")
               "* %<%H:%M>   %^g\n:PROPERTIES:\n:ANKI_NOTE_TYPE: Basic\n:ANKI_DECK: TestDeck\n:END:\n** Front\n%?\n** Back\n%x\n"))
(add-to-list 'org-capture-templates
             '("A" "Anki cloze"
               entry
               (file+headline org-my-anki-file "Dispatch Shelf")
               "* %<%H:%M>   %^g\n:PROPERTIES:\n:ANKI_NOTE_TYPE: Cloze\n:ANKI_DECK: TestDeck\n:END:\n** Text\n%x\n** Extra\n"))

;; Allow Emacs to access content from clipboard.
(setq x-select-enable-clipboard t
      x-select-enable-primary t)
;; frame that can be opened with WM
(defun make-orgcapture-frame ()
    "Create a new frame and run org-capture."
    (interactive)
    (make-frame '((name . "org-capture") (window-system . x)))
    (select-frame-by-name "org-capture")
    (counsel-org-capture)
    (delete-other-windows)
    )

Ace Jump

Ace jump mode is a minor mode of emacs, which help you to move the cursor within Emacs. You can move your cursor to ANY position ( across window and frame ) in emacs by using only 3 times key press.

(map! :leader
      (:prefix ("j" . "ace jump")
       :desc "jump line mode" "l" #'ace-jump-line-mode
       :desc "jump word mode" "w" #'ace-jump-word-mode
       :desc "jump char mode" "c" #'ace-jump-char-mode
       :desc "jump to previous point" "p" #'ace-jump-mode-pop-mark))

Fix?

Can’t remember what it was for 🙃

(after! projectile
  (setq projectile-project-root-files-bottom-up
        (remove ".git" projectile-project-root-files-bottom-up)))
(setq pdf-latex-command "lualatex")
(use-package vue-mode
  :mode "\\.vue\\'"
  :config
  (add-hook 'vue-mode-hook #'lsp))
(use-package color-identifiers-mode)
(add-hook 'after-init-hook 'global-color-identifiers-mode)

(setq redisplay-dont-pause t
  scroll-margin 1
  scroll-step 1
  scroll-conservatively 10000
  scroll-preserve-screen-position 1)

(setq lsp-volar-take-over-mode nil)