Skip to content

Latest commit

Β 

History

History
774 lines (732 loc) Β· 20.9 KB

File metadata and controls

774 lines (732 loc) Β· 20.9 KB

Rameez’s Emacs Config

Introduction

I’ve declared configuration bankruptcy many times before this. Here’s to hoping a literate configuration sticks.

Disable Native Comp Warnings

With native comp enabled there tends to be a lot of annoying warnings. To not go insane I’ll turn this off.

(defvar native-comp-deferred-compilation-deny-list nil)
(setq comp-async-report-warnings-errors nil)

Server

Start emacs-server on Emacs boot

Start the emacs server so emacsclient can connect to it.

(server-start)

Package Management

straight.el

I use straight.el to manage my packages.

Enable straight to use use-package by default before bootstrapping.

(setq straight-use-package-by-default t)

We bootstrap straight.el with the following.

(defvar bootstrap-version)
(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 5))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
        (url-retrieve-synchronously
         "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
         'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (load bootstrap-file nil 'nomessage))

I use the use-package straight integration to make switching back to use-package easier. First we install use-package with straight.el.

(straight-use-package 'use-package)

Read PATH properly

(use-package exec-path-from-shell
  :config
  (setq exec-path-from-shell-variables '("PATH" "SHELL"))
  (exec-path-from-shell-initialize))

Interface

Startup Message

Disable startup message.

(setq inhibit-startup-message t)

Scrollbar

Disable the scrollbar

(scroll-bar-mode -1)

Toolbar

Disable the toolbar

(tool-bar-mode -1)

Menu bar

Disable the menu bar.

(menu-bar-mode -1)

Font

(set-face-attribute 'default nil :font "JetbrainsMono Nerd Font" :height 180)

Theme

Doom Themes

I like Doom Themes because they offer the best integration with various syntaxes.

;; (use-package doom-themes
;;   :config
;;   ;; Global settings (defaults)
;;   (setq doom-themes-enable-bold t    ; if nil, bold is universally disabled
;;         doom-themes-enable-italic t) ; if nil, italics is universally disabled
;;   ;;(load-theme 'doom-gruvbox t)

;;   ;; Enable flashing mode-line on errors
;;   (doom-themes-visual-bell-config)
;;   ;; Corrects (and improves) org-mode's native fontification.
;;   (doom-themes-org-config))

Zenburn

The GOAT.

;; (use-package zenburn-theme
;;   :config
;;   (setq zenburn-use-variable-pitch t)
;;   ;; scale headings in org-mode
;;   (setq zenburn-scale-org-headlines t)
;;   ;; scale headings in outline-mode
;;   (setq zenburn-scale-outline-headlines t)
  
;;   ;; enable theme
;;   (load-theme 'zenburn t))

Poet

;; (use-package poet-theme
;;   :config
;;   ;; enable theme
;;   (load-theme 'poet t))

Ef-themes

See here.

(use-package ef-themes
  :config
  (setq ef-themes-to-toggle '(ef-summer ef-winter))
  (setq ef-themes-headings ; read the manual's entry or the doc string
        '((0 . (variable-pitch light 1.9))
          (1 . (variable-pitch light 1.8))
          (2 . (variable-pitch regular 1.7))
          (3 . (variable-pitch regular 1.6))
          (4 . (variable-pitch regular 1.5))
          (5 . (variable-pitch 1.4)) ; absence of weight means `bold'
          (6 . (variable-pitch 1.3))
          (7 . (variable-pitch 1.2))
          (t . (variable-pitch 1.1))))
  (setq ef-themes-mixed-fonts t
        ef-themes-variable-pitch-ui t)
  (mapc #'disable-theme custom-enabled-themes)
  (load-theme 'ef-winter :no-confirm))

Modeline

Doom Modeline

(use-package doom-modeline
  :config
  (doom-modeline-mode 1))

Keybinding panel

which-key

which-key is great for getting an overview of what keybindings are available.

(use-package which-key
  :init (which-key-mode)
  :diminish which-key-mode
  :config
  (setq which-key-idle-delay 0.3))

Startup Screen

emacs-dashboard

(use-package page-break-lines)

(use-package dashboard
  :ensure t
  :config
  (dashboard-setup-startup-hook))

Keybindings

Setup

Evil

For undo/redo to work nicely with Evil mode we use undo-tree.

(use-package undo-tree
  :ensure t
  :after evil
  :diminish
  :config
  (evil-set-undo-system 'undo-tree)
  (global-undo-tree-mode 1))   

I grew up on Vim keybindings, so Evil at heart.

(use-package evil
  :init
  (setq evil-want-integration t)
  (setq evil-want-keybinding nil)
  :config
  (evil-mode t)
  (with-eval-after-load 'evil-maps
    (define-key evil-motion-state-map (kbd "RET") nil))
  (fset 'evil-visual-update-x-selection 'ignore))

We also install evil-collection so other modes in Emacs work too. These include magit, calendar etc.

(use-package evil-collection
  :after evil
  :config
  (evil-collection-init))

evil-commentary provides a simular gcc keybinding as in Vim.

(use-package evil-commentary
  :config
  (evil-commentary-mode))

Get a Vim surround equivalent.

(use-package evil-surround
  :after (evil)
  :config
  (global-evil-surround-mode 1))

Use Evil in org-mode and org-mode agenda. For keybindings see here.

(use-package evil-org
  :ensure t
  :after org
  :hook (org-mode . (lambda () evil-org-mode))
  :config
  (require 'evil-org-agenda)
  (evil-org-agenda-set-keys))

General

I use general to define various keymaps based on different modes. I also define a handy function to define various leader key mappings.

(use-package general
  :config
  (general-evil-setup t)
  
  (general-create-definer rkn/keymap-define-global
    :keymaps '(normal insert visual emacs)
    :prefix "SPC"
    :global-prefix "M-SPC")
  
  (general-create-definer rkn/keymap-define-map
    :states '(normal)
    :prefix "SPC"
    :global-prefix "M-SPC"
    :major-modes t))

Applications

Spell Checking

aspell

Set ispell to use the aspell binary.

(setq ispell-program-name "aspell")

Syntax Checking

Flycheck

(use-package flycheck
  :ensure t
  :init (global-flycheck-mode))

Projects

Projectile

For jumping between git projects quickly.

(use-package projectile
  :diminish projectile-mode
  :config
  (projectile-mode))

Completions

Vertico

Use a lightweight completion engine such as vertico.

(use-package vertico
  :init
  (vertico-mode)
  
  ;; Wrap around list
  (setq vertico-cycle t)
  )

Orderless

Combine vertico with orderless for better completion typing. Typing a SPC after a completion narrows down a list some more.

(use-package orderless
  :init
  (setq completion-styles '(orderless)
        completion-category-defaults nil
        completion-category-overrides '((file (styles . (partial-completion))))))

Save History

This puts your last used command/completion to the top of the list.

(use-package savehist
  :init
  (savehist-mode))

Consult

Consult provides some extra completion for built-in emacs functions.

(use-package consult
  :init
  (setq consult-project-root-function #'projectile-project-root)

  :config
  (setq consult-find-args (concat "find . "
				  "-not ( -wholename */.git/* -prune ) "
				  "-not ( -wholename */.venv/* -prune ) ")))

Marginalia

Provides helpful annotations to commands/functions. For files it also displays file permissions etc.

(use-package marginalia
  :init
  (marginalia-mode))

Icons

For some pretty eye candy.

After installation you need to install icon fonts with:

M-x all-the-icons-install-fonts

(use-package all-the-icons
  :if (display-graphic-p))

(use-package all-the-icons-completion
  :init
  (all-the-icons-completion-mode)
  (add-hook 'marginalia-mode-hook #'all-the-icons-completion-marginalia-setup))

Company

Company is a text completion framework for Emacs. It stands for β€œCOMplete ANYthing”.

(use-package company
  :config
  (global-company-mode))

LSP

lsp-mode

(use-package lsp-mode
  :init
  ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
  (setq lsp-keymap-prefix "C-c l")
  :hook ((lsp-mode . lsp-enable-which-key-integration))
  :commands lsp)

lsp-ui

(use-package lsp-ui :commands lsp-ui-mode)

VCS

Git

Magit

(use-package magit)

GPG

Allow emacs to ask for GPG password.

(use-package pinentry
  :config
  
  (setq epa-pinentry-mode 'loopback)
  (pinentry-start))

Languages

Org

Org-Mode

I use org-mode for managing this config and for tending to my Digital Garden.

(use-package org)

Fix source block indentation

This fixes the strange indentation in src blocks after hitting the return key in org files.

(setq org-edit-src-content-indentation 0
      org-src-tab-acts-natively t
      org-src-preserve-indentation t)

Enable word wrapping

Enable word and line wrapping in org-mode using visual mode

(add-hook 'org-mode-hook 'visual-line-mode)

Additional TODO keywords

(setq org-todo-keywords
      '((sequence "TODO" "BLOCKED" "DONE")))

(setq org-todo-keyword-faces
      '(("TODO" . org-warning)
	("BLOCKED" . "red")))

Capture Templates

(setq current-journal-file (expand-file-name (format-time-string "~/Dropbox/DigitalGarden/journals/%Y-%m-%b.org")))

(setq org-capture-templates
      '(("p" "Day Planning" entry (file+olp+datetree current-journal-file)
"* Day Planning %U
** Thoughts / diary / fleeting notes
** Tasks for today [/]
*** TODO %?
** Tasks that will satisfy end-of-the-day me [/]
** Focus Blocks
** Habits [/]
- [ ] Are you satisfied with the number of pomodori?
- [ ] Did you tend to your Digital Garden?")))

Better org-mode bullets

I use org-superstar to make a bullets and sections look less ugly.

(use-package org-superstar
  :after (org)
  :config
  (setq org-superstar-leading-bullet ?\s
        org-superstar-leading-fallback ?\s
        org-hide-leading-stars nil
        org-superstar-todo-bullet-alist
        '(("TODO" . 9744)
          ("[ ]"  . 9744)
          ("DONE" . 9745)
          ("[X]"  . 9745)))
  :hook
  (org-mode . (lambda () (org-superstar-mode 1))))

Autolist

(use-package org-autolist
  :config
  (add-hook 'org-mode-hook (lambda () (org-autolist-mode))))  

Headings Startup Visibility

Sometimes my org file are too long and I’d like to open them with headings collapsed.

(setq org-startup-folded t)

Spell checking

Enable spell checking in org-mode.

(add-hook 'org-mode-hook 'flyspell-mode)

Fix stupid bookmark-fontify

Sometimes my org-capture’s would have an ugly coloring.

(setq bookmark-fontify nil)

Centre org-mode for a nice writing experience

I use Olivetti for this

(use-package olivetti)

Allow the enter key to follow links

The below variable needs to be in order to allow for RET to follow a link. If you are using Evil (like I am) you also need to unbind RET from Evil. This shouldn’t matter since RET is not bound to anything useful anyway.

(setq org-return-follows-link t)

Turn on indent mode everywhere

(setq org-startup-indented t)

Babel

Tangling

Languages to tangle

In order to tangle certain languages we code blocks we need to define the following:

(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (python . t)))
Auto-tangling

To enable auto-tangling on save we define a custom function.

(defun rkn/org-babel-tangle-dont-ask ()
  (when (string-equal (buffer-file-name) (expand-file-name "~/.config/dotfiles/modules/editors/emacs/config/emacs.org"))
    (let ((org-confirm-babel-evaluate nil))
      (org-babel-tangle))))

We then invoke this function as an org-mode-hook.

(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'rkn/org-babel-tangle-dont-ask
                                              'run-at-end 'only-in-org-mode)))

Org-Pomodoro

(use-package org-pomodoro)

Org-Agenda

Custom Agenda Views

Helpful to see what I’ve been working on or plan to work on.

(setq org-agenda-custom-commands
      '(
	("c" . "My Custom Agendas")

	("cu" "Unscheduled TODO"
	 ((todo ""
		((org-agenda-overriding-header "\nUnscheduled TODO")
		 (org-agenda-skip-function '(org-agenda-skip-entry-if 'timestamp)))))
	 nil
	 nil)

	("cw" "Weekly Review"
	 ((agenda ""
		  ((org-agenda-start-day "-7d")
		   (org-agenda-span 14)
		   (org-agenda-start-on-weekday 1)
		   (org-agenda-archives-mode t)))
	  (alltodo "")))

	("n" "Agenda and all TODOs"
	 ((agenda #1="")
	  (alltodo #1#)))))

Clojure

Clojure-Mode

(use-package clojure-mode
  :after (flycheck-clj-kondo)
  :ensure t
  :config
  (require 'flycheck-clj-kondo)
  (add-hook 'clojure-mode-hook 'enable-paredit-mode)
  (add-hook 'clojure-mode-hook 'lsp)
  (add-hook 'clojurescript-mode-hook 'enable-paredit-mode)
  (add-hook 'clojurescript-mode-hook 'lsp)
  (add-hook 'clojurec-mode-hook 'lsp)

  (setq clojure-indent-style 'align-arguments)
  (setq clojure-align-forms-automatically t)

  (setq gc-cons-threshold (* 100 1024 1024)
        read-process-output-max (* 1024 1024)
        treemacs-space-between-root-nodes nil
        company-minimum-prefix-length 1
        lsp-lens-enable t
        lsp-signature-auto-activate nil
                                        ; lsp-enable-indentation nil ; uncomment to use cider indentation instead of lsp
                                        ; lsp-enable-completion-at-point nil ; uncomment to use cider completion instead of lsp
        ))

clj-kondo

(use-package flycheck-clj-kondo)

Cider

(use-package cider)

clj-refactor

(use-package clj-refactor
  :ensure t
  :init
  (add-hook 'clojure-mode-hook 'clj-refactor-mode)
  (add-hook 'clojurescript-mode-hook 'clj-refactor-mode)
  :diminish clj-refactor-mode)

Aggressive-Indent mode

(use-package aggressive-indent
  :config
  (add-hook 'clojure-mode-hook #'aggressive-indent-mode)
  (add-hook 'clojurescript-mode-hook #'aggressive-indent-mode))

rainbow-delimiters

(use-package rainbow-delimiters
  :ensure t
  :init
  (add-hook 'clojure-mode-hook 'rainbow-delimiters-mode)
  (add-hook 'clojurescript-mode-hook 'rainbow-delimiters-mode)
  :diminish rainbow-delimiters-mode)

lispyville

(use-package lispyville
  :after (org)
  :init
  (general-add-hook '(emacs-lisp-mode-hook lisp-mode-hook clojure-mode-hook clojurescript-mode-hook) #'lispyville-mode)
  :config
  (lispyville-set-key-theme '(operators c-w additional commentary slurp/barf-cp)))

Docker

(use-package dockerfile-mode
  :mode "Dockerfile\\'")

Markdown

(use-package markdown-mode
  :commands (markdown-mode gfm-mode)
  :mode (("README\\.md\\'" . gfm-mode)
         ("\\.md\\'" . markdown-mode)
         ("\\.markdown\\'" . markdown-mode))
  :init (setq markdown-command "multimarkdown"))

Enable word wrapping

Enable word and line wrapping in markdown modes using visual mode

(add-hook 'markdown-mode-hook 'visual-line-mode)
(add-hook 'gfm-mode-hook 'visual-line-mode)

Spell checking

Enable spell checking in markdown-mode.

(add-hook 'markdown-mode-hook 'flyspell-mode)

Python

Use PyRight for Python LSP

(use-package lsp-pyright
  :ensure t
  :hook (python-mode . (lambda ()
                         (require 'lsp-pyright)
                         (lsp))))  ; or lsp-deferred

Auto Formatting using Black

(use-package python-black
  :demand t
  :after python
  :hook (python-mode . python-black-on-save-mode))

Pipenv

Pipfile should use conf-toml-mode.

(add-to-list 'auto-mode-alist '("\\Pipfile\\'" . conf-toml-mode))

Yaml

(use-package yaml-mode
  :mode "\\.(yml|yaml)\\'")

Rust

rustic

(use-package rustic)

Terraform

terraform-mode

(use-package terraform-mode)

Nim

nim-mode

(use-package nim-mode
  :ensure t
  :hook
  (nim-mode . lsp))

Nix

(use-package nix-mode
  :mode "\\.nix\\'"
  :config
  (setq nix-nixfmt-bin "~/.nix-profile/bin/nixfmt"))

Custom Keymaps

Keymaps

Global

File

Handy keymaps for handling files.

(defun rkn/reload-emacs-config()
  (interactive)
  (load-file user-init-file))

(rkn/keymap-define-global
  ;; grep current file quickly
  "/" 'consult-line
  
  "f" '(:ignore t :which-key "file")
  "f f" 'find-file
  "f d" '(:ignore t :which-key "dot")
  "f d e" '((lambda() (interactive)(find-file "~/.config/dotfiles/modules/editors/emacs/config/emacs.org")) :which-key "dot-edit")
  "f d i" '((lambda() (interactive)(find-file user-init-file)) :which-key "dot-edit")
  "f d r" '((lambda() (interactive)(rkn/reload-emacs-config)) :which-key "reload-emacs-config")
  "f d R" '((lambda() (interactive)(shell-command "dot rebuild")(rkn/reload-emacs-config)) :which-key "reload-dotfiles"))

Git

Git operations

(rkn/keymap-define-global
  ;; grep current file quickly
  "g" '(:ignore t :which-key "git")
  "g g" 'magit-status
  "g b" 'magit-blame)

Projects

Handing switching between projects, finding files in projects etc.

(rkn/keymap-define-global
  ;; grep current file quickly
  "p" '(:ignore t :which-key "project")
  "p p" 'projectile-switch-project
  "p s" 'consult-ripgrep
  "SPC" 'consult-find)

Buffers

Quick keybindings for dealing with buffers.

(rkn/keymap-define-global
  "b" '(:ignore t :which-key "buffer")
  "bb" 'consult-buffer)

Company

(general-define-key
 "C-SPC" 'company-complete)

Agenda

This includes only org-agenda for now.

(rkn/keymap-define-global
  "a" 'org-agenda)

Toggles

Global interface toggles.

(rkn/keymap-define-global
  "t" '(:ignore t :which-key "toggle")
  "tt" 'ef-themes-toggle
  "tf" 'toggle-frame-fullscreen
  "tl" 'linum-mode)

Org-Mode

(rkn/keymap-define-map
  :keymaps 'org-mode-map
  "m" '(:ignore t :which-key "org")
  "m SPC" 'consult-outline
  "m c" '(:ignore t :which-key "clock")
  "m c i" 'org-clock-in
  "m c o" 'org-clock-out
  "m e" '(:ignore t :which-key "edit")
  "m e s" 'org-edit-src-code)

Clojure-Mode

(rkn/keymap-define-map
  :keymaps 'clojure-mode-map 
  "m" '(:ignore t :which-key "clojure")
  ;; cider
  "m c" '(:ignore t :which-key "cider")
  "m c c" 'cider-connect-clj
  "m c s" 'cider-connect-cljs
  "m e" '(:ignore t :which-key "eval")
  "m e e" 'cider-eval-last-sexp
  "m e c" 'cider-eval-defun-to-comment
  "m r" '(:ignore t :which-key "repl")
  "m r n" 'cider-repl-set-ns)

Nix-Mode

(rkn/keymap-define-map
  :keymaps 'nix-mode-map
  "m" '(:ignore t :which-key "nix")
  "m f" 'nix-format-buffer)