Skip to content

shawngerrard/emacs-setup

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

60 Commits
 
 
 
 
 
 
 
 

Repository files navigation

My DOOM EMACS setup guide

DOOM EMACS setup

A guide to installing and configuring my DOOM EMACS setup.

Pre-requisites

You need to ensure the following dependencies are installed to follow this guide successfully.

Installing EMACS

The first step is to install the base vanilla Gnu-EMACS application compatible with DOOM. For the purposes of this guide, we’ll be installing Gnu-EMACS version 28.1. At this point in time, the minimum required EMACS version is 27.1.

Note: You’ll need to review the DOOM prerequisites for EMACS to identify the EMACS versions compatible with DOOM.

Installing EMACS GUI

The recommended installation instructions for installing EMACS (and the GUI components) can be found on github,

Installing EMACS using the Ubuntu apt package manager

To get up and running quickly, you can install emacs using the apt package manager.

The general repositories used in Ubuntu 20.04 and 22.04 (focal, jammy, etc) run older versions of Emacs (26). These aren’t compatible with DOOM.

You will need to use a Personal Package Archive (PPA) to install a newer version of Emacs in Ubuntu. A recommended PPA is ‘kelleyk/emacs’ and can be added with the following:

sudo add-apt-repository ppa:kelleyk/emacs

Now we should be able to install a newer version of Emacs through the apt package manager.

sudo apt install emacs28

To uninstall emacs you’ll need to also remove all dependencies.

sudo apt-get remove emacs emacs28 emacs-bin-common emacs-common emacs-el && sudo apt autoremove

(Recommended) Installing EMACS by building from source

You’ll need the following packages installed to build the emacs source.

libncurses-dev libgnutls28-dev gnutls-bin pkg-config

Then, obtain the source code tarball for the specific version you want. In this case, we’re installing version 28.1.

wget https://ftp.gnu.org/gnu/emacs/emacs-28.1.tar.xz

Extract the source code from the tarball.

tar xvf emacs-28.1.tar.xz

Finally, configure, build, and install emacs using the scipts supplied with the source files.

cd emacs-28.1
./configure
sudo make
sudo make install

You should now be able to start emacs successfully.

Note: To uninstall emacs you can follow the step above but instead of sudo make install you can run sudo make uninstall

Installing DOOM

Run the following command to clone the DOOM configuration to your local computer:

git clone --depth 1 https://github.com/doomemacs/doomemacs ~/.config/emacs
~/.config/emacs/bin/doom install

Add the Emacs binary files to the PATH environment variable, if you haven’t already. You’ll need to add the following line to the bottom of your ​~/.bashrc configuration file:

export PATH="~/.config/emacs/bin:$PATH"

If you have any private emacs configuration to sync with DOOM, or if you’ve made changes to init.el or packages.el, you’ll need to run doom sync.

Finally, to run the new setup, use doom run in the terminal. You should be met with the DOOM landing screen.

Note: Visit the official DOOM GitHub repository for more information if you have any installation issues.

Alternative - Install DOOM and apply configuration to EMACS

You can find information on the DOOM configuration framework for emacs in the DOOMEMACS github repository.

It’s recommended that you ensure your system is up-to-date.

sudo apt update && sudo apt upgrade

Now, we clone the DOOM configuration from git into the $HOME/emacs.d directory, and use the doom install function from the binary.

git clone https://github.com/hlissner/doom-emacs ~/.emacs.d
~/.emacs.d/bin/doom install

Note: Ensure that you have an SSH authentication key-pair loaded into git and the local ssh-agent. You may need to add this code to your bashrc configuration.

You should be able to run doom doctor to diagnose any problems associated with an installation or with the system configuration.

The next time you open emacs, your DOOM configuration should be loaded.

Customizations

I’ve added customizations and modules to EMACS that are helpful in my workflow. Consult the sections below for updating your Emacs world.

Configuration

My configuration for DOOM can be copied into the ​~/.config/doom folder to retain all config below. Alternatively, assuming this repository resides within ​~/documents, you can execute the following code to use symlinks instead:

ln -s ~/documents/emacs-setup/.config/doom/config.el ~/.config/doom/config.el
ln -s ~/documents/emacs-setup/.config/doom/init.el ~/.config/doom/init.el
ln -s ~/documents/emacs-setup/.config/doom/packages.el ~/.config/doom/packages.el
cp ~/documents/emacs-setup/.config/doom/custom.el ~/.config/doom/custom.el

**Note:** You will notice that custom.el is not created as a symlink but is instead copied directly to the .config folder. This is so that any custom changes per each device made in this repository do not create a conflict with each other, as a git pull will override settings in symoblically linked files.

Packages

For some custom packages/EmacsLisp files that I want EMACS to load, I’ve created the directory ​~/packages to hold these files.

Then, to ensure that the packages will be recognized by EMACS when it initializes, we add the following line to ​~/.config/doom/config.el:

(let ((default-directory (expand-file-name "~/packages/")))
  (normal-top-level-add-subdirs-to-load-path))

This allows us to add the ​~/packages directory and all sub-directories to the Emacs load-path

Theme

I replace the doom-theme variable in config.el with the following:

(setq doom-theme 'doom-horizon)

I also create a custom.el file with the following code:

(custom-set-faces
 '(font-lock-comment-face ((t (:foreground "color-173" :slant italic)))))

This will update some of the font faces that are harder to see with my setup.

Org-Agenda

I’ve made an update to ​~/.config/doom/init.el to change the directory that org-agenda uses to find TODO items (​~/documents/*).

At the bottom of the init.el file, I’ve inserted the following code:

(setq org-agenda-files (directory-files-recursively "~/documents/" "\\.org$"))

Restart DOOMEMACS to apply changes. When prompted, select n to avoid importing variables from other org files outside of this directory.

Org-Roam

I use org-roam as a mind-mapping tool and as a local knowledge-base. I.E - my second-brain.

First, we must create a folder to hold our .org roam files. For this, I clone/pull second-brain from my private git repo. mkdir somewhere will work just as well.

git clone git@github.com:shawngerrard/second-brain.git ~/documents/second-brain

Installing org-roam in DOOM as is simple as opening init.el and updating the :lang org package to pass in the roam flags. We do this by replacing org in init.el to (org +roam2).

Note: Using the DOOM org-roam package will “pin” the package at a specific commit - this is so that DOOM can maintain stability. If you use org-roam-ui (as I do - see below!), you may need to bump the org-roam package to keep up with the org-roam-ui updates. You can do this by using M-x doom/bump-package-at-point (with your cursor over the package! statement in packages.el). This will generate a :pin with the the latest commit for the package, which should save you the trouble of guessing where every package is installed.

We must also update our config.el file with the following:

(setq org-roam-directory (file-truename "~/documents/second-brain/"))
(setq find-file-visit-truename t)
(org-roam-db-autosync-mode)

Note: The above code will set the scanning roam directory for .org files to ​~/documents/second-brain/. You can set this to any other directory as you wish. The next line will instruct Emacs to resolve symlinks. The final line ensures that org-roam syncs file changes with its cache (sqlite3).

Now, run doom sync -u to reload your configuration. You should be able to view the org-roam command menu in Doom by pressing SPC n r.

Please review SystemCrafter’s useful video to learn how to use org-roam.

Org-Roam capture templates

In the second-brain repository, I make use of org-roam-capture templates. These allow me to create similar org-roam nodes with a consistent structure, as well as speed-up the process of creating nodes.

To do this, we need to update our init.el with the following:

(setq org-roam-capture-templates
      '(("d" "default" plain
         "%?"
         :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+Title: ${title}\n")
         :unnarrowed t)
        ("p" "exo-planets" plain (file "~/documents/second-brain/templates/exoplanet.org")
          :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+Title: ${title}\n")
          :unnarrowed t)
        )
      )

Note: We keep the “default” setting to ensure that we can continue to create blank nodes.

Note: Please ensure that the filepath in the form above is pointing to the correct template according to your system.

Org-Roam-UI

Org-roam-ui is a fantastic front-end UI for exploring my org-roam second-brain.

https://github.com/shawngerrard/emacs-setup/blob/main/org-roam-ui-example.png

For information relating to this org-roam UI overlay, visit the org-roam-ui github repository.

To install, because we use Doom we must first unpin the org-roam package. This is because org-roam-ui tries to keep up with the latest features of org-roam. We also must enable the org-roam-ui package. We can do all of this in our packages.el with the following:

(unpin! org-roam)
(package! org-roam-ui)

We must then update our config.el to use the websocket package and the org-roam-ui package. Doing this will install a local server where we can interrogate our second-brain in a UI rendered in our default browser. Update config.el with the following:

(use-package! websocket
      :after org-roam)

(use-package! org-roam-ui
  :after org-roam ;; or :after org
;;         normally we'd recommend hooking orui after org-roam, but since org-roam does not have
;;         a hookable mode anymore, you're advised to pick something yourself
;;         if you don't care about startup time, use
;;  :hook (after-init . org-roam-ui-mode)
  :config
  (setq org-roam-ui-sync-theme t
        org-roam-ui-follow t
        org-roam-ui-update-on-save t
        org-roam-ui-open-on-start t))

Finally, run doom sync -u to install the packages.

Finally, once the sync is complete, we must do the following to access our swish org-roam-ui:

  • Start our local webserver with the following command: M-x org-roam-ui-mode RET
  • Access http://127.0.0.1:35901/ to view our UI served from our local webserver.

NOTE: While the org-roam-ui-mode is enabled, the websocket should interpret changes to our org-roam nodes and update the UI in real-time.

Fountain mode

I use Fountain mode as my main screenwriting program in EMACS. For more information about Fountain mode, visit https://fountain.io.

Make sure to refer to the documentation regarding syntax formatting for .fountain files.

To install:

  1. Clone the Fountain mode files into the ​~/packages directory.
    git clone git@github.com:rnkn/fountain-mode.git ~/packages/fountain-mode
        
  2. Add the following line to ​~/.config/doom/config.el:
    (require 'fountain-mode)
        
  3. Restart EMACS.
  4. Test the file by opening a .fountain file.

    You can download a sample .fountain file with the following command: wget https://fountain.io/_downloads/Big-Fish.fountain

VTerm

I use vterm as a terminal emulation application within DOOM.

Installing vterm

This can be installed pretty easily by uncommenting the vterm line in init.el and running doom sync, however if you attempt to use vterm (M-x vterm) you’ll be asked to compile the application first.

Note: If you encounter an error advising you to install libtools, you can run the following command in the terminal.

# Install libtools-bin and cmake
sudo apt-get install libtool-bin cmake
  

Starting vterm during DOOM startup

I’ve added a hook into init.el to append the application to the window-setup-hook variable so it starts when DOOM launches.

;; Hook to start vterm automatically during DOOM startup
(add-hook 'window-setup-hook #'vterm 'append)

Treemacs

I use treemacs to add a drawer-style UI to DOOM, similar to VS Code.

Installing treemacs

This can be installed by uncommenting the treemacs line in init.el and running doom sync.

Opening the treemacs drawer

You can open the treemacs drawer by using M-X treemacs.

Configuring treemacs

Configuring the active workspace to display

By default, I prefer treemacs to open my documents folder in the workspace.

To do this, press M-x treemacs-edit-workspaces. We can add multiple projects/folders to the workspace by putting the definition ​~/documents under the perspectives heading.

Configuring icons / font

By default, typically the icons in treemacs cannot be found, resulting in malformed icons.

To allow the correct icons to show, we must do the following:

  1. Download and extract a nerd-font from the official nerd-font website. I use the JetBrainsMono font.
    # Download the JetBrainsMono font
    wget https://github.com/ryanoasis/nerd-fonts/releases/download/v3.1.1/JetBrainsMono.zip
    
    # Unzip the font files into a subdirectory called JetBrainsMono
    unzip JetBrainsMono.zip -d ./JetBrainsMono
        
  2. Install the fonts.

    If using Windows or WSL, right-click and select install. You will also need to use the windows terminal settings to update the fonts. Pressing CTRL+COMMA in Windows 11 will open the settings menu, otherwise click on the icon in the top-left of the terminal window and select preferences. Update the font-face setting found in the left-hand menu Profiles > Defaults then click appearance.

    If using Ubuntu, fonts are typically installed in the user font directory under ​~/.local/share. To do this, we must perform the following:

    # Create the directory under /.local/share
    mkdir ~/.local/share/fonts
    
    # Move the fonts into the new directory above
    mv /path/to/extracted/fonts/* ~/.local/share/fonts/
        
  3. Install the fonts into DOOM using M-x install-package nerd-icons
  4. Update config.el with the following:
    ;; Use the nerd-icons package
    (require 'nerd-icons)
    
    ;; Install the package into treemacs
    (use-package treemacs-nerd-icons
      :config
      (treemacs-load-theme "nerd-icons"))
    
    ;; Configure treemacs to use a specific nerd-font
    (setq nerd-icons-font-family "JetBrainsMono Nerd Font Mono")
        
  5. If the icons are still not showing, the icons have not been installed correctly in step 2. You may need to run M-x nerd-icons-install-fonts RET to ensure that these are installed into the correct directory, particularly if using the wslg GUI version of emacs.

Using treemacs

Documentation for treemacs can be found in the offcial github page.

Help within treemacs

You can open a hydra containing option keys you can use from within the treemacs drawer. You need to change to the treemacs window and use the ? key.

Starting treemacs during DOOM startup

I’ve added a hook into init.el to append the application to the window-setup-hook variable so it starts when DOOM launches.

;; Hook to start treemacs automatically during DOOM startup
(add-hook 'window-setup-hook #'treemacs 'append)

Integrated development environment (IDE)

The next sections under this heading will step through the applications I use to set up an IDE within DOOM.

Language Server Protocol (LSP)

lsp is a standardized protocol developed by Microsoft that acts as an interpreter in an IDE and communicates with language servers to provide “language intelligence tools”, such as intelli-sense.

You need to install LSP into DOOM as well as a language server for the particular language you want to provide support for.

LSP installation

It comes out-of-the-box with DOOM and can be installed by uncommenting :tools lsp in your init.el.

You also need to indicate which languages should use lsp. You can do this by updating the specific language in init.el under :lang, as per the following examples:

  • (go +lsp)
  • (python +lsp)

If your language isn’t supported (I.E doesn’t contain a +lsp entry in init.el), then you can add a hook in either config.el or init.el.

(add-hook 'MAJOR-MODE-local-vars-hook #'lsp!)

Note: Change MAJOR-MODE to the major-mode you’re targeting, E.G - typescript-mode.

Make sure to run doom sync after these changes.

Language server installation (Typescript)

You’ll need to install the server package globally on your system. I use typescript, so I install the typescript-language-server through npm.

# Install typescript-language-server
npm install -g typescript-language-server typescript

Then, I can install the appropriate language server in DOOM using M-x lsp-install-server.

Using typescript as an example, use ts-ls (Typescript Language Server) for supporting ts code - M-x lsp-install-server RET ts-ls RET.

DOOM will then ask you to select the project directory that the language server should import. Usually the project directory for typescript projects is the directory that contains tsconfig.json.

Language server installation (YAML)

You can install the YAML language server by using npm:

# Install yaml-language-server
npm install -g yaml-language-server

Then run the Emacs installer with: M-x lsp-install-server RET yamlls RET.

Language server installation (Terraform)

Install `terraform-mode` from MELPA:

M-x package-install terraform-mode

Install `terraform-ls` language server from the HashiCorp repository:

# Download the HashiCorp signing key to the apt keyring
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg

# Verify the key fingerprint
gpg --no-default-keyring --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg --fingerprint

# Add the HashiCorp apt repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list

# Update the repository and install terraform-ls from apt
sudo apt update && sudo apt install terraform-ls

Add the package hook for `terraform-mode` to start when `.tf` files are opened into `config.el`:

(use-package terraform-mode
  :mode ("\\.tf\\'" "\\.tfvars\\'")
  :hook (terraform-mode . lsp-deferred)
  :config
  (setq terraform-indent-level 2))

Debug Adapter Protocol (DAP)

Similar to lsp, dap is a standardised protocol developed by Microsoft that integrates our IDE client (DOOM) with debug servers to provide debugging capabilities to IDE’s.

We need to install dap into DOOM and also configure it to integrate with our specific language debug servers (I.E typescript, C#, etc).

DAP-mode installation

To use DAP, we must install dap-mode.

Note: It’s possible to use MELPA M-x package-install to install dap-mode, however I had issues with configuring this so have opted to use DOOM’s package management system.

Insert the following code into your packages.el file.

(package! dap-mode)

Insert the following code into your config.el file.

(use-package! dap-mode)

Run doom sync to ensure installation.

Typescript debug server configuration/integration

Below is the basic configuration to use in config.el to configure dap-mode for use with typescript files by:

  1. Enabling typescript-mode major mode when a .ts buffer is created.
  2. Starting lsp when entering typsescript-mode.
  3. Starting and configuring dap-node for typescript debugging when entering typescript-mode.
(use-package! typescript-mode
  :mode "\\.ts\\'"
  :hook (typescript-mode lsp-deferred)
  :config
  (setq typescript-indent-level 2)
  (require 'dap-node)
  (dap-node-setup))

Useful DOOM keybinds

By default, I run DOOMEMACS in evil mode, which means that keybinds in EMACS emulate vi/vim keybinds.

Legend for US Keyboard layout

  • M- is short for “Meta key” and is bound to ALT
  • C- is short for “Control key” and is bound to CTRL
  • S- is short for “Super key” and is bound to SHIFT
  • SPC- is known as a “Leader” key:
    • In evil-mode this is bound to SPC.

    Note: You must change to evil-mode to use the leader key in DOOMEMACS.

    Note: SPC-u is bound to universal-argument which is used to input into many commands, such as shrinking/enlarging windows/buffers. The traditional equivalent in EMACS is C-u.

Custom keybinds

I’ve created custom keybindings for certain actions in DOOM that make life a little easier.

lsp-describe-thing-at-point

This lsp function describes a keyword/symbol/function/etc in DOOM by pulling up the documentation of it from the official SDK.

I’ve mapped this keybinding as follows:

(global-set-key "\C-c d" lsp-describe-thing-at-point)

Note: This only works when lsp-mode is enabled, I.E when we’re in an IDE file (E.G - .ts, .py, etc).

Keybinds

Disable evil-mode

Rationale: Some of the descriptions in documentation (such as SPC-h or M-x) for DOOMEMACS are intended for SPACEMACS users rather than vi/vim users, which can be confusing as simple keybinds for killing/yanking etc are different from what is stated.

Easiest way to disable evil-mode is to toggle is with: M-x evil-mode

Note: This will only toggle evil-mode for the current EMACS session. To disable evil-mode permanently, refer to the StackExchange forum post: https://emacs.stackexchange.com/questions/53319/how-to-disable-evil-mode-everywhere

Insert a link snippet (E.G - a URL)

Insert a URL with C-c C-l and paste in the URL.

Kill/yank commands

I prefer using the mark functionality to select text. You can set a mark by using C-SPC, then use your left/right keys to highlight the text you want to manipulate.

Then, press any of the operations as per below to operate over the text accordingly.

Evil mode
  • Copy: y
  • Cut: d
  • Paste: P or S-p
Default mode
  • Copy: M-w
  • Cut: C-w
  • Paste: C-y
  • Kill rest of line: C-k

Insert an escape character

Rationale: When inserting a file path into the start of a code block, such as ​~/documents/, this can create formatting issues when the org file is rendered, requiring us to place an escape character beside the initial tilde.

Insert a zero width space beside the first tilde with C-x 8 <RET> zero width space <RET>.

Traverse org-mode headings

  • Move to the parent heading: C-c C-u
  • Move to the prev heading: C-c C-p
  • Move to the next heading: C-c C-n
  • Move to the prev heading on the same level: C-c C-b
  • Move to the next heading on the same level: C-c C-f

Shrink/Enlarge windows

  • Shrink a window to fit its content: C-x -
  • Shrink or enlarge a window by an argument value (negative values shrink): SPC-u <value> C-x ^

Org-mode shortcuts

You can shortcut some useful EMACS commands in org-mode by inserting certain characters and pressing keys.

Insert a code snippet

You can create a code snippet in an org file by prefixing with <s and pressing tab.

Insert a quote block

You can create a quote block in an org file by prefixing with <q and pressing tab.

About

A guide to installing and configuring my EMACS setup.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published